123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428 |
- /*
- weapons.qc
- weapon and weapon hit functions
- Copyright (C) 1996-1997 Id Software, Inc.
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License
- as published by the Free Software Foundation; either version 2
- of the License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to:
- Free Software Foundation, Inc.
- 59 Temple Place - Suite 330
- Boston, MA 02111-1307, USA
- */
- void (entity targ, entity inflictor, entity attacker, float damage) T_Damage;
- void () player_run;
- void(entity bomb, entity attacker, float rad, entity ignore, string dtype) T_RadiusDamage;
- void(vector org, float damage) SpawnBlood;
- void() SuperDamageSound;
- // called by worldspawn
- void() W_Precache =
- {
- precache_sound ("weapons/r_exp3.wav"); // new rocket explosion
- precache_sound ("weapons/rocket1i.wav"); // spike gun
- precache_sound ("weapons/sgun1.wav");
- precache_sound ("weapons/guncock.wav"); // player shotgun
- precache_sound ("weapons/ric1.wav"); // ricochet (used in c code)
- precache_sound ("weapons/ric2.wav"); // ricochet (used in c code)
- precache_sound ("weapons/ric3.wav"); // ricochet (used in c code)
- precache_sound ("weapons/spike2.wav"); // super spikes
- precache_sound ("weapons/tink1.wav"); // spikes tink (used in c code)
- precache_sound ("weapons/grenade.wav"); // grenade launcher
- precache_sound ("weapons/bounce.wav"); // grenade bounce
- precache_sound ("weapons/shotgn2.wav"); // super shotgun
- };
- float() crandom =
- {
- return 2*(random() - 0.5);
- };
- /*
- ================
- W_FireAxe
- ================
- */
- void() W_FireAxe =
- {
- local vector source;
- local vector org;
- makevectors (self.v_angle);
- source = self.origin + '0 0 16';
- traceline (source, source + v_forward*64, FALSE, self);
- if (trace_fraction == 1.0)
- return;
-
- org = trace_endpos - v_forward*4;
- if (trace_ent.takedamage)
- {
- trace_ent.axhitme = 1;
- SpawnBlood (org, 20);
- if (deathmatch > 3)
- T_Damage (trace_ent, self, self, 75);
- else
- T_Damage (trace_ent, self, self, 20);
- }
- else
- { // hit wall
- sound (self, CHAN_WEAPON, "player/axhit2.wav", 1, ATTN_NORM);
- WriteByte (MSG_MULTICAST, SVC_TEMPENTITY);
- WriteByte (MSG_MULTICAST, TE_GUNSHOT);
- WriteByte (MSG_MULTICAST, 3);
- WriteCoord (MSG_MULTICAST, org_x);
- WriteCoord (MSG_MULTICAST, org_y);
- WriteCoord (MSG_MULTICAST, org_z);
- multicast (org, MULTICAST_PVS);
- }
- };
- //============================================================================
- vector() wall_velocity =
- {
- local vector vel;
-
- vel = normalize (self.velocity);
- vel = normalize(vel + v_up*(random()- 0.5) + v_right*(random()- 0.5));
- vel = vel + 2*trace_plane_normal;
- vel = vel * 200;
-
- return vel;
- };
- /*
- ================
- SpawnMeatSpray
- ================
- */
- void(vector org, vector vel) SpawnMeatSpray =
- {
- local entity missile;
- local vector org;
- missile = spawn ();
- missile.owner = self;
- missile.movetype = MOVETYPE_BOUNCE;
- missile.solid = SOLID_NOT;
- makevectors (self.angles);
- missile.velocity = vel;
- missile.velocity_z = missile.velocity_z + 250 + 50*random();
- missile.avelocity = '3000 1000 2000';
-
- // set missile duration
- missile.nextthink = time + 1;
- missile.think = SUB_Remove;
- setmodel (missile, "progs/zom_gib.mdl");
- setsize (missile, '0 0 0', '0 0 0');
- setorigin (missile, org);
- };
- /*
- ================
- SpawnBlood
- ================
- */
- void(vector org, float damage) SpawnBlood =
- {
- WriteByte (MSG_MULTICAST, SVC_TEMPENTITY);
- WriteByte (MSG_MULTICAST, TE_BLOOD);
- WriteByte (MSG_MULTICAST, 1);
- WriteCoord (MSG_MULTICAST, org_x);
- WriteCoord (MSG_MULTICAST, org_y);
- WriteCoord (MSG_MULTICAST, org_z);
- multicast (org, MULTICAST_PVS);
- };
- /*
- ================
- spawn_touchblood
- ================
- */
- void(float damage) spawn_touchblood =
- {
- local vector vel;
- vel = wall_velocity () * 0.2;
- SpawnBlood (self.origin + vel*0.01, damage);
- };
- /*
- ==============================================================================
- MULTI-DAMAGE
- Collects multiple small damages into a single damage
- ==============================================================================
- */
- entity multi_ent;
- float multi_damage;
- vector blood_org;
- float blood_count;
- vector puff_org;
- float puff_count;
- void() ClearMultiDamage =
- {
- multi_ent = world;
- multi_damage = 0;
- blood_count = 0;
- puff_count = 0;
- };
- void() ApplyMultiDamage =
- {
- if (!multi_ent)
- return;
- T_Damage (multi_ent, self, self, multi_damage);
- };
- void(entity hit, float damage) AddMultiDamage =
- {
- if (!hit)
- return;
-
- if (hit != multi_ent)
- {
- ApplyMultiDamage ();
- multi_damage = damage;
- multi_ent = hit;
- }
- else
- multi_damage = multi_damage + damage;
- };
- void() Multi_Finish =
- {
- if (puff_count)
- {
- WriteByte (MSG_MULTICAST, SVC_TEMPENTITY);
- WriteByte (MSG_MULTICAST, TE_GUNSHOT);
- WriteByte (MSG_MULTICAST, puff_count);
- WriteCoord (MSG_MULTICAST, puff_org_x);
- WriteCoord (MSG_MULTICAST, puff_org_y);
- WriteCoord (MSG_MULTICAST, puff_org_z);
- multicast (puff_org, MULTICAST_PVS);
- }
- if (blood_count)
- {
- WriteByte (MSG_MULTICAST, SVC_TEMPENTITY);
- WriteByte (MSG_MULTICAST, TE_BLOOD);
- WriteByte (MSG_MULTICAST, blood_count);
- WriteCoord (MSG_MULTICAST, blood_org_x);
- WriteCoord (MSG_MULTICAST, blood_org_y);
- WriteCoord (MSG_MULTICAST, blood_org_z);
- multicast (puff_org, MULTICAST_PVS);
- }
- };
- /*
- ==============================================================================
- BULLETS
- ==============================================================================
- */
- /*
- ================
- TraceAttack
- ================
- */
- void(float damage, vector dir) TraceAttack =
- {
- local vector vel, org;
-
- vel = normalize(dir + v_up*crandom() + v_right*crandom());
- vel = vel + 2*trace_plane_normal;
- vel = vel * 200;
- org = trace_endpos - dir*4;
- if (trace_ent.takedamage)
- {
- blood_count = blood_count + 1;
- blood_org = org;
- AddMultiDamage (trace_ent, damage);
- }
- else
- {
- puff_count = puff_count + 1;
- }
- };
- /*
- ================
- FireBullets
- Used by shotgun, super shotgun, and enemy soldier firing
- Go to the trouble of combining multiple pellets into a single damage call.
- ================
- */
- void(float shotcount, vector dir, vector spread) FireBullets =
- {
- local vector direction;
- local vector src;
-
- makevectors(self.v_angle);
- src = self.origin + v_forward*10;
- src_z = self.absmin_z + self.size_z * 0.7;
- ClearMultiDamage ();
- traceline (src, src + dir*2048, FALSE, self);
- puff_org = trace_endpos - dir*4;
- while (shotcount > 0)
- {
- direction = dir + crandom()*spread_x*v_right + crandom()*spread_y*v_up;
- traceline (src, src + direction*2048, FALSE, self);
- if (trace_fraction != 1.0)
- TraceAttack (4, direction);
- shotcount = shotcount - 1;
- }
- ApplyMultiDamage ();
- Multi_Finish ();
- };
- /*
- ================
- W_FireShotgun
- ================
- */
- void() W_FireShotgun =
- {
- local vector dir;
- sound (self, CHAN_WEAPON, "weapons/guncock.wav", 1, ATTN_NORM);
- msg_entity = self;
- WriteByte (MSG_ONE, SVC_SMALLKICK);
-
- if (deathmatch != 4 )
- self.currentammo = self.ammo_shells = self.ammo_shells - 1;
- dir = aim (self, 100000);
- FireBullets (6, dir, '0.04 0.04 0');
- };
- /*
- ================
- W_FireSuperShotgun
- ================
- */
- void() W_FireSuperShotgun =
- {
- local vector dir;
- if (self.currentammo == 1)
- {
- W_FireShotgun ();
- return;
- }
-
- sound (self ,CHAN_WEAPON, "weapons/shotgn2.wav", 1, ATTN_NORM);
- msg_entity = self;
- WriteByte (MSG_ONE, SVC_BIGKICK);
-
- if (deathmatch != 4)
- self.currentammo = self.ammo_shells = self.ammo_shells - 2;
- dir = aim (self, 100000);
- FireBullets (14, dir, '0.14 0.08 0');
- };
- /*
- ==============================================================================
- ROCKETS
- ==============================================================================
- */
- void() T_MissileTouch =
- {
- local float damg;
- // if (deathmatch == 4)
- // {
- // if ( ((other.weapon == 32) || (other.weapon == 16)))
- // {
- // if (random() < 0.1)
- // {
- // if (other != world)
- // {
- // // bprint (PRINT_HIGH, "Got here\n");
- // other.deathtype = "blaze";
- // T_Damage (other, self, self.owner, 1000 );
- // T_RadiusDamage (self, self.owner, 1000, other);
- // }
- // }
- // }
- // }
- if (other == self.owner)
- return; // don't explode on owner
- if (self.voided) {
- return;
- }
- self.voided = 1;
- if (pointcontents(self.origin) == CONTENT_SKY)
- {
- remove(self);
- return;
- }
- damg = 100 + random()*20;
-
- if (other.health)
- {
- other.deathtype = "rocket";
- T_Damage (other, self, self.owner, damg );
- }
- // don't do radius damage to the other, because all the damage
- // was done in the impact
- T_RadiusDamage (self, self.owner, 120, other, "rocket");
- // sound (self, CHAN_WEAPON, "weapons/r_exp3.wav", 1, ATTN_NORM);
- self.origin = self.origin - 8 * normalize(self.velocity);
- WriteByte (MSG_MULTICAST, SVC_TEMPENTITY);
- WriteByte (MSG_MULTICAST, TE_EXPLOSION);
- WriteCoord (MSG_MULTICAST, self.origin_x);
- WriteCoord (MSG_MULTICAST, self.origin_y);
- WriteCoord (MSG_MULTICAST, self.origin_z);
- multicast (self.origin, MULTICAST_PHS);
- remove(self);
- };
- /*
- ================
- W_FireRocket
- ================
- */
- void() W_FireRocket =
- {
- if (deathmatch != 4)
- self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
-
- sound (self, CHAN_WEAPON, "weapons/sgun1.wav", 1, ATTN_NORM);
- msg_entity = self;
- WriteByte (MSG_ONE, SVC_SMALLKICK);
- newmis = spawn ();
- newmis.owner = self;
- newmis.movetype = MOVETYPE_FLYMISSILE;
- newmis.solid = SOLID_BBOX;
-
- // set newmis speed
- makevectors (self.v_angle);
- newmis.velocity = aim(self, 1000);
- newmis.velocity = newmis.velocity * 1000;
- newmis.angles = vectoangles(newmis.velocity);
-
- newmis.touch = T_MissileTouch;
- newmis.voided = 0;
-
- // set newmis duration
- newmis.nextthink = time + 5;
- newmis.think = SUB_Remove;
- newmis.classname = "rocket";
- setmodel (newmis, "progs/missile.mdl");
- setsize (newmis, '0 0 0', '0 0 0');
- setorigin (newmis, self.origin + v_forward*8 + '0 0 16');
- };
- /*
- ===============================================================================
- LIGHTNING
- ===============================================================================
- */
- void(entity from, float damage) LightningHit =
- {
- WriteByte (MSG_MULTICAST, SVC_TEMPENTITY);
- WriteByte (MSG_MULTICAST, TE_LIGHTNINGBLOOD);
- WriteCoord (MSG_MULTICAST, trace_endpos_x);
- WriteCoord (MSG_MULTICAST, trace_endpos_y);
- WriteCoord (MSG_MULTICAST, trace_endpos_z);
- multicast (trace_endpos, MULTICAST_PVS);
- T_Damage (trace_ent, from, from, damage);
- };
- /*
- =================
- LightningDamage
- =================
- */
- void(vector p1, vector p2, entity from, float damage) LightningDamage =
- {
- local entity e1, e2;
- local vector f;
-
- f = p2 - p1;
- normalize (f);
- f_x = 0 - f_y;
- f_y = f_x;
- f_z = 0;
- f = f*16;
- e1 = e2 = world;
- traceline (p1, p2, FALSE, self);
- if (trace_ent.takedamage)
- {
- LightningHit (from, damage);
- if (self.classname == "player")
- {
- if (other.classname == "player")
- trace_ent.velocity_z = trace_ent.velocity_z + 400;
- }
- }
- e1 = trace_ent;
- traceline (p1 + f, p2 + f, FALSE, self);
- if (trace_ent != e1 && trace_ent.takedamage)
- {
- LightningHit (from, damage);
- }
- e2 = trace_ent;
- traceline (p1 - f, p2 - f, FALSE, self);
- if (trace_ent != e1 && trace_ent != e2 && trace_ent.takedamage)
- {
- LightningHit (from, damage);
- }
- };
- void() W_FireLightning =
- {
- local vector org;
- local float cells;
- if (self.ammo_cells < 1)
- {
- self.weapon = W_BestWeapon ();
- W_SetCurrentAmmo ();
- return;
- }
- // explode if under water
- if (self.waterlevel > 1)
- {
- if (deathmatch > 3)
- {
- if (random() <= 0.5)
- {
- self.deathtype = "selfwater";
- T_Damage (self, self, self.owner, 4000 );
- }
- else
- {
- cells = self.ammo_cells;
- self.ammo_cells = 0;
- W_SetCurrentAmmo ();
- T_RadiusDamage (self, self, 35*cells, world, "");
- return;
- }
- }
- else
- {
- cells = self.ammo_cells;
- self.ammo_cells = 0;
- W_SetCurrentAmmo ();
- T_RadiusDamage (self, self, 35*cells, world,"");
- return;
- }
- }
- if (self.t_width < time)
- {
- sound (self, CHAN_WEAPON, "weapons/lhit.wav", 1, ATTN_NORM);
- self.t_width = time + 0.6;
- }
- msg_entity = self;
- WriteByte (MSG_ONE, SVC_SMALLKICK);
- if (deathmatch != 4)
- self.currentammo = self.ammo_cells = self.ammo_cells - 1;
- org = self.origin + '0 0 16';
-
- traceline (org, org + v_forward*600, TRUE, self);
- WriteByte (MSG_MULTICAST, SVC_TEMPENTITY);
- WriteByte (MSG_MULTICAST, TE_LIGHTNING2);
- WriteEntity (MSG_MULTICAST, self);
- WriteCoord (MSG_MULTICAST, org_x);
- WriteCoord (MSG_MULTICAST, org_y);
- WriteCoord (MSG_MULTICAST, org_z);
- WriteCoord (MSG_MULTICAST, trace_endpos_x);
- WriteCoord (MSG_MULTICAST, trace_endpos_y);
- WriteCoord (MSG_MULTICAST, trace_endpos_z);
- multicast (org, MULTICAST_PHS);
- LightningDamage (self.origin, trace_endpos + v_forward*4, self, 30);
- };
- //=============================================================================
- void() GrenadeExplode =
- {
- if (self.voided) {
- return;
- }
- self.voided = 1;
- T_RadiusDamage (self, self.owner, 120, world, "grenade");
- WriteByte (MSG_MULTICAST, SVC_TEMPENTITY);
- WriteByte (MSG_MULTICAST, TE_EXPLOSION);
- WriteCoord (MSG_MULTICAST, self.origin_x);
- WriteCoord (MSG_MULTICAST, self.origin_y);
- WriteCoord (MSG_MULTICAST, self.origin_z);
- multicast (self.origin, MULTICAST_PHS);
- remove (self);
- };
- void() GrenadeTouch =
- {
- if (other == self.owner)
- return; // don't explode on owner
- if (other.takedamage == DAMAGE_AIM)
- {
- GrenadeExplode();
- return;
- }
- sound (self, CHAN_WEAPON, "weapons/bounce.wav", 1, ATTN_NORM); // bounce sound
- if (self.velocity == '0 0 0')
- self.avelocity = '0 0 0';
- };
- /*
- ================
- W_FireGrenade
- ================
- */
- void() W_FireGrenade =
- {
- if (deathmatch != 4)
- self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
-
- sound (self, CHAN_WEAPON, "weapons/grenade.wav", 1, ATTN_NORM);
- msg_entity = self;
- WriteByte (MSG_ONE, SVC_SMALLKICK);
- newmis = spawn ();
- newmis.voided=0;
- newmis.owner = self;
- newmis.movetype = MOVETYPE_BOUNCE;
- newmis.solid = SOLID_BBOX;
- newmis.classname = "grenade";
-
- // set newmis speed
- makevectors (self.v_angle);
- if (self.v_angle_x)
- newmis.velocity = v_forward*600 + v_up * 200 + crandom()*v_right*10 + crandom()*v_up*10;
- else
- {
- newmis.velocity = aim(self, 10000);
- newmis.velocity = newmis.velocity * 600;
- newmis.velocity_z = 200;
- }
- newmis.avelocity = '300 300 300';
- newmis.angles = vectoangles(newmis.velocity);
-
- newmis.touch = GrenadeTouch;
-
- // set newmis duration
- if (deathmatch == 4)
- {
- newmis.nextthink = time + 2.5;
- self.attack_finished = time + 1.1;
- // self.health = self.health - 1;
- T_Damage (self, self, self.owner, 10 );
- }
- else
- newmis.nextthink = time + 2.5;
- newmis.think = GrenadeExplode;
- setmodel (newmis, "progs/grenade.mdl");
- setsize (newmis, '0 0 0', '0 0 0');
- setorigin (newmis, self.origin);
- };
- //=============================================================================
- void() spike_touch;
- void() superspike_touch;
- /*
- ===============
- launch_spike
- Used for both the player and the ogre
- ===============
- */
- void(vector org, vector dir) launch_spike =
- {
- newmis = spawn ();
- newmis.voided=0;
- newmis.owner = self;
- newmis.movetype = MOVETYPE_FLYMISSILE;
- newmis.solid = SOLID_BBOX;
- newmis.angles = vectoangles(dir);
-
- newmis.touch = spike_touch;
- newmis.classname = "spike";
- newmis.think = SUB_Remove;
- newmis.nextthink = time + 6;
- setmodel (newmis, "progs/spike.mdl");
- setsize (newmis, VEC_ORIGIN, VEC_ORIGIN);
- setorigin (newmis, org);
- newmis.velocity = dir * 1000;
- };
- void() W_FireSuperSpikes =
- {
- local vector dir;
- local entity old;
-
- sound (self, CHAN_WEAPON, "weapons/spike2.wav", 1, ATTN_NORM);
- self.attack_finished = time + 0.2;
- if (deathmatch != 4)
- self.currentammo = self.ammo_nails = self.ammo_nails - 2;
- dir = aim (self, 1000);
- launch_spike (self.origin + '0 0 16', dir);
- newmis.touch = superspike_touch;
- setmodel (newmis, "progs/s_spike.mdl");
- setsize (newmis, VEC_ORIGIN, VEC_ORIGIN);
- msg_entity = self;
- WriteByte (MSG_ONE, SVC_SMALLKICK);
- };
- void(float ox) W_FireSpikes =
- {
- local vector dir;
- local entity old;
-
- makevectors (self.v_angle);
-
- if (self.ammo_nails >= 2 && self.weapon == IT_SUPER_NAILGUN)
- {
- W_FireSuperSpikes ();
- return;
- }
- if (self.ammo_nails < 1)
- {
- self.weapon = W_BestWeapon ();
- W_SetCurrentAmmo ();
- return;
- }
- sound (self, CHAN_WEAPON, "weapons/rocket1i.wav", 1, ATTN_NORM);
- self.attack_finished = time + 0.2;
- if (deathmatch != 4)
- self.currentammo = self.ammo_nails = self.ammo_nails - 1;
- dir = aim (self, 1000);
- launch_spike (self.origin + '0 0 16' + v_right*ox, dir);
- msg_entity = self;
- WriteByte (MSG_ONE, SVC_SMALLKICK);
- };
- .float hit_z;
- void() spike_touch =
- {
- local float rand;
- if (other == self.owner)
- return;
- if (self.voided) {
- return;
- }
- self.voided = 1;
- if (other.solid == SOLID_TRIGGER)
- return; // trigger field, do nothing
- if (pointcontents(self.origin) == CONTENT_SKY)
- {
- remove(self);
- return;
- }
-
- // hit something that bleeds
- if (other.takedamage)
- {
- spawn_touchblood (9);
- other.deathtype = "nail";
- T_Damage (other, self, self.owner, 9);
- }
- else
- {
- WriteByte (MSG_MULTICAST, SVC_TEMPENTITY);
- if (self.classname == "wizspike")
- WriteByte (MSG_MULTICAST, TE_WIZSPIKE);
- else if (self.classname == "knightspike")
- WriteByte (MSG_MULTICAST, TE_KNIGHTSPIKE);
- else
- WriteByte (MSG_MULTICAST, TE_SPIKE);
- WriteCoord (MSG_MULTICAST, self.origin_x);
- WriteCoord (MSG_MULTICAST, self.origin_y);
- WriteCoord (MSG_MULTICAST, self.origin_z);
- multicast (self.origin, MULTICAST_PHS);
- }
- remove(self);
- };
- void() superspike_touch =
- {
- local float rand;
- if (other == self.owner)
- return;
- if (self.voided) {
- return;
- }
- self.voided = 1;
- if (other.solid == SOLID_TRIGGER)
- return; // trigger field, do nothing
- if (pointcontents(self.origin) == CONTENT_SKY)
- {
- remove(self);
- return;
- }
-
- // hit something that bleeds
- if (other.takedamage)
- {
- spawn_touchblood (18);
- other.deathtype = "supernail";
- T_Damage (other, self, self.owner, 18);
- }
- else
- {
- WriteByte (MSG_MULTICAST, SVC_TEMPENTITY);
- WriteByte (MSG_MULTICAST, TE_SUPERSPIKE);
- WriteCoord (MSG_MULTICAST, self.origin_x);
- WriteCoord (MSG_MULTICAST, self.origin_y);
- WriteCoord (MSG_MULTICAST, self.origin_z);
- multicast (self.origin, MULTICAST_PHS);
- }
- remove(self);
- };
- /*
- ===============================================================================
- PLAYER WEAPON USE
- ===============================================================================
- */
- void() W_SetCurrentAmmo =
- {
- player_run (); // get out of any weapon firing states
- self.items = self.items - ( self.items & (IT_SHELLS | IT_NAILS | IT_ROCKETS | IT_CELLS) );
-
- if (self.weapon == IT_AXE)
- {
- self.currentammo = 0;
- self.weaponmodel = "progs/v_axe.mdl";
- self.weaponframe = 0;
- }
- else if (self.weapon == IT_SHOTGUN)
- {
- self.currentammo = self.ammo_shells;
- self.weaponmodel = "progs/v_shot.mdl";
- self.weaponframe = 0;
- self.items = self.items | IT_SHELLS;
- }
- else if (self.weapon == IT_SUPER_SHOTGUN)
- {
- self.currentammo = self.ammo_shells;
- self.weaponmodel = "progs/v_shot2.mdl";
- self.weaponframe = 0;
- self.items = self.items | IT_SHELLS;
- }
- else if (self.weapon == IT_NAILGUN)
- {
- self.currentammo = self.ammo_nails;
- self.weaponmodel = "progs/v_nail.mdl";
- self.weaponframe = 0;
- self.items = self.items | IT_NAILS;
- }
- else if (self.weapon == IT_SUPER_NAILGUN)
- {
- self.currentammo = self.ammo_nails;
- self.weaponmodel = "progs/v_nail2.mdl";
- self.weaponframe = 0;
- self.items = self.items | IT_NAILS;
- }
- else if (self.weapon == IT_GRENADE_LAUNCHER)
- {
- self.currentammo = self.ammo_rockets;
- self.weaponmodel = "progs/v_rock.mdl";
- self.weaponframe = 0;
- self.items = self.items | IT_ROCKETS;
- }
- else if (self.weapon == IT_ROCKET_LAUNCHER)
- {
- self.currentammo = self.ammo_rockets;
- self.weaponmodel = "progs/v_rock2.mdl";
- self.weaponframe = 0;
- self.items = self.items | IT_ROCKETS;
- }
- else if (self.weapon == IT_LIGHTNING)
- {
- self.currentammo = self.ammo_cells;
- self.weaponmodel = "progs/v_light.mdl";
- self.weaponframe = 0;
- self.items = self.items | IT_CELLS;
- }
- else
- {
- self.currentammo = 0;
- self.weaponmodel = "";
- self.weaponframe = 0;
- }
- };
- float() W_BestWeapon =
- {
- local float it;
-
- it = self.items;
- if (self.waterlevel <= 1 && self.ammo_cells >= 1 && (it & IT_LIGHTNING) )
- return IT_LIGHTNING;
- else if(self.ammo_nails >= 2 && (it & IT_SUPER_NAILGUN) )
- return IT_SUPER_NAILGUN;
- else if(self.ammo_shells >= 2 && (it & IT_SUPER_SHOTGUN) )
- return IT_SUPER_SHOTGUN;
- else if(self.ammo_nails >= 1 && (it & IT_NAILGUN) )
- return IT_NAILGUN;
- else if(self.ammo_shells >= 1 && (it & IT_SHOTGUN) )
- return IT_SHOTGUN;
-
- /*
- if(self.ammo_rockets >= 1 && (it & IT_ROCKET_LAUNCHER) )
- return IT_ROCKET_LAUNCHER;
- else if(self.ammo_rockets >= 1 && (it & IT_GRENADE_LAUNCHER) )
- return IT_GRENADE_LAUNCHER;
- */
- return IT_AXE;
- };
- float() W_CheckNoAmmo =
- {
- if (self.currentammo > 0)
- return TRUE;
- if (self.weapon == IT_AXE)
- return TRUE;
-
- self.weapon = W_BestWeapon ();
- W_SetCurrentAmmo ();
-
- // drop the weapon down
- return FALSE;
- };
- /*
- ============
- W_Attack
- An attack impulse can be triggered now
- ============
- */
- void() player_axe1;
- void() player_axeb1;
- void() player_axec1;
- void() player_axed1;
- void() player_shot1;
- void() player_nail1;
- void() player_light1;
- void() player_rocket1;
- void() W_Attack =
- {
- local float r;
- if (!W_CheckNoAmmo ())
- return;
- makevectors (self.v_angle); // calculate forward angle for velocity
- self.show_hostile = time + 1; // wake monsters up
- if (self.weapon == IT_AXE)
- {
- self.attack_finished = time + 0.5;
- sound (self, CHAN_WEAPON, "weapons/ax1.wav", 1, ATTN_NORM);
- r = random();
- if (r < 0.25)
- player_axe1 ();
- else if (r<0.5)
- player_axeb1 ();
- else if (r<0.75)
- player_axec1 ();
- else
- player_axed1 ();
- }
- else if (self.weapon == IT_SHOTGUN)
- {
- player_shot1 ();
- self.attack_finished = time + 0.5;
- W_FireShotgun ();
- }
- else if (self.weapon == IT_SUPER_SHOTGUN)
- {
- player_shot1 ();
- self.attack_finished = time + 0.7;
- W_FireSuperShotgun ();
- }
- else if (self.weapon == IT_NAILGUN)
- {
- player_nail1 ();
- }
- else if (self.weapon == IT_SUPER_NAILGUN)
- {
- player_nail1 ();
- }
- else if (self.weapon == IT_GRENADE_LAUNCHER)
- {
- player_rocket1();
- self.attack_finished = time + 0.6;
- W_FireGrenade();
- }
- else if (self.weapon == IT_ROCKET_LAUNCHER)
- {
- player_rocket1();
- self.attack_finished = time + 0.8;
- W_FireRocket();
- }
- else if (self.weapon == IT_LIGHTNING)
- {
- self.attack_finished = time + 0.1;
- sound (self, CHAN_AUTO, "weapons/lstart.wav", 1, ATTN_NORM);
- player_light1();
- }
- };
- /*
- ============
- W_ChangeWeapon
- ============
- */
- void() W_ChangeWeapon =
- {
- local float it, am, fl;
-
- it = self.items;
- am = 0;
-
- if (self.impulse == 1)
- {
- fl = IT_AXE;
- }
- else if (self.impulse == 2)
- {
- fl = IT_SHOTGUN;
- if (self.ammo_shells < 1)
- am = 1;
- }
- else if (self.impulse == 3)
- {
- fl = IT_SUPER_SHOTGUN;
- if (self.ammo_shells < 2)
- am = 1;
- }
- else if (self.impulse == 4)
- {
- fl = IT_NAILGUN;
- if (self.ammo_nails < 1)
- am = 1;
- }
- else if (self.impulse == 5)
- {
- fl = IT_SUPER_NAILGUN;
- if (self.ammo_nails < 2)
- am = 1;
- }
- else if (self.impulse == 6)
- {
- fl = IT_GRENADE_LAUNCHER;
- if (self.ammo_rockets < 1)
- am = 1;
- }
- else if (self.impulse == 7)
- {
- fl = IT_ROCKET_LAUNCHER;
- if (self.ammo_rockets < 1)
- am = 1;
- }
- else if (self.impulse == 8)
- {
- fl = IT_LIGHTNING;
- if (self.ammo_cells < 1)
- am = 1;
- }
- self.impulse = 0;
-
- if (!(self.items & fl))
- { // don't have the weapon or the ammo
- sprint (self, PRINT_HIGH, "no weapon.\n");
- return;
- }
-
- if (am)
- { // don't have the ammo
- sprint (self, PRINT_HIGH, "not enough ammo.\n");
- return;
- }
- //
- // set weapon, set ammo
- //
- self.weapon = fl;
- W_SetCurrentAmmo ();
- };
- /*
- ============
- CheatCommand
- ============
- */
- void() CheatCommand =
- {
- // if (deathmatch || coop)
- return;
- self.ammo_rockets = 100;
- self.ammo_nails = 200;
- self.ammo_shells = 100;
- self.items = self.items |
- IT_AXE |
- IT_SHOTGUN |
- IT_SUPER_SHOTGUN |
- IT_NAILGUN |
- IT_SUPER_NAILGUN |
- IT_GRENADE_LAUNCHER |
- IT_ROCKET_LAUNCHER |
- IT_KEY1 | IT_KEY2;
- self.ammo_cells = 200;
- self.items = self.items | IT_LIGHTNING;
- self.weapon = IT_ROCKET_LAUNCHER;
- self.impulse = 0;
- W_SetCurrentAmmo ();
- };
- /*
- ============
- CycleWeaponCommand
- Go to the next weapon with ammo
- ============
- */
- void() CycleWeaponCommand =
- {
- local float it, am;
-
- it = self.items;
- self.impulse = 0;
- while (1)
- {
- am = 0;
- if (self.weapon == IT_LIGHTNING)
- {
- self.weapon = IT_AXE;
- }
- else if (self.weapon == IT_AXE)
- {
- self.weapon = IT_SHOTGUN;
- if (self.ammo_shells < 1)
- am = 1;
- }
- else if (self.weapon == IT_SHOTGUN)
- {
- self.weapon = IT_SUPER_SHOTGUN;
- if (self.ammo_shells < 2)
- am = 1;
- }
- else if (self.weapon == IT_SUPER_SHOTGUN)
- {
- self.weapon = IT_NAILGUN;
- if (self.ammo_nails < 1)
- am = 1;
- }
- else if (self.weapon == IT_NAILGUN)
- {
- self.weapon = IT_SUPER_NAILGUN;
- if (self.ammo_nails < 2)
- am = 1;
- }
- else if (self.weapon == IT_SUPER_NAILGUN)
- {
- self.weapon = IT_GRENADE_LAUNCHER;
- if (self.ammo_rockets < 1)
- am = 1;
- }
- else if (self.weapon == IT_GRENADE_LAUNCHER)
- {
- self.weapon = IT_ROCKET_LAUNCHER;
- if (self.ammo_rockets < 1)
- am = 1;
- }
- else if (self.weapon == IT_ROCKET_LAUNCHER)
- {
- self.weapon = IT_LIGHTNING;
- if (self.ammo_cells < 1)
- am = 1;
- }
-
- if ( (self.items & self.weapon) && am == 0)
- {
- W_SetCurrentAmmo ();
- return;
- }
- }
- };
- /*
- ============
- CycleWeaponReverseCommand
- Go to the prev weapon with ammo
- ============
- */
- void() CycleWeaponReverseCommand =
- {
- local float it, am;
-
- it = self.items;
- self.impulse = 0;
- while (1)
- {
- am = 0;
- if (self.weapon == IT_LIGHTNING)
- {
- self.weapon = IT_ROCKET_LAUNCHER;
- if (self.ammo_rockets < 1)
- am = 1;
- }
- else if (self.weapon == IT_ROCKET_LAUNCHER)
- {
- self.weapon = IT_GRENADE_LAUNCHER;
- if (self.ammo_rockets < 1)
- am = 1;
- }
- else if (self.weapon == IT_GRENADE_LAUNCHER)
- {
- self.weapon = IT_SUPER_NAILGUN;
- if (self.ammo_nails < 2)
- am = 1;
- }
- else if (self.weapon == IT_SUPER_NAILGUN)
- {
- self.weapon = IT_NAILGUN;
- if (self.ammo_nails < 1)
- am = 1;
- }
- else if (self.weapon == IT_NAILGUN)
- {
- self.weapon = IT_SUPER_SHOTGUN;
- if (self.ammo_shells < 2)
- am = 1;
- }
- else if (self.weapon == IT_SUPER_SHOTGUN)
- {
- self.weapon = IT_SHOTGUN;
- if (self.ammo_shells < 1)
- am = 1;
- }
- else if (self.weapon == IT_SHOTGUN)
- {
- self.weapon = IT_AXE;
- }
- else if (self.weapon == IT_AXE)
- {
- self.weapon = IT_LIGHTNING;
- if (self.ammo_cells < 1)
- am = 1;
- }
-
- if ( (it & self.weapon) && am == 0)
- {
- W_SetCurrentAmmo ();
- return;
- }
- }
- };
- /*
- ============
- ServerflagsCommand
- Just for development
- ============
- */
- void() ServerflagsCommand =
- {
- serverflags = serverflags * 2 + 1;
- };
- /*
- ============
- ImpulseCommands
- ============
- */
- void() ImpulseCommands =
- {
- if (self.impulse >= 1 && self.impulse <= 8)
- W_ChangeWeapon ();
- if (self.impulse == 9)
- CheatCommand ();
- if (self.impulse == 10)
- CycleWeaponCommand ();
- if (self.impulse == 11)
- ServerflagsCommand ();
- if (self.impulse == 12)
- CycleWeaponReverseCommand ();
- self.impulse = 0;
- };
- /*
- ============
- W_WeaponFrame
- Called every frame so impulse events can be handled as well as possible
- ============
- */
- void() W_WeaponFrame =
- {
- if (time < self.attack_finished)
- return;
- ImpulseCommands ();
-
- // check for attack
- if (self.button0)
- {
- SuperDamageSound ();
- W_Attack ();
- }
- };
- /*
- ========
- SuperDamageSound
- Plays sound if needed
- ========
- */
- void() SuperDamageSound =
- {
- if (self.super_damage_finished > time)
- {
- if (self.super_sound < time)
- {
- self.super_sound = time + 1;
- sound (self, CHAN_BODY, "items/damage3.wav", 1, ATTN_NORM);
- }
- }
- return;
- };
|