From 0dd54252ffc5176c8ad78e56d5c8ef6c1d711f98 Mon Sep 17 00:00:00 2001 From: Mario Date: Fri, 25 Jan 2013 01:13:09 +1100 Subject: [PATCH] Fix TD monster spawn protection. Improve TD monster pathfinding --- gamemodes.cfg | 2 +- monsters.cfg | 4 - qcsrc/server/autocvars.qh | 2 +- qcsrc/server/monsters/lib/monsters.qc | 3 +- qcsrc/server/monsters/monster/demon.qc | 2 +- qcsrc/server/monsters/monster/dog.qc | 2 +- qcsrc/server/monsters/monster/enforcer.qc | 2 +- qcsrc/server/monsters/monster/fish.qc | 2 +- qcsrc/server/monsters/monster/hknight.qc | 2 +- qcsrc/server/monsters/monster/knight.qc | 2 +- qcsrc/server/monsters/monster/ogre.qc | 2 +- qcsrc/server/monsters/monster/shalrath.qc | 2 +- qcsrc/server/monsters/monster/shambler.qc | 2 +- qcsrc/server/monsters/monster/soldier.qc | 2 +- qcsrc/server/monsters/monster/spider.qc | 97 +++-------------------- qcsrc/server/monsters/monster/tarbaby.qc | 2 +- qcsrc/server/monsters/monster/wizard.qc | 2 +- qcsrc/server/monsters/monster/zombie.qc | 2 +- qcsrc/server/mutators/gamemode_td.qc | 57 ++++--------- qcsrc/server/mutators/gamemode_td.qh | 4 +- 20 files changed, 45 insertions(+), 150 deletions(-) diff --git a/gamemodes.cfg b/gamemodes.cfg index 94926ebaa..8987e5e5f 100644 --- a/gamemodes.cfg +++ b/gamemodes.cfg @@ -495,7 +495,7 @@ set g_td_generator_dontend 0 "don't change maps when a generator is destroyed (o set g_td_pvp 0 set g_td_monsters_skill_start 1 set g_td_monsters_skill_increment 0.1 -set g_td_monster_spawn_protection_radius 300 +set g_td_monsters_spawnshield_time 2 set g_td_max_waves 8 set g_td_kill_points 5 set g_td_turretkill_points 3 diff --git a/monsters.cfg b/monsters.cfg index 3d79f77e6..cae7a40eb 100644 --- a/monsters.cfg +++ b/monsters.cfg @@ -190,16 +190,12 @@ set g_monster_zombie_drop_size large "Size of the item zombies drop. Possible va set g_monster_spider 1 "Enable Spiders" set g_monster_spider_attack_type 0 "Spider attack type (0 = ice, 1 = fire, ...)" set g_monster_spider_attack_leap_delay 1.5 "Delay after spider attack leap" -set g_monster_spider_attack_leap_range 96 "Range of spider attack leap" set g_monster_spider_attack_stand_damage 35 "Damage when spider hits from a standing position" set g_monster_spider_attack_stand_delay 1.2 "Delay after a spider hits from a standing position" -set g_monster_spider_attack_stand_range 48 "Range of a spider standing position attack" set g_monster_spider_health 200 "Spider health" set g_monster_spider_idle_timer_min 1 "Minimum time a spider can stay idle" set g_monster_spider_speed_walk 150 "Spider walk speed" set g_monster_spider_speed_run 400 "Spider run speed" set g_monster_spider_stopspeed 100 Speed at which spider stops" -set g_monster_spider_target_recheck_delay 5 How much time should a spider run afer an enemy before checking if it's still in range" -set g_monster_spider_target_range 1200 How far the spider can see an enemy" set g_monster_spider_drop health "Spider drops this item on death" set g_monster_spider_drop_size large "Size of the item spiders drop. Possible values are: small, medium, large" \ No newline at end of file diff --git a/qcsrc/server/autocvars.qh b/qcsrc/server/autocvars.qh index e00fd585b..dd3284a6f 100644 --- a/qcsrc/server/autocvars.qh +++ b/qcsrc/server/autocvars.qh @@ -1296,7 +1296,7 @@ float autocvar_g_td_turret_walker_cost; float autocvar_g_td_tower_buff_cost; float autocvar_g_td_monsters_skill_start; float autocvar_g_td_monsters_skill_increment; -float autocvar_g_td_monster_spawn_protection_radius; +float autocvar_g_td_monsters_spawnshield_time; float autocvar_g_za_monster_count; float autocvar_g_monsters; float autocvar_g_monsters_max; diff --git a/qcsrc/server/monsters/lib/monsters.qc b/qcsrc/server/monsters/lib/monsters.qc index 0338f5ef6..38f41c2db 100644 --- a/qcsrc/server/monsters/lib/monsters.qc +++ b/qcsrc/server/monsters/lib/monsters.qc @@ -113,6 +113,7 @@ void MonsterTouch () return; if(self.enemy != other) + if not(other.flags & FL_MONSTER) if(monster_isvalidtarget(other, self, FALSE)) self.enemy = other; } @@ -541,7 +542,7 @@ void Monster_Appear () entity FindTarget (entity ent) { - if(MUTATOR_CALLHOOK(MonsterFindTarget)) { return ent.goalentity; } // Handled by a mutator + if(MUTATOR_CALLHOOK(MonsterFindTarget)) { return ent.enemy; } // Handled by a mutator local entity e; for(e = world; (e = findflags(e, monster_attack, TRUE)); ) { diff --git a/qcsrc/server/monsters/monster/demon.qc b/qcsrc/server/monsters/monster/demon.qc index 1e54bec4e..6bff2017c 100644 --- a/qcsrc/server/monsters/monster/demon.qc +++ b/qcsrc/server/monsters/monster/demon.qc @@ -22,7 +22,7 @@ const vector DEMON_MAX = '32 32 24'; void demon_think () { self.think = demon_think; - self.nextthink = time + 0.3; + self.nextthink = time + 0.1; monster_move(autocvar_g_monster_demon_speed_run, autocvar_g_monster_demon_speed_walk, 100, demon_anim_run, demon_anim_walk, demon_anim_stand); } diff --git a/qcsrc/server/monsters/monster/dog.qc b/qcsrc/server/monsters/monster/dog.qc index aa65d6d4b..a79c443e2 100644 --- a/qcsrc/server/monsters/monster/dog.qc +++ b/qcsrc/server/monsters/monster/dog.qc @@ -37,7 +37,7 @@ void Dog_JumpTouch () void dog_think () { self.think = dog_think; - self.nextthink = time + 0.3; + self.nextthink = time + 0.1; monster_move(autocvar_g_monster_dog_speed_run, autocvar_g_monster_dog_speed_walk, 50, dog_anim_run, dog_anim_walk, dog_anim_idle); } diff --git a/qcsrc/server/monsters/monster/enforcer.qc b/qcsrc/server/monsters/monster/enforcer.qc index 2e3fa1a55..b370e402e 100644 --- a/qcsrc/server/monsters/monster/enforcer.qc +++ b/qcsrc/server/monsters/monster/enforcer.qc @@ -24,7 +24,7 @@ float autocvar_g_monster_enforcer_attack_uzi_bullets; void enforcer_think () { self.think = enforcer_think; - self.nextthink = time + 0.3; + self.nextthink = time + 0.1; if(self.delay != -1) self.nextthink = self.delay; diff --git a/qcsrc/server/monsters/monster/fish.qc b/qcsrc/server/monsters/monster/fish.qc index 970fd47e3..f40272266 100644 --- a/qcsrc/server/monsters/monster/fish.qc +++ b/qcsrc/server/monsters/monster/fish.qc @@ -18,7 +18,7 @@ float autocvar_g_monster_fish_speed_run; void fish_think () { self.think = fish_think; - self.nextthink = time + 0.3; + self.nextthink = time + 0.1; monster_move(autocvar_g_monster_fish_speed_run, autocvar_g_monster_fish_speed_walk, 10, fish_anim_swim, fish_anim_swim, fish_anim_swim); } diff --git a/qcsrc/server/monsters/monster/hknight.qc b/qcsrc/server/monsters/monster/hknight.qc index f1d7e3cd2..a4b42acbd 100644 --- a/qcsrc/server/monsters/monster/hknight.qc +++ b/qcsrc/server/monsters/monster/hknight.qc @@ -171,7 +171,7 @@ void CheckContinueCharge () void hellknight_think () { self.think = hellknight_think; - self.nextthink = time + 0.3; + self.nextthink = time + 0.1; monster_move(autocvar_g_monster_hellknight_speed_run, autocvar_g_monster_hellknight_speed_walk, 100, hellknight_anim_run, hellknight_anim_walk, hellknight_anim_stand); } diff --git a/qcsrc/server/monsters/monster/knight.qc b/qcsrc/server/monsters/monster/knight.qc index 4aa625415..67ef1576b 100644 --- a/qcsrc/server/monsters/monster/knight.qc +++ b/qcsrc/server/monsters/monster/knight.qc @@ -25,7 +25,7 @@ float autocvar_g_monster_knight_speed_run; void knight_think () { self.think = knight_think; - self.nextthink = time + 0.3; + self.nextthink = time + 0.1; monster_move(autocvar_g_monster_knight_speed_run, autocvar_g_monster_knight_speed_walk, 50, knight_anim_run, knight_anim_walk, knight_anim_stand); } diff --git a/qcsrc/server/monsters/monster/ogre.qc b/qcsrc/server/monsters/monster/ogre.qc index 6b30c8e25..2331dd9f4 100644 --- a/qcsrc/server/monsters/monster/ogre.qc +++ b/qcsrc/server/monsters/monster/ogre.qc @@ -40,7 +40,7 @@ void chainsaw (float side) void ogre_think () { self.think = ogre_think; - self.nextthink = time + 0.3; + self.nextthink = time + 0.1; if(self.delay != -1) self.nextthink = self.delay; diff --git a/qcsrc/server/monsters/monster/shalrath.qc b/qcsrc/server/monsters/monster/shalrath.qc index c19e1ce67..732ff78ae 100644 --- a/qcsrc/server/monsters/monster/shalrath.qc +++ b/qcsrc/server/monsters/monster/shalrath.qc @@ -19,7 +19,7 @@ void() ShalMissile; void shalrath_think () { self.think = shalrath_think; - self.nextthink = time + 0.3; + self.nextthink = time + 0.1; if(self.delay != -1) self.nextthink = self.delay; diff --git a/qcsrc/server/monsters/monster/shambler.qc b/qcsrc/server/monsters/monster/shambler.qc index 0f82cc717..569462867 100644 --- a/qcsrc/server/monsters/monster/shambler.qc +++ b/qcsrc/server/monsters/monster/shambler.qc @@ -25,7 +25,7 @@ float autocvar_g_monster_shambler_speed_run; void shambler_think () { self.think = shambler_think; - self.nextthink = time + 0.3; + self.nextthink = time + 0.1; monster_move(autocvar_g_monster_shambler_speed_run, autocvar_g_monster_shambler_speed_walk, 300, shambler_anim_run, shambler_anim_walk, shambler_anim_stand); } diff --git a/qcsrc/server/monsters/monster/soldier.qc b/qcsrc/server/monsters/monster/soldier.qc index b4e46e0f5..54c7849e8 100644 --- a/qcsrc/server/monsters/monster/soldier.qc +++ b/qcsrc/server/monsters/monster/soldier.qc @@ -30,7 +30,7 @@ float autocvar_g_monster_soldier_attack_uzi_bullets; void soldier_think () { self.think = soldier_think; - self.nextthink = time + 0.3; + self.nextthink = time + 0.1; if(self.delay != -1) self.nextthink = self.delay; diff --git a/qcsrc/server/monsters/monster/spider.qc b/qcsrc/server/monsters/monster/spider.qc index 2007e5e28..744e05eb4 100644 --- a/qcsrc/server/monsters/monster/spider.qc +++ b/qcsrc/server/monsters/monster/spider.qc @@ -2,16 +2,11 @@ float autocvar_g_monster_spider; float autocvar_g_monster_spider_stopspeed; float autocvar_g_monster_spider_attack_leap_delay; -float autocvar_g_monster_spider_attack_leap_range; float autocvar_g_monster_spider_attack_stand_damage; float autocvar_g_monster_spider_attack_stand_delay; -float autocvar_g_monster_spider_attack_stand_range; float autocvar_g_monster_spider_health; -float autocvar_g_monster_spider_idle_timer_min; float autocvar_g_monster_spider_speed_walk; float autocvar_g_monster_spider_speed_run; -float autocvar_g_monster_spider_target_recheck_delay; -float autocvar_g_monster_spider_target_range; float autocvar_g_monster_spider_attack_type; // spider animations @@ -165,92 +160,18 @@ void spider_attack_leap() } } -void spider_think() +float spider_attack_ranged() { - float finished = FALSE, enemyDistance = 0, mySpeed = 0; + spider_attack_leap(); + return TRUE; +} +void spider_think() +{ self.think = spider_think; + self.nextthink = time + 0.1; - if(self.enemy && !monster_isvalidtarget(self.enemy, self, FALSE)) - self.enemy = world; - - if (self.enemy) - if (self.enemy.team == self.team || self.monster_owner == self.enemy) - self.enemy = world; - - if(teamplay && autocvar_g_monsters_teams && self.monster_owner.team != self.team) - self.monster_owner = world; - - // remove enemy that ran away - if (self.enemy) - if (self.delay <= time) // check if we can do the rescan now - if (vlen(self.origin - self.enemy.origin) > autocvar_g_monster_spider_target_range * self.scale) - { - //print("removing enemy, he is too far: ", ftos(vlen(self.origin - self.enemy.origin)), "\n"); - //print("delay was ", ftos(self.delay), "\n"); - self.enemy = world; - } - else - self.delay = time + autocvar_g_monster_spider_target_recheck_delay; - - // find an enemy if no enemy available - if not(self.enemy) - { - self.enemy = FindTarget(self); - if (self.enemy) - self.delay = time + autocvar_g_monster_spider_target_recheck_delay; - } - - if (self.enemy) - { - // this spider has an enemy, attack if close enough, go to it if not! - traceline(self.origin, self.enemy.origin, FALSE, self); - enemyDistance = vlen(trace_endpos - self.origin); - mySpeed = vlen(self.velocity); - - //print("speed ", ftos(mySpeed), "\n"); - - if (trace_ent == self.enemy) - if (self.enemy.deadflag == DEAD_NO) - if (enemyDistance <= autocvar_g_monster_spider_attack_stand_range * self.scale && mySpeed <= 30) - { - - //RadiusDamage (entity inflictor, entity attacker, float coredamage, float edgedamage, float rad, entity ignore, float forceintensity, float deathtype, entity directhitentity) - spider_attack_standing(); - finished = TRUE; - } - else if (enemyDistance <= autocvar_g_monster_spider_attack_leap_range * self.scale && !self.enemy.frozen) - { - // do attackleap (set yaw, velocity, and check do damage on the first player entity it touches) - spider_attack_leap(); - finished = TRUE; - } - - } - - self.nextthink = time + 1; - - if not(finished) - { - monster_move(autocvar_g_monster_spider_speed_run, autocvar_g_monster_spider_speed_walk, autocvar_g_monster_spider_stopspeed, spider_anim_walk, spider_anim_walk, spider_anim_idle); - - if (self.enemy || self.monster_owner) - { - self.nextthink = time + 0.1; - return; - } - } - - if not(self.enemy || self.monster_owner || self.goalentity) - { - // stay idle - //print("spider is idling while waiting for some fresh meat...\n"); - if (mySpeed <= 10) - self.frame = spider_anim_idle; - else - self.frame = spider_anim_walk; - self.nextthink = time + autocvar_g_monster_spider_idle_timer_min * random(); - } + monster_move(autocvar_g_monster_spider_speed_run, autocvar_g_monster_spider_speed_walk, autocvar_g_monster_spider_stopspeed, spider_anim_walk, spider_anim_walk, spider_anim_idle); } /** @@ -265,6 +186,8 @@ void spider_spawn() self.nextthink = time + random() * 0.5 + 0.1; self.pain_finished = self.nextthink; self.frame = spider_anim_idle; + self.attack_melee = spider_attack_standing; + self.attack_ranged = spider_attack_ranged; self.think = spider_think; self.sprite_height = 40 * self.scale; diff --git a/qcsrc/server/monsters/monster/tarbaby.qc b/qcsrc/server/monsters/monster/tarbaby.qc index 355648ef5..25903b3ef 100644 --- a/qcsrc/server/monsters/monster/tarbaby.qc +++ b/qcsrc/server/monsters/monster/tarbaby.qc @@ -18,7 +18,7 @@ float autocvar_g_monster_tarbaby_speed_run; void tarbaby_think () { self.think = tarbaby_think; - self.nextthink = time + 0.3; + self.nextthink = time + 0.1; monster_move(autocvar_g_monster_tarbaby_speed_run, autocvar_g_monster_tarbaby_speed_walk, 20, tarbaby_anim_run, tarbaby_anim_walk, tarbaby_anim_walk); } diff --git a/qcsrc/server/monsters/monster/wizard.qc b/qcsrc/server/monsters/monster/wizard.qc index 4460e0221..62a3be9e0 100644 --- a/qcsrc/server/monsters/monster/wizard.qc +++ b/qcsrc/server/monsters/monster/wizard.qc @@ -91,7 +91,7 @@ void Wiz_StartFast () void wizard_think () { self.think = wizard_think; - self.nextthink = time + 0.3; + self.nextthink = time + 0.1; monster_move(autocvar_g_monster_wizard_speed_run, autocvar_g_monster_wizard_speed_walk, 300, wizard_anim_fly, wizard_anim_hover, wizard_anim_hover); } diff --git a/qcsrc/server/monsters/monster/zombie.qc b/qcsrc/server/monsters/monster/zombie.qc index ff73c8efa..113ea6451 100644 --- a/qcsrc/server/monsters/monster/zombie.qc +++ b/qcsrc/server/monsters/monster/zombie.qc @@ -151,7 +151,7 @@ float zombie_attack_ranged() void zombie_think() { self.think = zombie_think; - self.nextthink = time + 0.3; + self.nextthink = time + 0.1; monster_move(autocvar_g_monster_zombie_speed_run, autocvar_g_monster_zombie_speed_walk, autocvar_g_monster_zombie_stopspeed, zombie_anim_runforward, zombie_anim_runforward, zombie_anim_idle); } diff --git a/qcsrc/server/mutators/gamemode_td.qc b/qcsrc/server/mutators/gamemode_td.qc index 050162322..077aa8532 100644 --- a/qcsrc/server/mutators/gamemode_td.qc +++ b/qcsrc/server/mutators/gamemode_td.qc @@ -21,6 +21,7 @@ void spawnfunc_td_controller() totalmonsters = ((self.monstercount) ? self.monstercount : autocvar_g_td_monster_count); wave_count = ((self.startwave) ? self.startwave : autocvar_g_td_start_wave); max_turrets = ((self.maxturrets) ? self.maxturrets : autocvar_g_td_turret_max); + build_time = ((self.buildtime) ? self.buildtime : autocvar_g_td_buildphase_time); wave_end(TRUE); } @@ -180,9 +181,6 @@ void spawnfunc_monster_swarm() default: self.classname = "monster_swarm"; break; } - - if(!self.protection_radius) - self.protection_radius = autocvar_g_td_monster_spawn_protection_radius; if(self.target2 != "") { @@ -557,7 +555,7 @@ void build_phase() GameLogEcho(sprintf(":buildphase:%d:%d", wave_count, totalmonsters)); self.think = combat_phase_announce; - self.nextthink = time + autocvar_g_td_buildphase_time - 6; + self.nextthink = time + build_time - 6; } void wave_end(float starting) @@ -688,6 +686,9 @@ MUTATOR_HOOKFUNCTION(td_PlayerDamage_Calculate) if(frag_attacker.realowner == frag_target) frag_damage = 0; + if(frag_target.flags & FL_MONSTER && time < frag_target.spawnshieldtime) + frag_damage = 0; + if(frag_target.vehicle_flags & VHF_ISVEHICLE && !DEATH_ISMONSTER(frag_deathtype)) frag_damage = 0; @@ -761,14 +762,18 @@ MUTATOR_HOOKFUNCTION(td_MonsterMove) return FALSE; } + if((vlen(self.goalentity.origin - self.origin) <= 100 && self.goalentity.classname == "td_waypoint") || (vlen(self.goalentity.origin - self.origin) <= 200 && self.flags & FL_FLY && self.goalentity.classname == "td_waypoint")) + { + self.target = self.goalentity.target; + self.goalentity = find(world, targetname, self.target); + } + + if(self.goalentity == world) + self.goalentity = generator; + monster_speed_run = 110 * monster_skill; monster_speed_walk = 75 * monster_skill; - if(vlen(self.realowner.origin - self.origin) < self.realowner.protection_radius && self.realowner.classname == "monster_swarm") - self.takedamage = DAMAGE_NO; - else - self.takedamage = DAMAGE_AIM; - return FALSE; } @@ -789,6 +794,8 @@ MUTATOR_HOOKFUNCTION(td_MonsterSpawn) return TRUE; } + self.spawnshieldtime = time + autocvar_g_td_monsters_spawnshield_time; + self.lastcheck = time; self.drop_size = self.health * 0.05; @@ -871,18 +878,7 @@ MUTATOR_HOOKFUNCTION(td_MonsterFindTarget) FOR_EACH_PLAYER(player) { ++n_players; } if(n_players < 1) // no players online, so do nothing - { return TRUE; - } - - if(vlen(self.goalentity.origin - self.origin) <= 100 && self.goalentity.classname == "waypoint") - self.goalentity.lastchecked = self; - - if((vlen(self.goalentity.origin - self.origin) <= 100 && self.goalentity.classname == "td_waypoint") || (vlen(self.goalentity.origin - self.origin) <= 200 && self.flags & FL_FLY && self.goalentity.classname == "td_waypoint")) - { - self.goalentity = find(world, targetname, self.goalentity.target); - self.target = self.goalentity.target; - } if(generator == world) { @@ -905,27 +901,6 @@ MUTATOR_HOOKFUNCTION(td_MonsterFindTarget) if((vlen(trace_endpos - self.origin) < 100 && e.turrcaps_flags & TFL_TURRCAPS_ISTURRET) || (vlen(trace_endpos - self.origin) < 200 && e != generator) || (vlen(trace_endpos - self.origin) < 500 && e == generator)) { self.enemy = e; - return TRUE; - } - } - if(self.target) // follow target if available - { - self.goalentity = find(world, targetname, self.target); - if(self.goalentity == world) - self.goalentity = generator; - return TRUE; - } - else - self.goalentity = generator; - - for(e = world;(e = find(e, classname, "waypoint")); ) - { - if(vlen(e.origin - self.origin) < 500) - if(e.lastchecked != self) - if(vlen(e.origin - self.origin) > 50) - { - //print(strcat("Goal found at ", vtos(e.origin), "\n")); - self.goalentity = e; } } diff --git a/qcsrc/server/mutators/gamemode_td.qh b/qcsrc/server/mutators/gamemode_td.qh index 692687620..84cec1a25 100644 --- a/qcsrc/server/mutators/gamemode_td.qh +++ b/qcsrc/server/mutators/gamemode_td.qh @@ -25,6 +25,7 @@ float SWARM_WEAK = 1; float SWARM_STRONG = 2; float SWARM_FLY = 3; float SWARM_SWIM = 4; +float build_time; float td_dont_end; .float lastcheck; void(float starting) wave_end; @@ -32,7 +33,6 @@ void(float starting) wave_end; float td_gencount; void() spawnfunc_td_controller; float oldrespawncvar; -.float protection_radius; float current_phase; #define PHASE_BUILD 1 #define PHASE_COMBAT 2 @@ -50,10 +50,10 @@ float current_phase; .float startwave; .float dontend; .float maxturrets; +.float buildtime; // Generator float gendestroyed; -.entity lastchecked; entity generator; // global generator entity (TODO: replace with a script for multi generator support?) float gendmg; #define GENERATOR_MIN '-52 -52 -14' -- 2.39.2