mirror of
https://github.com/nzp-team/quakec.git
synced 2025-02-16 17:10:55 +00:00
SERVER: Revamps wunderwaffe logic
This commit is contained in:
parent
f0e1a9c4f4
commit
d156216f42
8 changed files with 496 additions and 325 deletions
|
@ -34,6 +34,7 @@
|
|||
../source/server/weapons/frames_core.qc
|
||||
../source/server/weapons/rocket_launcher.qc
|
||||
../source/server/weapons/ray_gun.qc
|
||||
../source/server/weapons/tesla.qc
|
||||
../source/server/weapons/flamethrower.qc
|
||||
../source/server/weapons/grenade_launcher.qc
|
||||
../source/server/weapons/weapon_core.qc
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
../source/server/weapons/frames_core.qc
|
||||
../source/server/weapons/rocket_launcher.qc
|
||||
../source/server/weapons/ray_gun.qc
|
||||
../source/server/weapons/tesla.qc
|
||||
../source/server/weapons/flamethrower.qc
|
||||
../source/server/weapons/grenade_launcher.qc
|
||||
../source/server/weapons/weapon_core.qc
|
||||
|
|
|
@ -139,6 +139,21 @@ void() crawler_die1 =[ 0, crawler_die2] {SetZombieHitBox(CRAWLER_BBOX);self.f
|
|||
void() crawler_die2 =[ 1, crawler_die3] {self.frame = 38;};
|
||||
void() crawler_die3 =[ 2, SUB_Null] {self.iszomb = 0; self.frame = 39;self.nextthink = time + 3;self.think = removeZombie; addmoney(other, 60, true); if (crawler_num > 0) {crawler_num = crawler_num - 1;}};
|
||||
|
||||
//====================== Crawler Tesla Death ============================
|
||||
void() crawler_death_wunder1 =[ 72, crawler_death_wunder2 ] {tesla_arc(); play_sound_z(4); };
|
||||
void() crawler_death_wunder2 =[ 73, crawler_death_wunder3 ] {tesla_arc(); };
|
||||
void() crawler_death_wunder3 =[ 74, crawler_death_wunder4 ] {tesla_arc(); };
|
||||
void() crawler_death_wunder4 =[ 75, crawler_death_wunder5 ] {tesla_arc(); };
|
||||
void() crawler_death_wunder5 =[ 76, crawler_death_wunder6 ] {tesla_arc(); };
|
||||
void() crawler_death_wunder6 =[ 77, crawler_death_wunder7 ] {tesla_arc(); };
|
||||
void() crawler_death_wunder7 =[ 73, crawler_death_wunder8 ] {tesla_arc(); };
|
||||
void() crawler_death_wunder8 =[ 74, crawler_death_wunder9 ] {tesla_arc(); };
|
||||
void() crawler_death_wunder9 =[ 75, crawler_death_wunder10 ] {tesla_arc(); };
|
||||
void() crawler_death_wunder10 =[ 40, SUB_Null ] {tesla_arc(); self.iszomb = 0; self.nextthink = time + 3; self.think = removeZombie;};
|
||||
|
||||
|
||||
|
||||
|
||||
//======================== Climb Over Barricade ====================
|
||||
//40-70
|
||||
void() crawler_climbBarricade1 =[ 0, crawler_climbBarricade2] {self.movetype = MOVETYPE_STEP;self.zoom = 1;self.frame = 40;Zombie_Think();};
|
||||
|
@ -236,6 +251,7 @@ void(entity who) makeCrawler =
|
|||
who.th_melee = zombie_attack;
|
||||
who.th_idle = crawler_idle1;
|
||||
who.th_windowhop = crawler_climbBarricade1;
|
||||
who.th_diewunder = Zombie_Tesla_Death;
|
||||
|
||||
who.th_fall = crawler_fall1;
|
||||
who.th_land = crawler_land1;
|
||||
|
|
|
@ -85,19 +85,6 @@ $frame dogdeath1 dogdeath2
|
|||
void() dog_deathanim =[ $dogdeath1, dog_deathanim2 ] {self.frame = 35;};
|
||||
void() dog_deathanim2 =[ $dogdeath2, SUB_Null ] {self.nextthink = time + 3; self.think = removeZombie; self.frame = 36;};
|
||||
|
||||
// DOG WAFFE DEATH
|
||||
// 37-46
|
||||
$frame dogwunder1 dogwunder2 dogwunder3 dogwunder4 dogwunder5 dogwunder6 dogwunder7 dogwunder8 dogwunder9 dogwunder10
|
||||
void() die_dog_wunder1 =[ $dogwunder1, die_dog_wunder2 ] {Zombie_Walk(0);Zombie_Tesla_Light();self.frame = 37;};
|
||||
void() die_dog_wunder2 =[ $dogwunder2, die_dog_wunder3 ] {Zombie_Walk(0);self.frame = 38;};
|
||||
void() die_dog_wunder3 =[ $dogwunder3, die_dog_wunder4 ] {Zombie_Walk(0);self.frame = 39;};
|
||||
void() die_dog_wunder4 =[ $dogwunder4, die_dog_wunder5 ] {Zombie_Walk(0);self.frame = 40;};
|
||||
void() die_dog_wunder5 =[ $dogwunder5, die_dog_wunder6 ] {Zombie_Walk(0);self.frame = 41;};
|
||||
void() die_dog_wunder6 =[ $dogwunder6, die_dog_wunder7 ] {Zombie_Walk(0);Zombie_Find_Tesla_Target();self.frame = 42;};
|
||||
void() die_dog_wunder7 =[ $dogwunder7, die_dog_wunder8 ] {Zombie_Walk(0);self.frame = 43;};
|
||||
void() die_dog_wunder8 =[ $dogwunder8, die_dog_wunder9 ] {Zombie_Walk(0);self.frame = 44;};
|
||||
void() die_dog_wunder9 =[ $dogwunder9, die_dog_wunder10 ] {Zombie_Walk(0);self.frame = 45;};
|
||||
void() die_dog_wunder10 =[ $dogwunder10, die_dog_wunder10 ] {Zombie_Walk(0);self.frame = 46;self.health = 0; self.th_die();};
|
||||
|
||||
// DOG LIGHTNING SPAWN
|
||||
// 1-13
|
||||
|
@ -144,33 +131,38 @@ void() Dog_Think =
|
|||
}
|
||||
|
||||
float dogCount;
|
||||
void() Dog_Death =
|
||||
{
|
||||
self.aistatus = "0";
|
||||
self.solid = SOLID_NOT;
|
||||
self.movetype = MOVETYPE_NONE;
|
||||
self.takedamage = DAMAGE_NO;
|
||||
|
||||
|
||||
void(entity ent) Dog_Death_Cleanup = {
|
||||
// Already dead
|
||||
if(ent.aistatus == "0") {
|
||||
return;
|
||||
}
|
||||
ent.aistatus = "0";
|
||||
ent.solid = SOLID_NOT;
|
||||
ent.movetype = MOVETYPE_NONE;
|
||||
ent.takedamage = DAMAGE_NO;
|
||||
|
||||
sound(self, 5, "sounds/null.wav", 1, ATTN_NORM);
|
||||
sound(ent, 5, "sounds/null.wav", 1, ATTN_NORM);
|
||||
|
||||
self.usedent = world;
|
||||
|
||||
self.health = 0;
|
||||
ent.usedent = world;
|
||||
ent.health = 0;
|
||||
Remaining_Zombies = Remaining_Zombies - 1;
|
||||
dogCount -= 1;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void() Dog_Death = {
|
||||
Dog_Death_Cleanup(self);
|
||||
play_sound_z(3);
|
||||
//Gotta' make sure we set it back down instead of glitching it up, yo'
|
||||
if(self.s_time > 0 && sounds_playing > 0)
|
||||
{
|
||||
if(self.s_time > 0 && sounds_playing > 0) {
|
||||
sounds_playing --;
|
||||
self.s_time = 0;
|
||||
}
|
||||
|
||||
if (rounds == dogRound)
|
||||
{
|
||||
if (!Remaining_Zombies)
|
||||
Spawn_Powerup(self.origin + '0 0 12', PU_MAXAMMO);
|
||||
if(rounds == dogRound && Remaining_Zombies == 0) {
|
||||
Spawn_Powerup(self.origin + '0 0 12', PU_MAXAMMO);
|
||||
}
|
||||
|
||||
float r = random();
|
||||
|
@ -178,15 +170,43 @@ void() Dog_Death =
|
|||
// explode chance
|
||||
if (r < 0.75 || self.electro_targeted == true) {
|
||||
self.frame = 0;
|
||||
setmodel (self, "models/sprites/explosion.spr");
|
||||
setmodel(self, "models/sprites/explosion.spr");
|
||||
sound (self, CHAN_VOICE, "sounds/weapons/grenade/explode.wav", 1, ATTN_NORM);
|
||||
dog_explodeanim();
|
||||
} else {
|
||||
dog_deathanim();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
// DOG WAFFE DEATH
|
||||
// 37-46
|
||||
void() dog_die_wunder1 =[ 37, dog_die_wunder2 ] {tesla_arc();};
|
||||
void() dog_die_wunder2 =[ 38, dog_die_wunder3 ] {tesla_arc();};
|
||||
void() dog_die_wunder3 =[ 39, dog_die_wunder4 ] {tesla_arc();};
|
||||
void() dog_die_wunder4 =[ 40, dog_die_wunder5 ] {tesla_arc();};
|
||||
void() dog_die_wunder5 =[ 41, dog_die_wunder6 ] {tesla_arc();};
|
||||
void() dog_die_wunder6 =[ 42, dog_die_wunder7 ] {tesla_arc();};
|
||||
void() dog_die_wunder7 =[ 43, dog_die_wunder8 ] {tesla_arc();};
|
||||
void() dog_die_wunder8 =[ 44, dog_die_wunder9 ] {tesla_arc();};
|
||||
void() dog_die_wunder9 =[ 45, dog_die_wunder10 ] {tesla_arc();};
|
||||
void() dog_die_wunder10 =[ 46, SUB_Null ] {print("ayoooo\n");tesla_arc(); self.iszomb=0; self.nextthink=time+3; self.think=removeZombie;};
|
||||
|
||||
|
||||
void() Dog_Death_Tesla = {
|
||||
Dog_Death_Cleanup(self);
|
||||
// TODO - place tesla spark correctly
|
||||
tesla_spark(self.origin);
|
||||
|
||||
if(rounds == dogRound && Remaining_Zombies == 0) {
|
||||
Spawn_Powerup(self.origin + '0 0 12', PU_MAXAMMO);
|
||||
}
|
||||
|
||||
dog_die_wunder1();
|
||||
};
|
||||
|
||||
|
||||
|
||||
void(entity where) spawn_a_dogB =
|
||||
{
|
||||
local entity sdog;//USED FOR WHAT TO SPAWN
|
||||
|
@ -242,7 +262,7 @@ void(entity where) spawn_a_dogB =
|
|||
|
||||
sdog.th_melee = dog_meleeanim;
|
||||
sdog.th_idle = dog_idleanim;
|
||||
sdog.th_diewunder = die_dog_wunder1;
|
||||
sdog.th_diewunder = Dog_Death_Tesla;
|
||||
|
||||
sdog.electro_targeted = 0;
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@ void() Zombie_Walk_Setup;
|
|||
void() crawler_rip_board1;
|
||||
void() crawler_da1;
|
||||
void() crawler_die1;
|
||||
void() crawler_death_wunder1;
|
||||
void() LinkZombiesHitbox;
|
||||
|
||||
|
||||
|
@ -1027,7 +1028,7 @@ void() removeZombie =
|
|||
self.flags = 0;
|
||||
self.crawling = 0;
|
||||
self.bleedingtime = 0;
|
||||
self.iszomb = 0;
|
||||
self.iszomb = 0; // 1 for alive AI, 0 for corpses / unallocated reserevd ents
|
||||
self.owner = world;
|
||||
|
||||
self.spawnflags = 0;
|
||||
|
@ -1095,46 +1096,55 @@ void() zombie_deathC8 =[ $deathC8, zombie_deathC9 ] {self.frame = 146;zombie_
|
|||
void() zombie_deathC9 =[ $deathC9, zombie_deathC10 ] {self.frame = 147;};
|
||||
void() zombie_deathC10 =[ $deathC10, SUB_Null ] {self.iszomb = 0; self.nextthink = time + 3; self.think = removeZombie; self.frame = 148;};
|
||||
|
||||
void() Zombie_Death =
|
||||
{
|
||||
self.aistatus = "0";
|
||||
self.solid = SOLID_NOT;
|
||||
self.movetype = MOVETYPE_NONE;
|
||||
self.takedamage = DAMAGE_NO;
|
||||
|
||||
self.head.solid = SOLID_NOT;
|
||||
self.head.movetype = MOVETYPE_NONE;
|
||||
self.head.takedamage = DAMAGE_NO;
|
||||
self.larm.solid = SOLID_NOT;
|
||||
self.larm.movetype = MOVETYPE_NONE;
|
||||
self.larm.takedamage = DAMAGE_NO;
|
||||
self.rarm.solid = SOLID_NOT;
|
||||
self.rarm.movetype = MOVETYPE_NONE;
|
||||
self.rarm.takedamage = DAMAGE_NO;
|
||||
|
||||
// ...
|
||||
sound(self, CHAN_WEAPON, "sounds/null.wav" ,1, ATTN_NORM);
|
||||
sound(self, CHAN_VOICE, "sounds/null.wav" ,1, ATTN_NORM);
|
||||
sound(self, CHAN_BODY, "sounds/null.wav" ,1, ATTN_NORM);
|
||||
sound(self, CHAN_ITEM, "sounds/null.wav" ,1, ATTN_NORM);
|
||||
|
||||
void(entity ent) Zombie_Death_Cleanup = {
|
||||
// Already dead
|
||||
if(ent.aistatus == "0") {
|
||||
return;
|
||||
}
|
||||
ent.aistatus = "0";
|
||||
ent.solid = SOLID_NOT;
|
||||
ent.movetype = MOVETYPE_NONE;
|
||||
ent.takedamage = DAMAGE_NO;
|
||||
|
||||
self.usedent = world;
|
||||
ent.head.solid = SOLID_NOT;
|
||||
ent.head.movetype = MOVETYPE_NONE;
|
||||
ent.head.takedamage = DAMAGE_NO;
|
||||
ent.larm.solid = SOLID_NOT;
|
||||
ent.larm.movetype = MOVETYPE_NONE;
|
||||
ent.larm.takedamage = DAMAGE_NO;
|
||||
ent.rarm.solid = SOLID_NOT;
|
||||
ent.rarm.movetype = MOVETYPE_NONE;
|
||||
ent.rarm.takedamage = DAMAGE_NO;
|
||||
|
||||
sound(ent, CHAN_WEAPON, "sounds/null.wav" ,1, ATTN_NORM);
|
||||
sound(ent, CHAN_VOICE, "sounds/null.wav" ,1, ATTN_NORM);
|
||||
sound(ent, CHAN_BODY, "sounds/null.wav" ,1, ATTN_NORM);
|
||||
sound(ent, CHAN_ITEM, "sounds/null.wav" ,1, ATTN_NORM);
|
||||
|
||||
if(self.goalentity.classname == "window")
|
||||
ent.usedent = world;
|
||||
|
||||
if(ent.goalentity.classname == "window")
|
||||
{
|
||||
if(self.goalentity.box1owner == self)
|
||||
self.goalentity.box1owner = world;
|
||||
if(self.goalentity.box2owner == self)
|
||||
self.goalentity.box2owner = world;
|
||||
if(self.goalentity.box3owner == self)
|
||||
self.goalentity.box3owner = world;
|
||||
if(self.goalentity.usedent == self)
|
||||
self.goalentity.usedent = world;
|
||||
if(ent.goalentity.box1owner == ent)
|
||||
ent.goalentity.box1owner = world;
|
||||
if(ent.goalentity.box2owner == ent)
|
||||
ent.goalentity.box2owner = world;
|
||||
if(ent.goalentity.box3owner == ent)
|
||||
ent.goalentity.box3owner = world;
|
||||
if(ent.goalentity.usedent == ent)
|
||||
ent.goalentity.usedent = world;
|
||||
}
|
||||
|
||||
|
||||
self.health = 0;
|
||||
ent.health = 0;
|
||||
Remaining_Zombies = Remaining_Zombies - 1;
|
||||
}
|
||||
|
||||
|
||||
void() Zombie_Death =
|
||||
{
|
||||
Zombie_Death_Cleanup(self);
|
||||
|
||||
// Death Noises
|
||||
if (self.electro_targeted == false)
|
||||
|
@ -1174,7 +1184,7 @@ void() Zombie_Death =
|
|||
{
|
||||
zombie_deathA1();
|
||||
}
|
||||
else if(random() < 0.6)
|
||||
else if(random() < 0.5)
|
||||
{
|
||||
zombie_deathB1();
|
||||
}
|
||||
|
@ -1190,7 +1200,6 @@ void() Zombie_Death =
|
|||
// Electric Damage
|
||||
// --------------------
|
||||
//
|
||||
void() Zombie_Tesla_Light;
|
||||
|
||||
//
|
||||
// Z_ElectroShock
|
||||
|
@ -1206,7 +1215,13 @@ void() Z_ElectroShock =
|
|||
self.death_timer_activated = true;
|
||||
|
||||
// Spawn a Sparkle
|
||||
Zombie_Tesla_Light();
|
||||
if(self.crawling == true) {
|
||||
tesla_spark(self.origin - '0 0 18');
|
||||
}
|
||||
else {
|
||||
tesla_spark(self.origin + '0 0 13');
|
||||
}
|
||||
// Zombie_Tesla_Light();
|
||||
|
||||
// Decide what to Gib
|
||||
float r = random();
|
||||
|
@ -1256,129 +1271,48 @@ void() Z_ElectroShock =
|
|||
|
||||
/////////////////////ZOMBIE WAFFE STUFF/////////////////////
|
||||
|
||||
void() Zombie_Lightning_Think =
|
||||
{
|
||||
self.frame++;
|
||||
|
||||
if (self.frame >= 3)
|
||||
self.frame = 0;
|
||||
|
||||
// suicide timer!
|
||||
if(self.ltime < time) {
|
||||
remove(self);
|
||||
}
|
||||
|
||||
self.nextthink = time + 0.05;
|
||||
}
|
||||
|
||||
void() Zombie_Tesla_Light =
|
||||
{
|
||||
// lightning sprite
|
||||
local entity lightning = spawn();
|
||||
setmodel(lightning, "models/sprites/lightning.spr");
|
||||
setorigin(lightning, self.origin + '0 0 13');
|
||||
lightning.think = Zombie_Lightning_Think;
|
||||
lightning.nextthink = time + 0.05;
|
||||
lightning.ltime = time + 1;
|
||||
}
|
||||
|
||||
void() Zombie_Find_Tesla_Target =
|
||||
{
|
||||
entity zombs = findradius(self.origin, 200);
|
||||
entity tempe;
|
||||
vector org;
|
||||
vector targetorg;
|
||||
float break_loop;
|
||||
|
||||
if (self.teslacount > 10)
|
||||
return;
|
||||
|
||||
break_loop = false;
|
||||
while(break_loop == false) {
|
||||
|
||||
if (zombs == world) {
|
||||
break_loop = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (zombs.classname == "ai_zombie" || zombs.classname == "ai_dog") {
|
||||
break_loop = true;
|
||||
|
||||
zombs.firer = self.firer;
|
||||
|
||||
// remove libs
|
||||
if (zombs.head)
|
||||
setmodel(zombs.head, "");
|
||||
if (zombs.larm)
|
||||
setmodel(zombs.larm, "");
|
||||
if (zombs.rarm)
|
||||
setmodel(zombs.rarm, "");
|
||||
|
||||
// add 50pts
|
||||
addmoney(self.firer, 50, true);
|
||||
|
||||
// kill
|
||||
self.firer.kills += 1;
|
||||
|
||||
// add to tesla count
|
||||
zombs.teslacount = self.teslacount + 1;
|
||||
|
||||
// classname change
|
||||
zombs.classname = "wunder";
|
||||
zombs.head.classname = zombs.larm.classname =
|
||||
zombs.rarm.classname = "wunder_limb";
|
||||
|
||||
// just to be extra careful
|
||||
zombs.takedamage = zombs.head.takedamage =
|
||||
zombs.larm.takedamage = zombs.rarm.takedamage = DAMAGE_NO;
|
||||
|
||||
org = self.origin + '0 0 13';
|
||||
targetorg = zombs.origin + '0 0 13';
|
||||
|
||||
// shoot lightning
|
||||
|
||||
#ifdef FTE
|
||||
|
||||
te_lightning2(self, org, targetorg);
|
||||
|
||||
#else
|
||||
|
||||
WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
|
||||
WriteByte (MSG_BROADCAST, TE_LIGHTNING2);
|
||||
WriteEntity (MSG_BROADCAST, self);
|
||||
WriteCoord (MSG_BROADCAST, org_x);
|
||||
WriteCoord (MSG_BROADCAST, org_y);
|
||||
WriteCoord (MSG_BROADCAST, org_z);
|
||||
WriteCoord (MSG_BROADCAST, targetorg_x);
|
||||
WriteCoord (MSG_BROADCAST, targetorg_y);
|
||||
WriteCoord (MSG_BROADCAST, targetorg_z);
|
||||
|
||||
#endif // FTE
|
||||
|
||||
// anim play
|
||||
tempe = self;
|
||||
self = zombs;
|
||||
self.th_diewunder();
|
||||
self = tempe;
|
||||
}
|
||||
zombs = zombs.chain;
|
||||
}
|
||||
}
|
||||
|
||||
// Wunder'd
|
||||
// 149-152 (FIXME - animate wunder'd zombies)
|
||||
$frame wunder1 wunder2 wunder3 wunder4 wunder5 wunder6 wunder7 wunder8 wunder9 wunder10
|
||||
|
||||
void() zombie_wunder1 =[ $wunder1, zombie_wunder2 ] {play_sound_z(4);Zombie_Tesla_Light();Zombie_Walk(0);self.frame = 149;self.solid = SOLID_NOT;};
|
||||
void() zombie_wunder2 =[ $wunder2, zombie_wunder3 ] {Zombie_Walk(0);self.frame = 150;};
|
||||
void() zombie_wunder3 =[ $wunder3, zombie_wunder4 ] {Zombie_Walk(0);Zombie_Find_Tesla_Target();self.frame = 151;};
|
||||
void() zombie_wunder4 =[ $wunder4, zombie_wunder5 ] {Zombie_Walk(0);self.frame = 152;};
|
||||
void() zombie_wunder5 =[ $wunder5, zombie_wunder6 ] {Zombie_Walk(0);self.frame = 151;};
|
||||
void() zombie_wunder6 =[ $wunder6, zombie_wunder7 ] {Zombie_Walk(0);self.frame = 152;};
|
||||
void() zombie_wunder7 =[ $wunder7, zombie_wunder8 ] {Zombie_Walk(0);self.frame = 151;};
|
||||
void() zombie_wunder8 =[ $wunder8, zombie_wunder9 ] {play_sound_z(3);Zombie_Walk(0);self.frame = 152;};
|
||||
void() zombie_wunder9 =[ $wunder9, zombie_wunder10 ] {Zombie_Walk(0);self.frame = 151;};
|
||||
void() zombie_wunder10 =[ $wunder10, SUB_Null ] {self.health = 0; self.th_die();Zombie_Walk(0);self.frame = 152;};
|
||||
void() zombie_wunder1 =[ $wunder1, zombie_wunder2 ] {tesla_arc(); play_sound_z(4); self.frame = 149;};
|
||||
void() zombie_wunder2 =[ $wunder2, zombie_wunder3 ] {tesla_arc(); self.frame = 150;};
|
||||
void() zombie_wunder3 =[ $wunder3, zombie_wunder4 ] {tesla_arc(); self.frame = 151;};
|
||||
void() zombie_wunder4 =[ $wunder4, zombie_wunder5 ] {tesla_arc(); self.frame = 152;};
|
||||
void() zombie_wunder5 =[ $wunder5, zombie_wunder6 ] {tesla_arc(); self.frame = 151;};
|
||||
void() zombie_wunder6 =[ $wunder6, zombie_wunder7 ] {tesla_arc(); self.frame = 152;};
|
||||
void() zombie_wunder7 =[ $wunder7, zombie_wunder8 ] {tesla_arc(); self.frame = 151;};
|
||||
void() zombie_wunder8 =[ $wunder8, zombie_wunder9 ] {tesla_arc(); play_sound_z(3); self.frame = 152;};
|
||||
void() zombie_wunder9 =[ $wunder9, zombie_wunder10 ] {tesla_arc(); self.frame = 151;};
|
||||
void() zombie_wunder10 =[ $wunder10, SUB_Null ] {
|
||||
tesla_arc(); self.iszomb = 0; self.nextthink = time + 3; self.think = removeZombie;self.frame = 152;
|
||||
// Play final death anim:
|
||||
if(random() < 0.3) {
|
||||
zombie_deathA1();
|
||||
}
|
||||
else if(random() < 0.5) {
|
||||
zombie_deathB1();
|
||||
}
|
||||
else {
|
||||
zombie_deathC1();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
void() Zombie_Tesla_Death = {
|
||||
Zombie_Death_Cleanup(self);
|
||||
if(self.crawling == true) {
|
||||
tesla_spark(self.origin - '0 0 18');
|
||||
crawler_death_wunder1();
|
||||
}
|
||||
else {
|
||||
tesla_spark(self.origin + '0 0 13');
|
||||
zombie_wunder1();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/////////////////////ZOMBIE SPAWNING/////////////////////
|
||||
void() zombieRise =
|
||||
|
@ -1551,12 +1485,11 @@ void(float i) spawnSingleZombEnt =
|
|||
zSpawn.rarm.takedamage = DAMAGE_NO;
|
||||
|
||||
#ifndef FTE
|
||||
|
||||
updateLimb (zSpawn, 2, zSpawn.rarm);
|
||||
|
||||
#endif
|
||||
#endif // FTE
|
||||
|
||||
};
|
||||
|
||||
void(entity szombie) SetUpHitBoxes =
|
||||
{
|
||||
szombie.head.solid = SOLID_CORPSE;
|
||||
|
@ -1740,7 +1673,7 @@ void(entity where) spawn_a_zombieB =
|
|||
szombie.th_fall = zombie_fall1;
|
||||
szombie.th_land = zombie_land1;
|
||||
|
||||
szombie.th_diewunder = zombie_wunder1;
|
||||
szombie.th_diewunder = Zombie_Tesla_Death;
|
||||
|
||||
//szombie.th_jump = zombie_jump1;
|
||||
//szombie.th_grabledge = zombie_grabledge1;
|
||||
|
|
|
@ -149,6 +149,7 @@ void() W_SprintStop;
|
|||
void SwitchWeapon(float to);
|
||||
void GetUp();
|
||||
void Weapon_Logic();
|
||||
void (float shotcount, float sprd, float Damage, float side) FireTrace;
|
||||
.float downed;
|
||||
.float fire_delay;
|
||||
.float fire_delay2;
|
||||
|
@ -275,7 +276,18 @@ float zombie_spawn_timer; // the actual timer for spawn delay
|
|||
.vector idlebox;
|
||||
.vector hop_spot;//used for windows (zombies hop to these)
|
||||
.vector goalorigin;
|
||||
.float teslacount;
|
||||
|
||||
.float teslacount; // TODO - Remove this
|
||||
|
||||
.float tesla_n_kills; // Player - Number of kills remaining for the current tesla shot
|
||||
.float tesla_next_arc_time; // Zombie - Time at which zombie should try arcing
|
||||
.float tesla_arc_num; // Zombie - current arc number
|
||||
.entity tesla_arc_parent; // Zombie - Track the entity that we arced from
|
||||
.entity tesla_arc_owner; // Zombie - Player ent that fired the tesla
|
||||
void(vector pos) tesla_spark;
|
||||
|
||||
|
||||
|
||||
.float iszomb;
|
||||
.float onfire;
|
||||
.entity firer;
|
||||
|
|
319
source/server/weapons/tesla.qc
Normal file
319
source/server/weapons/tesla.qc
Normal file
|
@ -0,0 +1,319 @@
|
|||
/*
|
||||
server/weapons/tesla.qc
|
||||
|
||||
Core logic for the Wunderwaffe special weapon.
|
||||
|
||||
Copyright (C) 2021-2022 NZ:P Team
|
||||
|
||||
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
|
||||
|
||||
|
||||
*/
|
||||
|
||||
|
||||
//
|
||||
// Think function for tesla spark sprite spawned at zombie torso
|
||||
//
|
||||
void() tesla_spark_think =
|
||||
{
|
||||
float prev_frame = self.frame;
|
||||
while(self.frame == prev_frame) {
|
||||
self.frame = rint(random()*3);
|
||||
}
|
||||
if(self.ltime < time) {
|
||||
remove(self);
|
||||
}
|
||||
self.nextthink = time + 0.05;
|
||||
}
|
||||
|
||||
//
|
||||
// Tesla spark sprite spawned at zombie torso
|
||||
//
|
||||
void(vector pos) tesla_spark = {
|
||||
local entity lightning = spawn();
|
||||
setmodel(lightning, "models/sprites/lightning.spr");
|
||||
setorigin(lightning, pos);
|
||||
lightning.think = tesla_spark_think;
|
||||
lightning.nextthink = time + 0.05;
|
||||
lightning.ltime = time + 1;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
void(entity hit_ent, entity arc_parent, entity arc_owner, float arc_num, float do_arc) tesla_damage = {
|
||||
// set lib models to null
|
||||
// (if we remove them RelinkZombies will cry)
|
||||
if (hit_ent.head)
|
||||
setmodel(hit_ent.head, "");
|
||||
if (hit_ent.larm)
|
||||
setmodel(hit_ent.larm, "");
|
||||
if (hit_ent.rarm)
|
||||
setmodel(hit_ent.rarm, "");
|
||||
|
||||
hit_ent.velocity.x = 0;
|
||||
hit_ent.velocity.y = 0;
|
||||
|
||||
// window hop fix
|
||||
if (self.state == 1 || self.hop_step != 0) {
|
||||
self.state = self.hop_step = 0;
|
||||
}
|
||||
|
||||
// // change classname so it can't be re-targted
|
||||
// hit_ent.classname = "wunder";
|
||||
|
||||
if(arc_owner != world) {
|
||||
arc_owner.tesla_n_kills += 1;
|
||||
|
||||
// 50 points for waffe kills
|
||||
if(arc_owner.classname == "player") {
|
||||
addmoney(arc_owner, 50, true);
|
||||
}
|
||||
}
|
||||
|
||||
if(do_arc == true) {
|
||||
// float wait_time = lerp(0.2,0.6, random()) * arc_num;
|
||||
// The first zombie does not wait, every arc thereafter does
|
||||
float wait_time = arc_num == 1 ? 0 : lerp(0.2,0.6, random()) * arc_num;
|
||||
hit_ent.tesla_next_arc_time = time + wait_time;
|
||||
// print("Entity ", hit_ent.classname, " set to arc after ",ftos(wait_time)," (t=", ftos(hit_ent.tesla_next_arc_time), ")\n");
|
||||
}
|
||||
else {
|
||||
// print("Entity ", hit_ent.classname, " NOT set to arc at.\n");
|
||||
hit_ent.tesla_next_arc_time = -1;
|
||||
}
|
||||
hit_ent.tesla_arc_parent = arc_parent;
|
||||
hit_ent.tesla_arc_owner = arc_owner;
|
||||
hit_ent.tesla_arc_num = arc_num;
|
||||
// play our wunder-ful anim
|
||||
entity oself = self;
|
||||
self = hit_ent;
|
||||
self.th_diewunder();
|
||||
self = oself;
|
||||
}
|
||||
|
||||
|
||||
vector(entity ent) tesla_arc_ofs_for_ent = {
|
||||
if(ent.classname == "ai_zombie") {
|
||||
if(ent.crawling == true) {
|
||||
return '0 0 -18';
|
||||
}
|
||||
else {
|
||||
return '0 0 20';
|
||||
}
|
||||
}
|
||||
else if(ent.classname == "ai_dog") {
|
||||
return '0 0 0';
|
||||
}
|
||||
|
||||
return '0 0 0';
|
||||
}
|
||||
|
||||
|
||||
// entity cur_ent, entity prev_ent, entity player
|
||||
void() tesla_arc = {
|
||||
if(self.tesla_next_arc_time < 0) {
|
||||
return;
|
||||
}
|
||||
if(self.tesla_next_arc_time > time) {
|
||||
return;
|
||||
}
|
||||
// print("\"",self.classname,"\" arcing ( arcs:",ftos(self.tesla_arc_num)," kills: ",ftos(self.tesla_arc_owner.tesla_n_kills),") for arctime: ");
|
||||
// print(ftos(self.tesla_next_arc_time),"\n");
|
||||
self.tesla_next_arc_time = -1;
|
||||
if(self.tesla_arc_owner.tesla_n_kills >= 10) {
|
||||
// print("\tAt max kills. Stopping.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
self.iszomb = 0;
|
||||
|
||||
// If we can't arc any further, tell parent to keep trying
|
||||
if(self.tesla_arc_num >= 5) {
|
||||
// We already waited, do it immediately
|
||||
self.tesla_arc_parent.tesla_next_arc_time = 0;
|
||||
// print("\tAt max arc-counts, keep arcing from parent.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// Maximum arcing distance for this zombie
|
||||
float max_dist = 300 - (20 * self.tesla_arc_num);
|
||||
// print("\tZombie arc to max dist: ", ftos(max_dist), "\n");
|
||||
|
||||
entity best_ent = world;
|
||||
if(max_dist > 0) {
|
||||
// If arcing, find the closest zombie to current zombie:
|
||||
entity ent = findfloat(world, iszomb, 1);
|
||||
float dist;
|
||||
float best_dist = max_dist;
|
||||
while(ent != world) {
|
||||
if(ent != self && ent.aistatus == "1") {
|
||||
dist = vlen(self.origin - ent.origin);
|
||||
if(dist < best_dist) {
|
||||
// Check traceline to make sure is visible
|
||||
vector trace_start = self.origin + tesla_arc_ofs_for_ent(self);
|
||||
vector trace_end = ent.origin + tesla_arc_ofs_for_ent(self);
|
||||
traceline(trace_start, trace_end, MOVE_NOMONSTERS, world);
|
||||
if(trace_fraction >= 1.0) {
|
||||
best_dist = dist;
|
||||
best_ent = ent;
|
||||
}
|
||||
}
|
||||
}
|
||||
ent = findfloat(ent, iszomb, 1);
|
||||
}
|
||||
}
|
||||
|
||||
// print("\tZombie arcing to entity: \"", best_ent.classname, "\" dist: ", ftos(best_dist), "\n");
|
||||
|
||||
|
||||
// We found a zombie to arc to, continue arc from there
|
||||
if(best_ent != world) {
|
||||
tesla_damage(best_ent, self, self.tesla_arc_owner, self.tesla_arc_num + 1, true);
|
||||
|
||||
vector source_pos = self.origin + tesla_arc_ofs_for_ent(self);
|
||||
vector target_pos = best_ent.origin + tesla_arc_ofs_for_ent(best_ent);
|
||||
|
||||
#ifdef FTE
|
||||
te_lightning1(self, source_pos, target_pos);
|
||||
#else
|
||||
WriteByte(MSG_BROADCAST, SVC_TEMPENTITY);
|
||||
WriteByte(MSG_BROADCAST, TE_LIGHTNING1);
|
||||
WriteEntity(MSG_BROADCAST, self);
|
||||
WriteCoord(MSG_BROADCAST, source_pos.x);
|
||||
WriteCoord(MSG_BROADCAST, source_pos.y);
|
||||
WriteCoord(MSG_BROADCAST, source_pos.z);
|
||||
WriteCoord(MSG_BROADCAST, target_pos.x);
|
||||
WriteCoord(MSG_BROADCAST, target_pos.y);
|
||||
WriteCoord(MSG_BROADCAST, target_pos.z);
|
||||
#endif // FTE
|
||||
}
|
||||
// No ent to arc to, tell arc parent to resume its search
|
||||
// else if(self.tesla_arc_parent != world) {
|
||||
// // Don't wait, start immediately
|
||||
// self.tesla_arc_parent.tesla_next_arc_time = 0;
|
||||
// }
|
||||
// Have self immediately arc again next frame
|
||||
self.tesla_next_arc_time = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Fire lightning out of the gun
|
||||
void() W_FireTesla =
|
||||
{
|
||||
vector source;
|
||||
|
||||
source = self.origin + self.view_ofs;
|
||||
makevectors(self.v_angle);
|
||||
vector barrel_ofs = '5.560 -3 30';
|
||||
source += v_right * barrel_ofs.x;
|
||||
source += v_up * barrel_ofs.y;
|
||||
source += v_forward * barrel_ofs.z;
|
||||
|
||||
|
||||
#ifdef FTE
|
||||
self.dimension_hit = HITBOX_DIM_LIMBS | HITBOX_DIM_ZOMBIES;
|
||||
#endif // FTE
|
||||
|
||||
FireTrace(1, 0, 0, 0);
|
||||
|
||||
#ifdef FTE
|
||||
self.dimension_hit = HITBOX_DIM_ZOMBIES;
|
||||
#endif // FTE
|
||||
|
||||
|
||||
#ifdef FTE
|
||||
te_lightning1(world, source, trace_endpos);
|
||||
#else
|
||||
WriteByte(MSG_BROADCAST, SVC_TEMPENTITY);
|
||||
WriteByte(MSG_BROADCAST, TE_LIGHTNING2);
|
||||
WriteEntity(MSG_BROADCAST, self);
|
||||
WriteCoord(MSG_BROADCAST, source_x);
|
||||
WriteCoord(MSG_BROADCAST, source_y);
|
||||
WriteCoord(MSG_BROADCAST, source_z);
|
||||
WriteCoord(MSG_BROADCAST, trace_endpos_x);
|
||||
WriteCoord(MSG_BROADCAST, trace_endpos_y);
|
||||
WriteCoord(MSG_BROADCAST, trace_endpos_z);
|
||||
#endif // FTE
|
||||
|
||||
self.tesla_n_kills = 0;
|
||||
|
||||
entity hit_ent = trace_ent;
|
||||
if(hit_ent.classname == "ai_zombie_head" || hit_ent.classname == "ai_zombie_larm" || hit_ent.classname == "ai_zombie_rarm")
|
||||
hit_ent = hit_ent.owner;
|
||||
|
||||
// print("W_FireTesla hit ent: ", hit_ent.classname, "\n");
|
||||
|
||||
if(trace_ent != world && trace_ent.takedamage) {
|
||||
tesla_damage(hit_ent, world, self, 1, true);
|
||||
}
|
||||
// Not a direct-hit, do splash damage:
|
||||
else {
|
||||
tesla_spark(trace_endpos);
|
||||
|
||||
// TODO - Search for proximity to players and damage players
|
||||
// TODO - Electric overlay player HUD
|
||||
|
||||
|
||||
// ------- Find zombie closest to splash damage pos ---------
|
||||
// Damage any players within splash damage radius along the way
|
||||
float inner_radius = 30;
|
||||
float splash_radius = 110;
|
||||
entity ent = findradius(trace_endpos, splash_radius);
|
||||
float dist;
|
||||
entity best_ent = world;
|
||||
float best_dist = splash_radius;
|
||||
while(ent != world) {
|
||||
if(ent == self) {
|
||||
// ----------------------------------------
|
||||
// Player logic:
|
||||
// ----------------------------------------
|
||||
// - Same damage with or without jug
|
||||
// - Deal 75 damage at `inner_radius` qu
|
||||
// - Deal 0 damage at `splash_radius` qu
|
||||
// - Linearly interpolate damage in-between
|
||||
dist = vlen(ent.origin - trace_endpos);
|
||||
// lerp_frac: 1 at inner_radius, 0 at splash_radius
|
||||
float lerp_frac = (dist - splash_radius) / (inner_radius - splash_radius);
|
||||
float damage = lerp(0, 75, lerp_frac);
|
||||
// print("Giving player ",ftos(damage), " damage.\n");
|
||||
|
||||
if (other.perks & P_JUG)
|
||||
DamageHandler(ent, self, damage, S_ZAPPER);
|
||||
else
|
||||
DamageHandler(ent, self, damage, S_ZAPPER);
|
||||
// ----------------------------------------
|
||||
}
|
||||
|
||||
if(ent.aistatus == "1") {
|
||||
dist = vlen(ent.origin - trace_endpos);
|
||||
if(dist < best_dist) {
|
||||
best_dist = dist;
|
||||
best_ent = ent;
|
||||
}
|
||||
}
|
||||
ent = ent.chain;
|
||||
}
|
||||
if(best_ent != world) {
|
||||
tesla_damage(best_ent, world, self, 1, true);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1033,137 +1033,6 @@ void (float shotcount, float sprd, float Damage, float side) FireTrace =
|
|||
|
||||
}
|
||||
|
||||
// Remove zombie, add money, request clone spawn.
|
||||
void(entity hit_ent) LightningHit =
|
||||
{
|
||||
local entity tempe;
|
||||
|
||||
// 50 points for waffe kills
|
||||
addmoney(self, 50, true);
|
||||
|
||||
// set lib models to null
|
||||
// (if we remove them RelinkZombies will cry)
|
||||
if (hit_ent.head)
|
||||
setmodel(hit_ent.head, "");
|
||||
if (hit_ent.larm)
|
||||
setmodel(hit_ent.larm, "");
|
||||
if (hit_ent.rarm)
|
||||
setmodel(hit_ent.rarm, "");
|
||||
|
||||
// window hop fix
|
||||
if (self.state == 1 || self.hop_step != 0) {
|
||||
self.state = self.hop_step = 0;
|
||||
}
|
||||
|
||||
// change classname so it can't be re-targted
|
||||
hit_ent.classname = "wunder";
|
||||
|
||||
// own it!
|
||||
hit_ent.firer = self;
|
||||
|
||||
// we're the start of a chain
|
||||
hit_ent.teslacount = 1;
|
||||
|
||||
// play our wunder-ful anim
|
||||
tempe = self;
|
||||
self = hit_ent;
|
||||
self.th_diewunder();
|
||||
self = tempe;
|
||||
|
||||
// kill
|
||||
self.kills += 1;
|
||||
};
|
||||
|
||||
// Initial Zombie impact, creds to Naievil/UP
|
||||
void(vector p1, vector p2, entity from, float damage) LightningDamage =
|
||||
{
|
||||
local entity e1, e2;
|
||||
local vector f;
|
||||
entity hit_ent;
|
||||
|
||||
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);
|
||||
|
||||
hit_ent = trace_ent;
|
||||
|
||||
if (hit_ent == world)
|
||||
return;
|
||||
|
||||
if (hit_ent.classname == "ai_zombie_head" || hit_ent.classname == "ai_zombie_larm" || hit_ent.classname == "ai_zombie_rarm")
|
||||
hit_ent = hit_ent.owner;
|
||||
|
||||
if (trace_ent.takedamage)
|
||||
{
|
||||
LightningHit (hit_ent);
|
||||
}
|
||||
e1 = trace_ent;
|
||||
|
||||
traceline (p1 + f, p2 + f, FALSE, self);
|
||||
if (trace_ent != e1 && trace_ent.takedamage)
|
||||
{
|
||||
LightningHit (hit_ent);
|
||||
}
|
||||
e2 = trace_ent;
|
||||
|
||||
|
||||
traceline (p1 - f, p2 - f, FALSE, self);
|
||||
if (trace_ent != e1 && trace_ent != e2 && trace_ent.takedamage)
|
||||
{
|
||||
LightningHit (hit_ent);
|
||||
}
|
||||
};
|
||||
|
||||
// Fire lightning out of the gun
|
||||
void() W_FireTesla =
|
||||
{
|
||||
vector source;
|
||||
|
||||
makevectors (self.v_angle);
|
||||
source = self.origin + self.view_ofs;
|
||||
|
||||
#ifdef FTE
|
||||
|
||||
self.dimension_hit = HITBOX_DIM_LIMBS | HITBOX_DIM_ZOMBIES;
|
||||
|
||||
#endif // FTE
|
||||
|
||||
FireTrace(1, 0, 0, 0);
|
||||
|
||||
#ifdef FTE
|
||||
|
||||
self.dimension_hit = HITBOX_DIM_ZOMBIES;
|
||||
|
||||
#endif // FTE
|
||||
|
||||
|
||||
#ifdef FTE
|
||||
|
||||
te_lightning2(self, source, trace_endpos);
|
||||
|
||||
#else
|
||||
|
||||
WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
|
||||
WriteByte (MSG_BROADCAST, TE_LIGHTNING2);
|
||||
WriteEntity (MSG_BROADCAST, self);
|
||||
WriteCoord (MSG_BROADCAST, source_x);
|
||||
WriteCoord (MSG_BROADCAST, source_y);
|
||||
WriteCoord (MSG_BROADCAST, source_z);
|
||||
WriteCoord (MSG_BROADCAST, trace_endpos_x);
|
||||
WriteCoord (MSG_BROADCAST, trace_endpos_y);
|
||||
WriteCoord (MSG_BROADCAST, trace_endpos_z);
|
||||
|
||||
#endif // FTE
|
||||
|
||||
LightningDamage (self.origin, trace_endpos + v_forward*4, self, 30);
|
||||
}
|
||||
|
||||
void(float side) W_Fire =
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue