/* server/ai/crawler_core.qc Crawler AI Type Copyright (C) 2021-2023 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 */ //========================= Crawling =========================== void() zombie_crawl1; void() zombie_fastcrawl1; void() crawlerify1; void() Crawler_Walk_Setup { if (self.walktype == 1) zombie_crawl1(); else zombie_fastcrawl1(); } void() crawler_footstep { if(self.laststep == 1) { self.laststep = 0; sound(self, 5, "sounds/zombie/sc0.wav", 1, ATTN_NORM); } else { self.laststep = 1; sound(self, 5, "sounds/zombie/sc1.wav", 1, ATTN_NORM); } } //14-28 void() zombie_crawl1 =[ 0, zombie_crawl2 ] {Zombie_Walk((2.955*self.speed_penalty));SetZombieHitBox(CRAWLER_BBOX);self.frame = 14;Zombie_Think();}; void() zombie_crawl2 =[ 1, zombie_crawl3 ] {Zombie_Walk((3.841*self.speed_penalty)); self.frame = 15;Zombie_Think();}; void() zombie_crawl3 =[ 2, zombie_crawl4 ] {Zombie_Walk((0.886*self.speed_penalty)); self.frame = 16;Zombie_Think();}; void() zombie_crawl4 =[ 3, zombie_crawl5 ] {Zombie_Walk((1.871*self.speed_penalty)); self.frame = 17;Zombie_Think();}; void() zombie_crawl5 =[ 4, zombie_crawl6 ] {Zombie_Walk((3.25*self.speed_penalty)); self.frame = 18;Zombie_Think();}; void() zombie_crawl6 =[ 5, zombie_crawl7 ] {Zombie_Walk((1.314*self.speed_penalty)); self.frame = 19;Zombie_Think();}; void() zombie_crawl7 =[ 6, zombie_crawl8 ] {Zombie_Walk((0.908*self.speed_penalty)); self.frame = 20;Zombie_Think();crawler_footstep();};//footstep void() zombie_crawl8 =[ 7, zombie_crawl9 ] {Zombie_Walk((0.776*self.speed_penalty)); self.frame = 21;Zombie_Think();}; void() zombie_crawl9 =[ 8, zombie_crawl10 ] {Zombie_Walk((0.698*self.speed_penalty)); self.frame = 22;Zombie_Think();}; void() zombie_crawl10 =[ 9, zombie_crawl11 ] {Zombie_Walk((0.641*self.speed_penalty)); self.frame = 23;Zombie_Think();}; void() zombie_crawl11 =[ 10, zombie_crawl12 ] {Zombie_Walk((0.588*self.speed_penalty)); self.frame = 24;Zombie_Think();}; void() zombie_crawl12 =[ 11, zombie_crawl13 ] {Zombie_Walk((0.295*self.speed_penalty)); self.frame = 25;Zombie_Think();}; void() zombie_crawl13 =[ 12, zombie_crawl14 ] {Zombie_Walk((1.182*self.speed_penalty)); self.frame = 26;Zombie_Think();}; void() zombie_crawl14 =[ 13, zombie_crawl15 ] {Zombie_Walk((0.492*self.speed_penalty)); self.frame = 27;Zombie_Think();}; void() zombie_crawl15 =[ 14, Crawler_Walk_Setup ] {Zombie_Walk((2.856*self.speed_penalty)); self.frame = 28;Zombie_Think();crawler_footstep();};//footstep void() zombie_fastcrawl1 =[ 0, zombie_fastcrawl2 ] {Zombie_Walk((2.955*self.speed_penalty));SetZombieHitBox(CRAWLER_BBOX);self.frame = 14;Zombie_Think();}; void() zombie_fastcrawl2 =[ 1, zombie_fastcrawl3 ] {Zombie_Walk((0.886*self.speed_penalty)); self.frame = 16;Zombie_Think();}; void() zombie_fastcrawl3 =[ 2, zombie_fastcrawl4 ] {Zombie_Walk((3.25*self.speed_penalty)); self.frame = 18;Zombie_Think();}; void() zombie_fastcrawl4 =[ 3, zombie_fastcrawl5 ] {Zombie_Walk((0.908*self.speed_penalty)); self.frame = 20;Zombie_Think();crawler_footstep();};//footstep void() zombie_fastcrawl5 =[ 4, zombie_fastcrawl6 ] {Zombie_Walk((0.698*self.speed_penalty)); self.frame = 22;Zombie_Think();}; void() zombie_fastcrawl6 =[ 5, zombie_fastcrawl7 ] {Zombie_Walk((0.588*self.speed_penalty)); self.frame = 24;Zombie_Think();}; void() zombie_fastcrawl7 =[ 6, zombie_fastcrawl8 ] {Zombie_Walk((1.182*self.speed_penalty)); self.frame = 26;Zombie_Think();}; void() zombie_fastcrawl8 =[ 7, Crawler_Walk_Setup ] {Zombie_Walk((2.856*self.speed_penalty)); self.frame = 28;Zombie_Think();crawler_footstep();};//footstep //====================== Zombie To Crawler ======================= //0-4 void() crawlerify1 =[ 0, crawlerify2 ] {SetZombieHitBox(CRAWLER_BBOX); self.frame = 0;Zombie_Think();}; void() crawlerify2 =[ 1, crawlerify3 ] {self.frame = 1;Zombie_Think();}; void() crawlerify3 =[ 2, crawlerify4 ] {self.frame = 2;Zombie_Think();}; void() crawlerify4 =[ 3, crawlerify5 ] {self.frame = 3;Zombie_Think();crawler_footstep();crawler_footstep();};//hit floor void() crawlerify5 =[ 4, Crawler_Walk_Setup ] {self.frame = 4;Zombie_Think();if(self.health <= 0) self.th_die();};//need to check for death since a grenade will not kill a zombie, only make him a crawler //====================== Crawler Idle ============================== //4-13 void() crawler_idle1 =[ 0, crawler_idle2 ] {SetZombieHitBox(CRAWLER_BBOX);Zombie_Walk(0); self.frame = 4;Zombie_Think();}; void() crawler_idle2 =[ 1, crawler_idle3 ] {Zombie_Walk(0); self.frame = 5;Zombie_Think();}; void() crawler_idle3 =[ 2, crawler_idle4 ] {Zombie_Walk(0); self.frame = 6;Zombie_Think();}; void() crawler_idle4 =[ 3, crawler_idle5 ] {Zombie_Walk(0); self.frame = 7;Zombie_Think();}; void() crawler_idle5 =[ 4, crawler_idle6 ] {Zombie_Walk(0); self.frame = 8;Zombie_Think();}; void() crawler_idle6 =[ 5, crawler_idle7 ] {Zombie_Walk(0); self.frame = 9;Zombie_Think();}; void() crawler_idle7 =[ 6, crawler_idle8 ] {Zombie_Walk(0); self.frame = 10;Zombie_Think();}; void() crawler_idle8 =[ 7, crawler_idle9 ] {Zombie_Walk(0); self.frame = 11;Zombie_Think();}; void() crawler_idle9 =[ 8, crawler_idle10 ] {Zombie_Walk(0); self.frame = 12;Zombie_Think();}; void() crawler_idle10 =[ 9, crawler_idle1 ] {Zombie_Walk(0); self.frame = 13;Zombie_Think();}; //===================== Crawler Attack =========================== //29-36 void() crawler_atk1 =[ 0, crawler_atk2] {SetZombieHitBox(CRAWLER_BBOX);self.frame = 29;Zombie_Think();}; void() crawler_atk2 =[ 1, crawler_atk3] {self.frame = 30;Zombie_Think();}; void() crawler_atk3 =[ 2, crawler_atk4] {self.frame = 31;Zombie_Think();}; void() crawler_atk4 =[ 3, crawler_atk5] {self.frame = 32;zombie_attack2();Zombie_Think();}; void() crawler_atk5 =[ 4, crawler_atk6] {self.frame = 33;Zombie_Think();}; void() crawler_atk6 =[ 5, crawler_atk7] {self.frame = 34;Zombie_Think();}; void() crawler_atk7 =[ 6, crawler_atk8] {self.frame = 35;Zombie_Think();}; void() crawler_atk8 =[ 7, zombie_decide] {self.frame = 36;Zombie_Think();}; //====================== Crawler Delay Attack ============================== //4-13 void(float which) crawler_attack_choose = { self.angles_y = vectoyaw(self.enemy.origin - self.origin); if(which != 1) { if(random() > 0.2) { return; } } if(vlen(self.enemy.origin - self.origin) > 60)//too far, cancel attack { zombie_decide(); return; } play_sound_z(1); crawler_atk1(); }; void() crawler_da1 =[ 0, crawler_da2 ] {SetZombieHitBox(CRAWLER_BBOX);crawler_attack_choose(0); self.frame = 4;Zombie_Think();}; void() crawler_da2 =[ 1, crawler_da3 ] {crawler_attack_choose(0); self.frame = 5;Zombie_Think();}; void() crawler_da3 =[ 2, crawler_da4 ] {crawler_attack_choose(0); self.frame = 6;Zombie_Think();}; void() crawler_da4 =[ 3, crawler_da5 ] {crawler_attack_choose(0); self.frame = 7;Zombie_Think();}; void() crawler_da5 =[ 4, crawler_da6 ] {crawler_attack_choose(0); self.frame = 8;Zombie_Think();}; void() crawler_da6 =[ 5, crawler_da7 ] {crawler_attack_choose(0); self.frame = 9;Zombie_Think();}; void() crawler_da7 =[ 6, crawler_da8 ] {crawler_attack_choose(0); self.frame = 10;Zombie_Think();}; void() crawler_da8 =[ 7, crawler_da9 ] {crawler_attack_choose(0); self.frame = 11;Zombie_Think();}; void() crawler_da9 =[ 8, crawler_da10 ] {crawler_attack_choose(0); self.frame = 12;Zombie_Think();}; void() crawler_da10 =[ 9, crawler_da1 ] {crawler_attack_choose(0); self.frame = 13;Zombie_Think();}; //====================== Crawler Death ============================ //37-39 void() crawler_die1 =[ 0, crawler_die2] {SetZombieHitBox(CRAWLER_BBOX);self.frame = 37;}; 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();}; void() crawler_climbBarricade2 =[ 1, crawler_climbBarricade3] {self.frame = 41; moveforwardalittle(0);Zombie_Think();}; void() crawler_climbBarricade3 =[ 2, crawler_climbBarricade4] {self.frame = 42; moveforwardalittle(0);Zombie_Think();}; void() crawler_climbBarricade4 =[ 3, crawler_climbBarricade5] {self.frame = 43; moveforwardalittle(1);Zombie_Think();}; void() crawler_climbBarricade5 =[ 4, crawler_climbBarricade6] {self.frame = 44; moveforwardalittle(0);Zombie_Think();}; void() crawler_climbBarricade6 =[ 5, crawler_climbBarricade7] {self.frame = 45; moveforwardalittle(0);Zombie_Think();}; void() crawler_climbBarricade7 =[ 6, crawler_climbBarricade8] {self.frame = 46; moveforwardalittle(1);Zombie_Think();}; void() crawler_climbBarricade8 =[ 7, crawler_climbBarricade9] {self.frame = 47; moveforwardalittle(0);Zombie_Think();}; void() crawler_climbBarricade9 =[ 8, crawler_climbBarricade10] {self.frame = 48; moveforwardalittle(0);Zombie_Think();}; void() crawler_climbBarricade10 =[ 9, crawler_climbBarricade11] {self.frame = 49; moveforwardalittle(1);Zombie_Think();}; void() crawler_climbBarricade11 =[ 10, crawler_climbBarricade12] {self.frame = 50; moveforwardalittle(0);Zombie_Think();}; void() crawler_climbBarricade12 =[ 11, crawler_climbBarricade13] {self.frame = 51; moveforwardalittle(0);Zombie_Think();}; void() crawler_climbBarricade13 =[ 12, crawler_climbBarricade14] {self.frame = 52; moveforwardalittle(1);Zombie_Think();}; void() crawler_climbBarricade14 =[ 13, crawler_climbBarricade15] {self.frame = 53; moveforwardalittle(0);Zombie_Think();}; void() crawler_climbBarricade15 =[ 14, crawler_climbBarricade16] {self.frame = 54; moveforwardalittle(0);Zombie_Think();}; void() crawler_climbBarricade16 =[ 15, crawler_climbBarricade17] {self.frame = 55; moveforwardalittle(1);Zombie_Think();}; void() crawler_climbBarricade17 =[ 16, crawler_climbBarricade18] {self.frame = 56; moveforwardalittle(0);Zombie_Think();}; void() crawler_climbBarricade18 =[ 17, crawler_climbBarricade19] {self.frame = 57; moveforwardalittle(0);Zombie_Think();}; void() crawler_climbBarricade19 =[ 18, crawler_climbBarricade20] {self.frame = 58; moveforwardalittle(1);Zombie_Think();}; void() crawler_climbBarricade20 =[ 19, crawler_climbBarricade21] {self.frame = 59; moveforwardalittle(0);Zombie_Think();}; void() crawler_climbBarricade21 =[ 20, crawler_climbBarricade22] {self.frame = 60; moveforwardalittle(0);Zombie_Think();}; void() crawler_climbBarricade22 =[ 21, crawler_climbBarricade23] {self.frame = 61; moveforwardalittle(1);Zombie_Think();}; void() crawler_climbBarricade23 =[ 22, crawler_climbBarricade24] {self.frame = 62; moveforwardalittle(0);Zombie_Think();}; void() crawler_climbBarricade24 =[ 23, crawler_climbBarricade25] {self.frame = 63; moveforwardalittle(0);Zombie_Think();}; void() crawler_climbBarricade25 =[ 24, crawler_climbBarricade26] {self.frame = 64; moveforwardalittle(1);Zombie_Think();}; void() crawler_climbBarricade26 =[ 25, crawler_climbBarricade27] {self.frame = 65; moveforwardalittle(0);Zombie_Think();}; void() crawler_climbBarricade27 =[ 26, crawler_climbBarricade28] {self.frame = 66; moveforwardalittle(0);Zombie_Think();}; void() crawler_climbBarricade28 =[ 27, crawler_climbBarricade29] {self.frame = 67; moveforwardalittle(1);Zombie_Think();}; void() crawler_climbBarricade29 =[ 28, crawler_climbBarricade30] {self.frame = 68; moveforwardalittle(1);Zombie_Think();}; void() crawler_climbBarricade30 =[ 29, crawler_climbBarricade31] {self.frame = 69; moveforwardalittle(1);Zombie_Think();}; void() crawler_climbBarricade31 =[ 30, SUB_Null] {self.frame = 70; self.movetype = MOVETYPE_WALK; self.zoom = 1;self.state = 0;self.hop_step = 6; self.th_walk();Zombie_Think();}; //======================== Crawler Fall ============================= //71 - 77 void() crawler_fall1 =[ 0, crawler_fall2] {SetZombieHitBox(CRAWLER_BBOX);self.fall = TRUE;CheckLand();self.frame=71;Zombie_Think();}; void() crawler_fall2 =[ 1, crawler_fall3] {self.fall = TRUE;CheckLand();self.frame=72;Zombie_Think();}; void() crawler_fall3 =[ 2, crawler_fall4] {self.fall = TRUE;CheckLand();self.frame=73;Zombie_Think();}; void() crawler_fall4 =[ 3, crawler_fall5] {self.fall = TRUE;CheckLand();self.frame=74;Zombie_Think();}; void() crawler_fall5 =[ 4, crawler_fall6] {self.fall = TRUE;CheckLand();self.frame=75;Zombie_Think();}; void() crawler_fall6 =[ 5, crawler_fall7] {self.fall = TRUE;CheckLand();self.frame=76;Zombie_Think();}; void() crawler_fall7 =[ 6, crawler_fall1] {self.fall = TRUE;CheckLand();self.frame=77;Zombie_Think();}; //======================== Crawler Land ============================ //77-86 void() crawler_land1 =[ 0, crawler_land2] {SetZombieHitBox(CRAWLER_BBOX);self.frame=77;Zombie_Think();}; void() crawler_land2 =[ 1, crawler_land3] {self.frame=78;Zombie_Think();}; void() crawler_land3 =[ 2, crawler_land4] {self.frame=79;Zombie_Think();}; void() crawler_land4 =[ 3, crawler_land5] {self.frame=80;Zombie_Think();}; void() crawler_land5 =[ 4, crawler_land6] {self.frame=81;Zombie_Think();}; void() crawler_land6 =[ 5, crawler_land7] {self.frame=82;Zombie_Think();}; void() crawler_land7 =[ 6, crawler_land8] {self.frame=83;Zombie_Think();}; void() crawler_land8 =[ 7, crawler_land9] {self.frame=84;Zombie_Think();}; void() crawler_land9 =[ 8, crawler_land10] {self.frame=85;Zombie_Think();}; void() crawler_land10 =[ 9, Crawler_Walk_Setup] {self.frame=86;Zombie_Think();}; //======================== Crawler Rip Board ======================= //103-126 void() crawler_rip_board1 =[ 0, crawler_rip_board2] {SetZombieHitBox(CRAWLER_BBOX);self.frame=103;Zombie_Think();}; void() crawler_rip_board2 =[ 1, crawler_rip_board3] {self.frame=104;Zombie_Think();}; void() crawler_rip_board3 =[ 2, crawler_rip_board4] {self.frame=105;Zombie_Think();}; void() crawler_rip_board4 =[ 3, crawler_rip_board5] {self.frame=106;Zombie_Think();}; void() crawler_rip_board5 =[ 4, crawler_rip_board6] {self.frame=107;Zombie_Think();}; void() crawler_rip_board6 =[ 5, crawler_rip_board7] {self.frame=108;Zombie_Think();}; void() crawler_rip_board7 =[ 6, crawler_rip_board8] {self.frame=109;Zombie_Think();}; void() crawler_rip_board8 =[ 7, crawler_rip_board9] {self.frame=110;Zombie_Think();}; void() crawler_rip_board9 =[ 8, crawler_rip_board10] {self.frame=111;Zombie_Think();}; void() crawler_rip_board10 =[ 9, crawler_rip_board11] {self.frame=112;Zombie_Think();}; void() crawler_rip_board11 =[ 10, crawler_rip_board12] {self.frame=113;Zombie_Think();}; void() crawler_rip_board12 =[ 11, crawler_rip_board13] {self.frame=114;Zombie_Think();}; void() crawler_rip_board13 =[ 12, crawler_rip_board14] {self.frame=115;zombie_attack2();}; void() crawler_rip_board14 =[ 13, crawler_rip_board15] {self.frame=116;Zombie_Think();}; void() crawler_rip_board15 =[ 14, crawler_rip_board16] {self.frame=117;Zombie_Think();}; void() crawler_rip_board16 =[ 15, crawler_rip_board17] {self.frame=118;Zombie_Think();}; void() crawler_rip_board17 =[ 16, crawler_rip_board18] {self.frame=119;Zombie_Think();}; void() crawler_rip_board18 =[ 17, crawler_rip_board19] {self.frame=120;Zombie_Think();}; void() crawler_rip_board19 =[ 18, crawler_rip_board20] {self.frame=121;Zombie_Think();}; void() crawler_rip_board20 =[ 19, crawler_rip_board21] {self.frame=122;Zombie_Think();}; void() crawler_rip_board21 =[ 20, crawler_rip_board22] {self.frame=123;Zombie_Think();}; void() crawler_rip_board22 =[ 21, crawler_rip_board23] {self.frame=124;Zombie_Think();}; void() crawler_rip_board23 =[ 22, crawler_rip_board24] {self.frame=125;Zombie_Think();}; void() crawler_rip_board24 =[ 23, zombie_decide] {self.frame=126;Zombie_Think();}; void(entity who) makeCrawler = { if(who.state == 1) { who.crawling = 2; return; } who.crawling = 2;//this means we haven't technically initiated it, but we're going to... who.th_die = Zombie_Death; who.th_walk = Crawler_Walk_Setup; 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; float multiplier = random(); if (multiplier < 0.33) { who.speed_penalty = 1; } else if (multiplier < 0.66) { who.speed_penalty = 1.75; } else { who.speed_penalty = 3; who.walktype = 2; } //who.th_jump = zombie_jump1; //who.th_grabledge = zombie_grabledge1; //who.th_diewunder = die_wunder1; setmodel(who,"models/ai/zbc%.mdl"); if(who.head.deadflag) { setmodel(who.head,"models/ai/zhc^.mdl"); #ifndef FTE updateLimb (who, 0, world); #endif // FTE } if(who.larm.deadflag) { setmodel(who.larm,"models/ai/zalc(.mdl"); #ifndef FTE updateLimb (who, 1, world); #endif // FTE } if(who.rarm.deadflag) { setmodel(who.rarm,"models/ai/zarc(.mdl"); #ifndef FTE updateLimb (who, 2, world); #endif // FTE } who.crawling = 1; setsize(who,'-9 -9 -32','9 9 -10'); local entity oself; oself = self; self = who; crawlerify1(); self = oself; crawler_num = crawler_num + 1; }