From b4a04898bf759a2091f2257b253a1d6a6cafe506 Mon Sep 17 00:00:00 2001 From: Mario Date: Mon, 10 Feb 2025 15:03:46 +1000 Subject: [PATCH] Add nukes --- mod/quake/common/_all.inc | 1 + mod/quake/common/_all.qh | 1 + mod/quake/common/effects/all.inc | 2 + mod/quake/common/effects/qc/_mod.inc | 2 + mod/quake/common/effects/qc/_mod.qh | 2 + mod/quake/common/effects/qc/modeleffects.qc | 146 ++++++++++++++ mod/quake/common/effects/qc/modeleffects.qh | 5 + mod/quake/common/notifications/all.inc | 2 + .../common/triggers/trigger/earthquake.qc | 4 +- mod/quake/common/weapons/all.inc | 1 + mod/quake/common/weapons/all.qh | 6 +- mod/quake/common/weapons/weapon/_mod.inc | 1 + mod/quake/common/weapons/weapon/_mod.qh | 1 + mod/quake/common/weapons/weapon/nuke.qc | 189 ++++++++++++++++++ mod/quake/common/weapons/weapon/nuke.qh | 32 +++ mod/quake/server/items.qc | 6 + 16 files changed, 396 insertions(+), 5 deletions(-) create mode 100644 mod/quake/common/effects/qc/_mod.inc create mode 100644 mod/quake/common/effects/qc/_mod.qh create mode 100644 mod/quake/common/effects/qc/modeleffects.qc create mode 100644 mod/quake/common/effects/qc/modeleffects.qh create mode 100644 mod/quake/common/weapons/weapon/nuke.qc create mode 100644 mod/quake/common/weapons/weapon/nuke.qh diff --git a/mod/quake/common/_all.inc b/mod/quake/common/_all.inc index 516f5ae64..809f5b04d 100644 --- a/mod/quake/common/_all.inc +++ b/mod/quake/common/_all.inc @@ -16,6 +16,7 @@ #include "ent_cs.qc" #include "deathtypes/all.qc" +#include "effects/qc/_mod.inc" #include "effects/all.qc" #include "notifications/all.qc" #include "triggers/include.qc" diff --git a/mod/quake/common/_all.qh b/mod/quake/common/_all.qh index e44cc8ca7..c2f3b742c 100644 --- a/mod/quake/common/_all.qh +++ b/mod/quake/common/_all.qh @@ -41,6 +41,7 @@ REGISTER_NET_TEMP(ENT_CLIENT_INIT) #include "physics.qh" +#include "effects/qc/_mod.qh" #include "effects/all.qh" #include "models/all.qh" #include "sounds/all.qh" diff --git a/mod/quake/common/effects/all.inc b/mod/quake/common/effects/all.inc index 7bb8eee77..9e7d0c6e4 100644 --- a/mod/quake/common/effects/all.inc +++ b/mod/quake/common/effects/all.inc @@ -45,3 +45,5 @@ EFFECT(0, QCC_MUSHROOM, "spawn_point_yellow") EFFECT(0, OTAMATONE_FIRE, "arc_smoke") EFFECT(0, ELECTRIFY, "arc_lightning") + +EFFECT(0, NUKE_EXPLODE, "fireball_explode") diff --git a/mod/quake/common/effects/qc/_mod.inc b/mod/quake/common/effects/qc/_mod.inc new file mode 100644 index 000000000..52020cc51 --- /dev/null +++ b/mod/quake/common/effects/qc/_mod.inc @@ -0,0 +1,2 @@ +// genmod.sh autogenerated file; do not modify +#include "modeleffects.qc" diff --git a/mod/quake/common/effects/qc/_mod.qh b/mod/quake/common/effects/qc/_mod.qh new file mode 100644 index 000000000..b687bcd4f --- /dev/null +++ b/mod/quake/common/effects/qc/_mod.qh @@ -0,0 +1,2 @@ +// genmod.sh autogenerated file; do not modify +#include "modeleffects.qh" diff --git a/mod/quake/common/effects/qc/modeleffects.qc b/mod/quake/common/effects/qc/modeleffects.qc new file mode 100644 index 000000000..3a0b5696d --- /dev/null +++ b/mod/quake/common/effects/qc/modeleffects.qc @@ -0,0 +1,146 @@ +#include "modeleffects.qh" + +REGISTER_NET_LINKED(ENT_CLIENT_MODELEFFECT) + +#ifdef SVQC + +.float scale2; + +bool modeleffect_SendEntity(entity this, entity to, int sf) +{ + float f; + WriteHeader(MSG_ENTITY, ENT_CLIENT_MODELEFFECT); + + f = 0; + if(this.velocity != '0 0 0') + f |= 1; + if(this.angles != '0 0 0') + f |= 2; + if(this.avelocity != '0 0 0') + f |= 4; + + WriteByte(MSG_ENTITY, f); + WriteShort(MSG_ENTITY, this.modelindex); + WriteByte(MSG_ENTITY, this.skin); + WriteByte(MSG_ENTITY, this.frame); + WriteVector(MSG_ENTITY, this.origin); + if(f & 1) + { + WriteVector(MSG_ENTITY, this.velocity); + } + if(f & 2) + { + WriteAngleVector(MSG_ENTITY, this.angles); + } + if(f & 4) + { + WriteAngleVector(MSG_ENTITY, this.avelocity); + } + WriteShort(MSG_ENTITY, this.scale * 256.0); + WriteShort(MSG_ENTITY, this.scale2 * 256.0); + WriteByte(MSG_ENTITY, this.teleport_time * 100.0); + WriteByte(MSG_ENTITY, this.fade_time * 100.0); + WriteByte(MSG_ENTITY, this.alpha * 255.0); + + return true; +} + +void modeleffect_spawn(string m, float s, float f, vector o, vector v, vector ang, vector angv, float s0, float s2, float a, float t1, float t2) +{ + entity e = new(modeleffect); + _setmodel(e, m); + e.frame = f; + setorigin(e, o); + e.velocity = v; + e.angles = ang; + e.avelocity = angv; + e.alpha = a; + e.teleport_time = t1; + e.fade_time = t2; + e.skin = s; + if(s0 >= 0) + e.scale = s0 / max6(-e.mins.x, -e.mins.y, -e.mins.z, e.maxs.x, e.maxs.y, e.maxs.z); + else + e.scale = -s0; + if(s2 >= 0) + e.scale2 = s2 / max6(-e.mins.x, -e.mins.y, -e.mins.z, e.maxs.x, e.maxs.y, e.maxs.z); + else + e.scale2 = -s2; + float sz = max(e.scale, e.scale2); + setsize(e, e.mins * sz, e.maxs * sz); + Net_LinkEntity(e, false, 0.1, modeleffect_SendEntity); +} + +#endif + +#ifdef CSQC + +entityclass(ModelEffect); +classfield(ModelEffect) .float frame1time; +classfield(ModelEffect) .float lifetime, fadetime; +classfield(ModelEffect) .float teleport_time; +classfield(ModelEffect) .float scale1, scale2; + +.float cnt; +.float scale; +.float alpha; + +void ModelEffect_Draw(entity this) +{ + this.angles = this.angles + frametime * this.avelocity; + setorigin(this, this.origin + frametime * this.velocity); + this.scale = this.scale1 + (this.scale2 - this.scale1) * (time - this.teleport_time) / (this.lifetime + this.fadetime - this.teleport_time); + this.alpha = this.cnt * bound(0, 1 - (time - this.lifetime) / this.fadetime, 1); + if(this.alpha < 0.003) + { + delete(this); + return; + } + this.drawmask = MASK_NORMAL; + if(this.scale <= 0) + { + this.drawmask = 0; + return; + } +} + +NET_HANDLE(ENT_CLIENT_MODELEFFECT, bool isnew) +{ + make_pure(this); + + int f = ReadByte(); + + entity e = new(modeleffect); + e.model = "from network"; + e.modelindex = ReadShort(); + e.skin = ReadByte(); + e.frame = ReadByte(); + e.frame1time = time; + e.origin = ReadVector(); + setorigin(e, e.origin); + if(f & 1) + { + e.velocity = ReadVector(); + } + if(f & 2) + { + e.angles = ReadAngleVector(); + } + if(f & 4) + { + e.avelocity = ReadAngleVector(); + } + e.scale1 = ReadShort() / 256.0; + e.scale2 = ReadShort() / 256.0; + e.lifetime = time + ReadByte() * 0.01; + e.fadetime = ReadByte() * 0.01; + e.teleport_time = time; + e.cnt = ReadByte() / 255.0; // actually alpha + + e.draw = ModelEffect_Draw; + if (isnew) IL_PUSH(g_drawables, e); + + if (!isnew) delete(e); // yes, this IS stupid, but I don't need to duplicate all the read* stuff then + return true; +} +#endif diff --git a/mod/quake/common/effects/qc/modeleffects.qh b/mod/quake/common/effects/qc/modeleffects.qh new file mode 100644 index 000000000..afa353fae --- /dev/null +++ b/mod/quake/common/effects/qc/modeleffects.qh @@ -0,0 +1,5 @@ +#pragma once + +#ifdef SVQC +void modeleffect_spawn(string m, float s, float f, vector o, vector v, vector ang, vector angv, float s0, float s2, float a, float t1, float t2); +#endif diff --git a/mod/quake/common/notifications/all.inc b/mod/quake/common/notifications/all.inc index 271bf8aad..72940d058 100644 --- a/mod/quake/common/notifications/all.inc +++ b/mod/quake/common/notifications/all.inc @@ -180,6 +180,7 @@ MSG_INFO_NOTIF(WEAPON_FRAG, N_CONSOLE, 2, 0, "s1 s2", "", "", _("^BG%s^K1 was fragged by ^BG%s"), "") MSG_INFO_NOTIF(WEAPON_THINKING_WITH_PORTALS, N_CONSOLE, 2, 0, "s1 s2", "", "", _("^BG%s%s^K1 is now thinking with portals"), "") + MSG_INFO_NOTIF(WEAPON_NUKE_SUICIDE, N_CONSOLE, 2, 0, "s1 s2", "", "", _("^BG%s%s^K1 became Death, the destroyer of worlds"), "") #undef N_DISABLE #undef N_CONSOLE @@ -378,6 +379,7 @@ MSG_MULTI_NOTIF(WEAPON_FRAG, N_ENABLE, NULL, INFO_WEAPON_FRAG, NULL) MSG_MULTI_NOTIF(WEAPON_THINKING_WITH_PORTALS, N_ENABLE, NULL, INFO_WEAPON_THINKING_WITH_PORTALS, CENTER_DEATH_SELF_GENERIC) + MSG_MULTI_NOTIF(WEAPON_NUKE_SUICIDE, N_ENABLE, NULL, INFO_WEAPON_NUKE_SUICIDE, CENTER_DEATH_SELF_GENERIC) #undef N_DISABL #undef N_ENABLE diff --git a/mod/quake/common/triggers/trigger/earthquake.qc b/mod/quake/common/triggers/trigger/earthquake.qc index 982539783..c8ecb6844 100644 --- a/mod/quake/common/triggers/trigger/earthquake.qc +++ b/mod/quake/common/triggers/trigger/earthquake.qc @@ -13,7 +13,7 @@ void earthquake_rumble(entity this) stop_earthquake(this); else { - _sound(this, CH_TRIGGER_SINGLE, "equake/rumble.wav", 1, ATTN_NONE ); + _sound(this, CH_TRIGGER_SINGLE, "equake/rumble.wav", 1, ATTN_NONE); setthink(this, earthquake_rumble); this.nextthink = time + 1; } @@ -22,6 +22,7 @@ void earthquake_rumble(entity this) void start_earthquake(entity this) { earthquake_active = true; + earthquake_intensity = this.weapon * 0.5; if(this.spawnflags & EQ_RANDOM) this.attack_finished = time + random() * this.delay; else @@ -63,7 +64,6 @@ spawnfunc(earthquake) precache_sound("equake/rumble.wav"); earthquake_active = false; - earthquake_intensity = this.weapon * 0.5; setsize(this, '0 0 0', '0 0 0'); setthink(this, stop_earthquake); diff --git a/mod/quake/common/weapons/all.inc b/mod/quake/common/weapons/all.inc index 86a130c21..885a630de 100644 --- a/mod/quake/common/weapons/all.inc +++ b/mod/quake/common/weapons/all.inc @@ -44,6 +44,7 @@ #include "weapon/organ.qh" #include "weapon/ball.qh" #include "weapon/wand.qh" +#include "weapon/nuke.qh" // WARNING: also update the weapon priority list in all.qh or your weapon won't work properly!! diff --git a/mod/quake/common/weapons/all.qh b/mod/quake/common/weapons/all.qh index c4a5fb4d9..bf1b4446d 100644 --- a/mod/quake/common/weapons/all.qh +++ b/mod/quake/common/weapons/all.qh @@ -4,14 +4,14 @@ #ifdef GAMEQC // TODO: cleaner way to list these? -noref string autocvar_cl_quake_weaponpriority = "katana breegull mushroom pogo rocketlauncher multirocketlauncher impaler cannon lightning plasma shock lightme otamatone laser_gun mic grenadelauncher multigrenade proximitygun tuba napalm fish chimes mayo spellbook hammer portalgun ocarina supernailgun lavasupernailgun organ crossbow piano sshotgun ripper doot nailgun lavanailgun biogun kazoo shotgun banjo ball wand chainsaw pan axe bongos"; +noref string autocvar_cl_quake_weaponpriority = "katana breegull mushroom pogo rocketlauncher multirocketlauncher impaler nuke cannon lightning plasma shock lightme otamatone laser_gun mic grenadelauncher multigrenade proximitygun tuba napalm fish chimes mayo spellbook hammer portalgun ocarina supernailgun lavasupernailgun organ crossbow piano sshotgun ripper doot nailgun lavanailgun biogun kazoo shotgun banjo ball wand chainsaw pan axe bongos"; noref bool autocvar_cl_quake_weaponpriority_useforcycling = false; -noref string autocvar_cl_quake_weaponpriority0 = "rocketlauncher cannon multirocketlauncher impaler grenadelauncher multigrenade biogun proximitygun tuba napalm fish mayo"; // explosives +noref string autocvar_cl_quake_weaponpriority0 = "rocketlauncher nuke cannon multirocketlauncher impaler grenadelauncher multigrenade biogun proximitygun tuba napalm fish mayo"; // explosives noref string autocvar_cl_quake_weaponpriority1 = "lightning plasma shock lightme"; // energy noref string autocvar_cl_quake_weaponpriority2 = "lightning portalgun"; // hitscan exact noref string autocvar_cl_quake_weaponpriority3 = "lightning sshotgun shotgun"; // hitscan all noref string autocvar_cl_quake_weaponpriority4 = "laser_gun shock grenadelauncher multigrenade napalm fish mayo ocarina supernailgun biogun tuba lavasupernailgun crossbow piano doot nailgun lavanailgun bongos kazoo chainsaw"; // spam weapons -noref string autocvar_cl_quake_weaponpriority5 = "cannon impaler portalgun"; // movement weapons +noref string autocvar_cl_quake_weaponpriority5 = "nuke cannon impaler portalgun"; // movement weapons noref string autocvar_cl_quake_weaponpriority6 = "tuba mic ocarina otamatone banjo bongos chimes mayo organ piano kazoo doot"; // musical instruments noref string autocvar_cl_quake_weaponpriority7 = ""; noref string autocvar_cl_quake_weaponpriority8 = ""; diff --git a/mod/quake/common/weapons/weapon/_mod.inc b/mod/quake/common/weapons/weapon/_mod.inc index 644540489..ad25d59fd 100644 --- a/mod/quake/common/weapons/weapon/_mod.inc +++ b/mod/quake/common/weapons/weapon/_mod.inc @@ -45,3 +45,4 @@ #include "chimes.qc" #include "ball.qc" #include "wand.qc" +#include "nuke.qc" diff --git a/mod/quake/common/weapons/weapon/_mod.qh b/mod/quake/common/weapons/weapon/_mod.qh index 7fc58a43c..30f623b0b 100644 --- a/mod/quake/common/weapons/weapon/_mod.qh +++ b/mod/quake/common/weapons/weapon/_mod.qh @@ -45,3 +45,4 @@ #include "chimes.qh" #include "ball.qh" #include "wand.qh" +#include "nuke.qh" diff --git a/mod/quake/common/weapons/weapon/nuke.qc b/mod/quake/common/weapons/weapon/nuke.qc new file mode 100644 index 000000000..ae67ee86d --- /dev/null +++ b/mod/quake/common/weapons/weapon/nuke.qc @@ -0,0 +1,189 @@ +#include "nuke.qh" + +#ifdef SVQC +PRECACHE(Nuke) +{ + precache_model("progs/v_nuke.mdl"); + precache_model("progs/g_nuke.mdl"); + + precache_model("progs/nuke.mdl"); + precache_model("models/sphere/sphere.md3"); + + precache_sound("equake/rumble.wav"); +} + +void nuke_explode_think(entity this) +{ + this.nextthink = time + 0.1; + + if(time >= this.attack_finished) + { + earthquake_active = false; + stopsound(this, CH_TRIGGER_SINGLE); + delete(this); + return; + } + + if(time >= this.wait) + { + this.wait = time + 1; + _sound(this, CH_TRIGGER_SINGLE, "equake/rumble.wav", 1, ATTN_NONE); + } + + if(time >= this.dmgtime) + { + T_RadiusDamage(this, this.realowner, 250 * this.scale2, WEP_NUKE.m_id, NULL); + this.dmgtime = time + 0.25; + } + + this.scale2 += 0.1; +} + +void nuke_think(entity this) +{ + setthink(this, nuke_think); + this.nextthink = time; + + if(this.wait && time > this.wait) + { + earthquake_active = true; + earthquake_intensity = 20; + this.attack_finished = time + 3.5; + sound(this, CH_WEAPON_SINGLE, SND_NUKE_EXPLODE_RANDOM(), 1, 0.1); + modeleffect_spawn("models/sphere/sphere.md3", 0, 0, this.origin, '0 0 0', '0 0 0', '0 0 0', 0, 800, 0.2, 1, 5); + Send_Effect(EFFECT_NUKE_EXPLODE, this.origin + '0 0 16', '0 0 0', 1); + setthink(this, nuke_explode_think); + this.nextthink = time; + setmodel(this, MDL_Null); + setsize(this, '0 0 0', '0 0 0'); + return; + } +} + +void nuke_setup(entity this) +{ + //set_movetype(this, MOVETYPE_NONE); + this.owner = NULL; // to allow collisions + setthink(this, nuke_think); + this.nextthink = time + 0.1; + this.solid = SOLID_TRIGGER; + settouch(this, func_null); +} + +spawnfunc(nuke) +{ + if(!this.speed) + this.speed = 2000; + if(!this.dmg) + this.dmg = 2000; + this.solid = SOLID_TRIGGER; + set_movetype(this, MOVETYPE_TOSS); + setmodel(this, MDL_NUKE); + setsize(this, '-16 -16 -16', '16 16 32'); + this.pos2 = this.angles; + if(!this.noalign) + DropToFloor_QC_DelayedInit(this); + nuke_setup(this); +} + +void nuke_projectile_touch(entity this, entity toucher) +{ + if(toucher && toucher.solid != SOLID_BSP) + return; + if(pointcontents(this.origin) == CONTENT_SKY) + { + delete(this); + return; + } + + // TODO: bumping sound? +} + +void nuke_projectile_think(entity this) +{ + this.nextthink = time; + if(time >= this.wait) + { + delete(this); + return; + } + + if(!IS_ONGROUND(this)) + return; + + sound(this, CH_WEAPON_B, SND_NUKE_LAND, 1, ATTN_NORM); + nuke_setup(this); + this.attack_finished = time + 0.5; + this.dmg = 2000; + this.speed = 2000; + this.wait = time + 7; +} + +void W_DropNuke(entity this, .entity weaponentity) +{ + if(!StatusEffects_active(STATUSEFFECT_SharpShooter, this)) + { + // add a delay to every weapon slot when dropping a nuke to prevent instant fires + for (int slot = 0; slot < MAX_WEAPONSLOTS; ++slot) + { + .entity w_ent = weaponentities[slot]; + if(this.(w_ent) && slot != weaponslot(weaponentity)) + ATTACK_FINISHED(this, w_ent) = time + 0.5; + } + STAT(WEAPONS, this) &= ~WEP_NUKE.m_wepset; + W_SwitchWeapon(this, w_getbestweapon(this, weaponentity), weaponentity); + } + + sound(this, CH_WEAPON_B, SND_NUKE_DROP, 1, ATTN_NORM); + + entity nuke = new(nuke_projectile); + nuke.owner = this; + nuke.realowner = this; + set_movetype(nuke, MOVETYPE_TOSS); + nuke.solid = SOLID_BBOX; + setmodel(nuke, MDL_NUKE); + //setsize(nuke, '-8 -8 -16', '8 8 8'); + vector cmin = this.mins, cmax = this.maxs; + // some basic sanity, but otherwise use player's hitbox to avoid exploits + cmin.z = -16; + cmax.z = 32; + setsize(nuke, cmin, cmax); + settouch(nuke, nuke_projectile_touch); + setthink(nuke, nuke_projectile_think); + nuke.wait = time + 3; + nuke.nextthink = time; + + vector org = this.origin + (this.view_ofs * 0.75); + setorigin(nuke, org); + nuke.angles = this.angles; + nuke.pos2 = nuke.angles; + makevectors(this.angles); + nuke.velocity = v_forward * 200 + v_up * 20; +} + +METHOD(Nuke, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire)) +{ + if(fire & 1) + if(!(time < ATTACK_FINISHED(actor, weaponentity))) + if(thiswep.wr_checkammo1(thiswep, actor, weaponentity)) + { + if(IS_PLAYER(actor)) + player_rocket1(actor); + wep_generic_rocket1(actor.(weaponentity)); + W_DropNuke(actor, weaponentity); + weapon_prepareattack(thiswep, actor, weaponentity, 1.5); + } +} +METHOD(Nuke, wr_checkammo1, bool(entity thiswep, entity actor, .entity weaponentity)) +{ + return true; // no ammo +} +METHOD(Nuke, wr_suicidemessage, Notification(entity thiswep)) +{ + return WEAPON_NUKE_SUICIDE; +} +METHOD(Nuke, wr_killmessage, Notification(entity thiswep)) +{ + return WEAPON_FRAG; +} +#endif diff --git a/mod/quake/common/weapons/weapon/nuke.qh b/mod/quake/common/weapons/weapon/nuke.qh new file mode 100644 index 000000000..cc3b1a744 --- /dev/null +++ b/mod/quake/common/weapons/weapon/nuke.qh @@ -0,0 +1,32 @@ +#pragma once + +#ifdef GAMEQC +SOUND(NUKE_DROP, "weapons/sword_swing"); +SOUND(NUKE_LAND, "enviro/physics/axemet1"); + +SOUND(NUKE_EXPLODE, "weapons/r_exp3"); +SOUND(NUKE_EXPLODE_ALT, "weapons/nuke_explode_alt"); +Sound SND_NUKE_EXPLODE_RANDOM() { + return (random() < 0.1) ? SND_NUKE_EXPLODE_ALT : SND_NUKE_EXPLODE; +} + +MODEL(NUKE, "progs/nuke.mdl"); +#endif + +CLASS(Nuke, Weapon) +/* ammotype */ ATTRIB(Nuke, ammo_type, int, 0); +/* impulse */ ATTRIB(Nuke, impulse, int, 7); +/* spawnflags*/ ATTRIB(Nuke, spawnflags, int, WEP_FLAG_NODUAL); +/* ammo */ ATTRIB(Nuke, aflag, int, 0); +/* modelname */ ATTRIB(Nuke, mdl, string, "nuke"); +/* crosshair */ ATTRIB(Nuke, w_crosshair, string, "gfx/crosshairfireball"); +/* crosshair */ ATTRIB(Nuke, w_crosshair_size, float, 0.8); +/* crosshair */ ATTRIB(Nuke, w_crosshair_color, vector, '1 1 0'); +/* wepimg */ ATTRIB(Nuke, model2, string, "nuke"); +/* refname */ ATTRIB(Nuke, netname, string, "nuke"); +/* wepname */ ATTRIB(Nuke, m_name, string, _("Nuke")); + +ENDCLASS(Nuke) +REGISTER_WEAPON(NUKE, NEW(Nuke)); + +SPAWNFUNC_WEAPON(weapon_nuke, WEP_NUKE) diff --git a/mod/quake/server/items.qc b/mod/quake/server/items.qc index 4da63bbbd..e2108a754 100644 --- a/mod/quake/server/items.qc +++ b/mod/quake/server/items.qc @@ -843,6 +843,12 @@ Weapon W_RandomizeWeapon(Weapon wpn) mytype = IT_ROCKETS; break; } + case WEP_NUKE: + { + if(random() < 0.33) + mytype = IT_ROCKETS; + break; + } case WEP_OTAMATONE: { if(random() > 0.5)