diff --git a/client.qc b/client.qc index 490ed15..80c6970 100644 --- a/client.qc +++ b/client.qc @@ -903,6 +903,8 @@ void() PlayerPreThink = makevectors (self.v_angle); // is this still used + self.deathtype = ""; + CheckRules (); WaterMove (); /* @@ -1140,9 +1142,9 @@ void() PlayerPostThink = sound (self, CHAN_BODY, "player/h2ojump.wav", 1, ATTN_NORM); else if (self.jump_flag < -650) { + self.deathtype = "falling"; T_Damage (self, world, world, 5); sound (self, CHAN_VOICE, "player/land2.wav", 1, ATTN_NORM); - self.deathtype = "falling"; } else sound (self, CHAN_VOICE, "player/land.wav", 1, ATTN_NORM); @@ -1186,9 +1188,9 @@ void() ClientDisconnect = { // let everyone else know bprint (PRINT_HIGH, self.netname); - bprint (PRINT_HIGH, " left the game with "); - bprint (PRINT_HIGH, ftos(self.frags)); - bprint (PRINT_HIGH, " frags\n"); + bprint (PRINT_HIGH, " left the game with "); + bprint (PRINT_HIGH, ftos(self.frags)); + bprint (PRINT_HIGH, " frags\n"); sound (self, CHAN_BODY, "player/tornoff2.wav", 1, ATTN_NONE); set_suicide_frame (); }; @@ -1200,6 +1202,7 @@ ClientObituary called when a player dies ============ */ + void(entity targ, entity attacker) ClientObituary = { local float rnum; @@ -1208,6 +1211,9 @@ void(entity targ, entity attacker) ClientObituary = local string attackerteam, targteam; rnum = random(); + //ZOID 12-13-96: self.team doesn't work in QW. Use keys + attackerteam = infokey(attacker, "team"); + targteam = infokey(targ, "team"); if (targ.classname == "player") { @@ -1216,7 +1222,6 @@ void(entity targ, entity attacker) ClientObituary = { if (targ.deathtype == "selfwater") { - targ.deathtype = ""; bprint (PRINT_MEDIUM, targ.netname); bprint (PRINT_MEDIUM," electrocutes himself.\n "); targ.frags = targ.frags - 1; @@ -1230,6 +1235,7 @@ void(entity targ, entity attacker) ClientObituary = bprint (PRINT_MEDIUM," was telefragged by "); bprint (PRINT_MEDIUM,attacker.owner.netname); bprint (PRINT_MEDIUM,"\n"); + logfrag (attacker.owner, targ); attacker.owner.frags = attacker.owner.frags + 1; return; @@ -1246,44 +1252,72 @@ void(entity targ, entity attacker) ClientObituary = return; } + // double 666 telefrag (can happen often in deathmatch 4) + if (attacker.classname == "teledeath3") + { + bprint (PRINT_MEDIUM,targ.netname); + bprint (PRINT_MEDIUM," was telefragged by "); + bprint (PRINT_MEDIUM,attacker.owner.netname); + bprint (PRINT_MEDIUM, "'s Satan's power\n"); + targ.frags = targ.frags - 1; + logfrag (targ, targ); + return; + } + + if (targ.deathtype == "squish") { - targ.deathtype = ""; - if (attacker != world) + if (teamplay && targteam == attackerteam && attackerteam != "" && targ != attacker) + { + logfrag (attacker, attacker); + attacker.frags = attacker.frags - 1; + bprint (PRINT_MEDIUM,attacker.netname); + bprint (PRINT_MEDIUM," squished a teammate\n"); + return; + } + else if (attacker.classname == "player" && attacker != targ) { bprint (PRINT_MEDIUM, attacker.netname); bprint (PRINT_MEDIUM," squishes "); bprint (PRINT_MEDIUM,targ.netname); bprint (PRINT_MEDIUM,"\n"); + logfrag (attacker, targ); attacker.frags = attacker.frags + 1; return; } + else + { + logfrag (targ, targ); + targ.frags = targ.frags - 1; // killed self + bprint (PRINT_MEDIUM,targ.netname); + bprint (PRINT_MEDIUM," was squished\n"); + return; + } } if (attacker.classname == "player") { -//ZOID 12-13-96: self.team doesn't work in QW. Use keys - attackerteam = infokey(attacker, "team"); - targteam = infokey(targ, "team"); - if (targ == attacker) { // killed self logfrag (attacker, attacker); attacker.frags = attacker.frags - 1; bprint (PRINT_MEDIUM,targ.netname); - - if (targ.weapon == 64 && targ.waterlevel > 1) - { - bprint (PRINT_MEDIUM," discharges into the water.\n"); - return; - } - if (targ.weapon == 16) + if (targ.deathtype == "grenade") bprint (PRINT_MEDIUM," tries to put the pin back in\n"); - else if (rnum) + else if (targ.deathtype == "rocket") bprint (PRINT_MEDIUM," becomes bored with life\n"); + else if (targ.weapon == 64 && targ.waterlevel > 1) + { + if (targ.watertype == CONTENT_SLIME) + bprint (PRINT_MEDIUM," discharges into the slime\n"); + else if (targ.watertype == CONTENT_LAVA) + bprint (PRINT_MEDIUM," discharges into the lava\n"); + else + bprint (PRINT_MEDIUM," discharges into the water.\n"); + } else - bprint (PRINT_MEDIUM," checks if his weapon is loaded\n"); + bprint (PRINT_MEDIUM," becomes bored with life\n"); return; } else if ( (teamplay == 2) && (targteam == attackerteam) && @@ -1310,32 +1344,17 @@ void(entity targ, entity attacker) ClientObituary = attacker.frags = attacker.frags + 1; rnum = attacker.weapon; - if (rnum == IT_AXE) - { - deathstring = " was ax-murdered by "; - deathstring2 = "\n"; - } - if (rnum == IT_SHOTGUN) - { - deathstring = " chewed on "; - deathstring2 = "'s boomstick\n"; - } - if (rnum == IT_SUPER_SHOTGUN) - { - deathstring = " ate 2 loads of "; - deathstring2 = "'s buckshot\n"; - } - if (rnum == IT_NAILGUN) + if (targ.deathtype == "nail") { deathstring = " was nailed by "; deathstring2 = "\n"; } - if (rnum == IT_SUPER_NAILGUN) + else if (targ.deathtype == "supernail") { deathstring = " was punctured by "; deathstring2 = "\n"; } - if (rnum == IT_GRENADE_LAUNCHER) + else if (targ.deathtype == "grenade") { deathstring = " eats "; deathstring2 = "'s pineapple\n"; @@ -1345,10 +1364,9 @@ void(entity targ, entity attacker) ClientObituary = deathstring2 = "'s grenade\n"; } } - if (rnum == IT_ROCKET_LAUNCHER) + else if (targ.deathtype == "rocket") { - - if (attacker.super_damage_finished > 0) + if (attacker.super_damage_finished > 0 && targ.health < -40) { rnum = random(); if (rnum < 0.3) @@ -1363,10 +1381,7 @@ void(entity targ, entity attacker) ClientObituary = bprint (PRINT_MEDIUM, " a new one\n"); return; } - if (deathmatch == 4) - deathstring2 = "'s OctaRocket!\n"; - else - deathstring2 = "'s quad rocket\n"; + deathstring2 = "'s quad rocket\n"; } else { @@ -1378,10 +1393,23 @@ void(entity targ, entity attacker) ClientObituary = deathstring2 = "'s rocket\n" ; } } - - } - if (rnum == IT_LIGHTNING) + else if (rnum == IT_AXE) + { + deathstring = " was ax-murdered by "; + deathstring2 = "\n"; + } + else if (rnum == IT_SHOTGUN) + { + deathstring = " chewed on "; + deathstring2 = "'s boomstick\n"; + } + else if (rnum == IT_SUPER_SHOTGUN) + { + deathstring = " ate 2 loads of "; + deathstring2 = "'s buckshot\n"; + } + else if (rnum == IT_LIGHTNING) { deathstring = " accepts "; if (attacker.waterlevel > 1) @@ -1438,22 +1466,21 @@ void(entity targ, entity attacker) ClientObituary = bprint (PRINT_MEDIUM," blew up\n"); return; } - if (attacker.solid == SOLID_BSP && attacker != world) - { - bprint (PRINT_MEDIUM," was squished\n"); - return; - } if (targ.deathtype == "falling") { - targ.deathtype = ""; bprint (PRINT_MEDIUM," fell to his death\n"); return; } - if (attacker.classname == "trap_shooter" || attacker.classname == "trap_spikeshooter") + if (targ.deathtype == "nail" || targ.deathtype == "supernail") { bprint (PRINT_MEDIUM," was spiked\n"); return; } + if (targ.deathtype == "laser") + { + bprint (PRINT_MEDIUM," was zapped\n"); + return; + } if (attacker.classname == "fireball") { bprint (PRINT_MEDIUM," ate a lavaball\n"); diff --git a/combat.qc b/combat.qc index f65c19a..f30acd1 100644 --- a/combat.qc +++ b/combat.qc @@ -2,7 +2,7 @@ void() T_MissileTouch; void() info_player_start; void(entity targ, entity attacker) ClientObituary; -void(entity inflictor, entity attacker, float damage, entity ignore) T_RadiusDamage; +void(entity inflictor, entity attacker, float damage, entity ignore, string dtype) T_RadiusDamage; /*SERVER void() monster_death_use; @@ -123,11 +123,11 @@ void(entity targ, entity inflictor, entity attacker, float damage) T_Damage= // check for quad damage powerup on the attacker - if (attacker.super_damage_finished > time) - if (deathmatch == 4) - damage = damage * 8; - else - damage = damage * 4; + if (attacker.super_damage_finished > time && inflictor.classname != "door") + if (deathmatch == 4) + damage = damage * 8; + else + damage = damage * 4; // save damage based on the target's armor level @@ -196,11 +196,13 @@ void(entity targ, entity inflictor, entity attacker, float damage) T_Damage= targteam = infokey(targ, "team"); if ((teamplay == 1) && (targteam == attackerteam) && - (attacker.classname == "player") && (attackerteam != "")) + (attacker.classname == "player") && (attackerteam != "") && + inflictor.classname !="door") return; + if ((teamplay == 3) && (targteam == attackerteam) && (attacker.classname == "player") && (attackerteam != "") && - (targ != attacker)) + (targ != attacker)&& inflictor.classname !="door") return; // do the damage @@ -246,7 +248,7 @@ void(entity targ, entity inflictor, entity attacker, float damage) T_Damage= T_RadiusDamage ============ */ -void(entity inflictor, entity attacker, float damage, entity ignore) T_RadiusDamage = +void(entity inflictor, entity attacker, float damage, entity ignore, string dtype) T_RadiusDamage = { local float points; local entity head; @@ -276,15 +278,11 @@ void(entity inflictor, entity attacker, float damage, entity ignore) T_RadiusDam if (points > 0) { if (CanDamage (head, inflictor)) - { // shambler takes half damage from all explosions - if (head.classname == "monster_shambler") - T_Damage (head, inflictor, attacker, points*0.5); - else - T_Damage (head, inflictor, attacker, points); - + { + head.deathtype = dtype; + T_Damage (head, inflictor, attacker, points); } } - } } head = head.chain; @@ -316,12 +314,7 @@ void(entity attacker, float damage) T_BeamDamage = if (points > 0) { if (CanDamage (head, attacker)) - { - if (head.classname == "monster_shambler") - T_Damage (head, attacker, attacker, points*0.5); - else - T_Damage (head, attacker, attacker, points); - } + T_Damage (head, attacker, attacker, points); } } head = head.chain; diff --git a/doors.qc b/doors.qc index 088e2ee..2cd303d 100644 --- a/doors.qc +++ b/doors.qc @@ -33,7 +33,7 @@ void() door_blocked = { other.deathtype = "squish"; T_Damage (other, self, self.goalentity, self.dmg); - other.deathtype = ""; + // if a door has a negative wait, it would never come back if blocked, // so let it just squash the object to death real fast if (self.wait >= 0) @@ -680,6 +680,7 @@ void () secret_blocked = if (time < self.attack_finished) return; self.attack_finished = time + 0.5; + other.deathtype = "squish"; T_Damage (other, self, self, self.dmg); }; diff --git a/items.qc b/items.qc index c543081..4ae0766 100644 --- a/items.qc +++ b/items.qc @@ -75,7 +75,7 @@ void(float timeleft) DropQuad = local entity item; item = spawn(); - item.origin = self.origin - '0 0 24'; + item.origin = self.origin; item.velocity_z = 300; item.velocity_x = -100 + (random() * 200); @@ -135,7 +135,7 @@ void(float timeleft) DropRing = local entity item; item = spawn(); - item.origin = self.origin - '0 0 24'; + item.origin = self.origin; item.velocity_z = 300; item.velocity_x = -100 + (random() * 200); @@ -1425,7 +1425,7 @@ void() item_artifact_super_damage = self.noise = "items/damage.wav"; setmodel (self, "progs/quaddama.mdl"); if (deathmatch == 4) - self.netname == "OctaPower"; + self.netname = "OctaPower"; else self.netname = "Quad Damage"; self.items = IT_QUAD; diff --git a/misc.qc b/misc.qc index d92b9a9..6ba82b5 100644 --- a/misc.qc +++ b/misc.qc @@ -217,7 +217,7 @@ void() barrel_explode = self.takedamage = DAMAGE_NO; self.classname = "explo_box"; // did say self.owner - T_RadiusDamage (self, self, 160, world); + T_RadiusDamage (self, self, 160, world, ""); WriteByte (MSG_MULTICAST, SVC_TEMPENTITY); WriteByte (MSG_MULTICAST, TE_EXPLOSION); WriteCoord (MSG_MULTICAST, self.origin_x); @@ -316,6 +316,7 @@ void() Laser_Touch = if (other.health) { SpawnBlood (org, 15); + other.deathtype = "laser"; T_Damage (other, self, self.owner, 15); } else diff --git a/plats.qc b/plats.qc index f557bf6..f60081e 100644 --- a/plats.qc +++ b/plats.qc @@ -111,6 +111,7 @@ void() plat_crush = { //dprint ("plat_crush\n"); + other.deathtype = "squish"; T_Damage (other, self, self, 1); if (self.state == STATE_UP) @@ -223,8 +224,10 @@ void() train_blocked = if (time < self.attack_finished) return; self.attack_finished = time + 0.5; + other.deathtype = "squish"; T_Damage (other, self, self, self.dmg); }; + void() train_use = { if (self.think != func_train_find) diff --git a/progs.src b/progs.src index be0cb25..e5b248b 100644 --- a/progs.src +++ b/progs.src @@ -7,6 +7,7 @@ items.qc weapons.qc world.qc client.qc +spectate.qc player.qc doors.qc buttons.qc diff --git a/server.qc b/server.qc index db5d250..031e253 100644 --- a/server.qc +++ b/server.qc @@ -14,6 +14,7 @@ void() monster_fish = {remove(self);}; void() monster_shalrath = {remove(self);}; void() monster_enforcer = {remove(self);}; void() monster_oldone = {remove(self);}; +void() event_lightning = {remove(self);}; /* ============================================================================== diff --git a/spectate.qc b/spectate.qc new file mode 100644 index 0000000..81c6533 --- /dev/null +++ b/spectate.qc @@ -0,0 +1,84 @@ +// Spectator functions +// Added Aug11'97 by Zoid +// +// These functions are called from the server if they exist. +// Note that Spectators only have one think since they movement code doesn't +// track them much. Impulse commands work as usual, but don't call +// the regular ImpulseCommand handler in weapons.qc since Spectators don't +// have any weapons and things can explode. +// +// --- Zoid. + +/* +=========== +SpectatorConnect + +called when a spectator connects to a server +============ +*/ +void() SpectatorConnect = +{ + bprint (PRINT_MEDIUM, "Spectator "); + bprint (PRINT_MEDIUM, self.netname); + bprint (PRINT_MEDIUM, " entered the game\n"); + + self.goalentity = world; // used for impulse 1 below +}; + +/* +=========== +SpectatorDisconnect + +called when a spectator disconnects from a server +============ +*/ +void() SpectatorDisconnect = +{ + bprint (PRINT_MEDIUM, "Spectator "); + bprint (PRINT_MEDIUM, self.netname); + bprint (PRINT_MEDIUM, " left the game\n"); +}; + +/* +================ +SpectatorImpulseCommand + +Called by SpectatorThink if the spectator entered an impulse +================ +*/ +void() SpectatorImpulseCommand = +{ + if (self.impulse == 1) { + // teleport the spectator to the next spawn point + // note that if the spectator is tracking, this doesn't do + // much + self.goalentity = find(self.goalentity, classname, "info_player_deathmatch"); + if (self.goalentity == world) + self.goalentity = find(self.goalentity, classname, "info_player_deathmatch"); + if (self.goalentity != world) { + setorigin(self, self.goalentity.origin); + self.angles = self.goalentity.angles; + self.fixangle = TRUE; // turn this way immediately + } + } + + self.impulse = 0; +}; + +/* +================ +SpectatorThink + +Called every frame after physics are run +================ +*/ +void() SpectatorThink = +{ + // self.origin, etc contains spectator position, so you could + // do some neat stuff here + + if (self.impulse) + SpectatorImpulseCommand(); +}; + + diff --git a/triggers.qc b/triggers.qc index cc89df1..b428ca8 100644 --- a/triggers.qc +++ b/triggers.qc @@ -318,16 +318,28 @@ void(vector org) spawn_tfog = void() tdeath_touch = { + local entity other2; + if (other == self.owner) return; // frag anyone who teleports in on top of an invincible player if (other.classname == "player") { + if (other.invincible_finished > time && + self.owner.invincible_finished > time) { + self.classname = "teledeath3"; + other.invincible_finished = 0; + self.owner.invincible_finished = 0; + T_Damage (other, self, self, 50000); + other2 = self.owner; + self.owner = other; + T_Damage (other2, self, self, 50000); + } + if (other.invincible_finished > time) + { self.classname = "teledeath2"; - if (self.owner.classname != "player") - { // other monsters explode themselves T_Damage (self.owner, self, self, 50000); return; } diff --git a/weapons.qc b/weapons.qc index fe8d3d2..3ff892f 100644 --- a/weapons.qc +++ b/weapons.qc @@ -2,7 +2,7 @@ */ void (entity targ, entity inflictor, entity attacker, float damage) T_Damage; void () player_run; -void(entity bomb, entity attacker, float rad, entity ignore) T_RadiusDamage; +void(entity bomb, entity attacker, float rad, entity ignore, string dtype) T_RadiusDamage; void(vector org, float damage) SpawnBlood; void() SuperDamageSound; @@ -386,8 +386,7 @@ void() T_MissileTouch = if (other.health) { - if (other.classname == "monster_shambler") - damg = damg * 0.5; // mostly immune + other.deathtype = "rocket"; T_Damage (other, self, self.owner, damg ); } @@ -395,10 +394,9 @@ void() T_MissileTouch = // was done in the impact - T_RadiusDamage (self, self.owner, 120, other); + T_RadiusDamage (self, self.owner, 120, other, "rocket"); - -// sound (self, CHAN_WEAPON, "weapons/r_exp3.wav", 1, ATTN_NORM); +// sound (self, CHAN_WEAPON, "weapons/r_exp3.wav", 1, ATTN_NORM); self.origin = self.origin - 8 * normalize(self.velocity); WriteByte (MSG_MULTICAST, SVC_TEMPENTITY); @@ -446,7 +444,7 @@ void() W_FireRocket = // set newmis duration newmis.nextthink = time + 5; newmis.think = SUB_Remove; - newmis.classname = "grenade"; + newmis.classname = "rocket"; setmodel (newmis, "progs/missile.mdl"); setsize (newmis, '0 0 0', '0 0 0'); @@ -545,7 +543,7 @@ void() W_FireLightning = cells = self.ammo_cells; self.ammo_cells = 0; W_SetCurrentAmmo (); - T_RadiusDamage (self, self, 35*cells, world); + T_RadiusDamage (self, self, 35*cells, world, ""); return; } } @@ -554,7 +552,7 @@ void() W_FireLightning = cells = self.ammo_cells; self.ammo_cells = 0; W_SetCurrentAmmo (); - T_RadiusDamage (self, self, 35*cells, world); + T_RadiusDamage (self, self, 35*cells, world,""); return; } } @@ -599,8 +597,7 @@ void() GrenadeExplode = } self.voided = 1; - - T_RadiusDamage (self, self.owner, 120, world); + T_RadiusDamage (self, self.owner, 120, world, "grenade"); WriteByte (MSG_MULTICAST, SVC_TEMPENTITY); WriteByte (MSG_MULTICAST, TE_EXPLOSION); @@ -796,6 +793,7 @@ local float rand; if (other.takedamage) { spawn_touchblood (9); + other.deathtype = "nail"; T_Damage (other, self, self.owner, 9); } else @@ -842,6 +840,7 @@ local float rand; if (other.takedamage) { spawn_touchblood (18); + other.deathtype = "supernail"; T_Damage (other, self, self.owner, 18); } else