From: Mario Date: Fri, 8 Feb 2013 00:17:25 +0000 (+1100) Subject: Some more targeting cleanup (fixes monsters targeting invisible players after re... X-Git-Tag: xonotic-v0.8.0~241^2^2~534 X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=eb35949fe1a06854ffb501491d55ec5575c78949;p=xonotic%2Fxonotic-data.pk3dir.git Some more targeting cleanup (fixes monsters targeting invisible players after re-spawning a few times) --- diff --git a/qcsrc/server/monsters/lib/monsters.qc b/qcsrc/server/monsters/lib/monsters.qc index 5ca1ae568..33a1e1efa 100644 --- a/qcsrc/server/monsters/lib/monsters.qc +++ b/qcsrc/server/monsters/lib/monsters.qc @@ -231,7 +231,7 @@ void Monster_Fade () self.nextthink = time + self.respawntime; setorigin(self, self.pos1); self.angles = self.pos2; - self.health = 0; + self.health = self.max_health; // TODO: check if resetting to max_health is wise here return; } self.think = SUB_Remove; @@ -469,6 +469,9 @@ void monster_move(float runspeed, float walkspeed, float stopspeed, float manim_ if(self.enemy.health <= 0 || (!autocvar_g_monsters_typefrag && self.enemy.BUTTON_CHAT)) self.enemy = world; + if not(self.enemy.takedamage) + self.enemy = world; + if not(self.enemy) self.enemy = FindTarget(self); @@ -619,7 +622,11 @@ void monsters_damage (entity inflictor, entity attacker, float damage, float dea self.target2 = ""; SUB_UseTargets(); - self.monster_die(); + self.monster_die(); + + frag_attacker = attacker; + frag_target = self; + MUTATOR_CALLHOOK(MonsterDies); } } @@ -639,14 +646,11 @@ void monster_hook_death() self.realowner.monstercount -= 1; totalspawned -= 1; - - MUTATOR_CALLHOOK(MonsterDies); } // used to hook into monster post spawn functions without a mutator void monster_hook_spawn() { - self.health *= monster_skill; // skill based monster health? self.max_health = self.health; if(teamplay && autocvar_g_monsters_teams) @@ -683,11 +687,11 @@ float monster_initialize(string net_name, return FALSE; // support for quake style removing monsters based on skill - if(autocvar_skill <= autocvar_g_monsters_skill_easy && (self.spawnflags & MONSTERSKILL_NOTEASY)) { return FALSE; } - else if(autocvar_skill == autocvar_g_monsters_skill_normal && (self.spawnflags & MONSTERSKILL_NOTMEDIUM)) { return FALSE; } - else if(autocvar_skill == autocvar_g_monsters_skill_hard && (self.spawnflags & MONSTERSKILL_NOTHARD)) { return FALSE; } - else if(autocvar_skill == autocvar_g_monsters_skill_insane && (self.spawnflags & MONSTERSKILL_NOTINSANE)) { return FALSE; } - else if(autocvar_skill >= autocvar_g_monsters_skill_nightmare && (self.spawnflags & MONSTERSKILL_NOTNIGHTMARE)) { return FALSE; } + if(monster_skill <= autocvar_g_monsters_skill_easy && (self.spawnflags & MONSTERSKILL_NOTEASY)) { return FALSE; } + if(monster_skill == autocvar_g_monsters_skill_normal && (self.spawnflags & MONSTERSKILL_NOTMEDIUM)) { return FALSE; } + if(monster_skill == autocvar_g_monsters_skill_hard && (self.spawnflags & MONSTERSKILL_NOTHARD)) { return FALSE; } + if(monster_skill == autocvar_g_monsters_skill_insane && (self.spawnflags & MONSTERSKILL_NOTINSANE)) { return FALSE; } + if(monster_skill >= autocvar_g_monsters_skill_nightmare && (self.spawnflags & MONSTERSKILL_NOTNIGHTMARE)) { return FALSE; } if(self.model == "") if(bodymodel == "") diff --git a/qcsrc/server/mutators/gamemode_rts.qc b/qcsrc/server/mutators/gamemode_rts.qc index cd815b991..c9a570571 100644 --- a/qcsrc/server/mutators/gamemode_rts.qc +++ b/qcsrc/server/mutators/gamemode_rts.qc @@ -9,11 +9,47 @@ void spawnfunc_healing_tower() spawnfunc_turret_fusionreactor(); self.classname = "healing_tower"; self.target_range = 1000; - self.shot_dmg = 20; + self.shot_dmg = 30; +} + +void rts_waypoint_think() +{ + float goalcount = 0; + entity e; + + self.nextthink = time + 0.1; + + for(e = world; (e = findentity(e, goalentity, self)); ) + { + ++goalcount; + } + + if(goalcount < 1) + { + WaypointSprite_Kill(self.sprite); + remove(self); + return; + } +} + +void Monster_LevelUp(entity e) +{ + if(self.level >= 5) + return; // max level is 5 for now + e.speed += 0.25; + e.max_health += 20; + e.health = e.max_health; + e.level += 1; + WaypointSprite_UpdateHealth(e.sprite, e.health); } MUTATOR_HOOKFUNCTION(rts_PlayerSpawn) { + if(self.rts_viewangle) + self.angles_x = self.rts_viewangle; + else + self.angles_x = 30; + self.effects |= EF_NODRAW; self.oldorigin = self.origin; self.monster_attack = FALSE; @@ -21,7 +57,6 @@ MUTATOR_HOOKFUNCTION(rts_PlayerSpawn) self.takedamage = DAMAGE_NO; self.flags |= FL_NOTARGET; self.movetype = MOVETYPE_NOCLIP; - self.angles_x = 30; stuffcmd(self, "cl_cmd settemp cl_prydoncursor 1\n"); return FALSE; } @@ -57,28 +92,20 @@ MUTATOR_HOOKFUNCTION(rts_PlayerThink) self.oldorigin_z -= 50; break; } - self.hasweapon_complain_spam = time + 99999; // no spam + self.hasweapon_complain_spam = time + 9999999999; // no spam - entity head, w, wp = world; + entity head, wp = world; if(!self.cursor_trace_ent && self.BUTTON_ATCK && time >= self.last_click) { FOR_EACH_MONSTER(head) { - if(head.goalentity) head.goalentity.selected = TRUE; // do this to make sure we're not removing any owned waypoints below - if(head.owner != self) continue; - + head.selected = FALSE; if(!self.enemy) head.owner = world; } - - for(w = world; (w = find(w, classname, "monster_waypoint")); ) - { - if not(w.selected) - remove(w); - } } if(self.cursor_trace_ent.flags & FL_MONSTER && self.BUTTON_ATCK && time >= self.last_click) { @@ -101,20 +128,20 @@ MUTATOR_HOOKFUNCTION(rts_PlayerThink) } if(self.BUTTON_ATCK2) { - entity e = world; - if(self.cursor_trace_ent) e = self.cursor_trace_ent; - else e = findradius(self.cursor_trace_endpos, 50); - - if not(IsDifferentTeam(e, self)) - e = world; // same team + entity e = self.cursor_trace_ent; - if not(e.takedamage) - e = world; // can't hurt this enemy + if(e) + if not(IsDifferentTeam(e, self) || e.takedamage) + e = world; - if(e == world) + if not(e) { wp = spawn(); wp.classname = "monster_waypoint"; // set so we can kill this later + wp.owner = self; // hmm... + wp.think = rts_waypoint_think; + wp.nextthink = time; + WaypointSprite_Spawn("Waypoint", 0, 0, wp, '0 0 10', world, 0, wp, sprite, FALSE, RADARICON_DANGER, ((teamplay) ? TeamColor(self.team) : '1 0 0')); setorigin(wp, self.cursor_trace_endpos); } @@ -125,11 +152,10 @@ MUTATOR_HOOKFUNCTION(rts_PlayerThink) if(e) { - remove(head.goalentity); head.goalentity = world; head.enemy = e; } - else if(wp) + else { head.goalentity = wp; head.enemy = world; @@ -142,7 +168,20 @@ MUTATOR_HOOKFUNCTION(rts_PlayerThink) MUTATOR_HOOKFUNCTION(rts_MonsterSpawn) { - self.respawntime = 10; // default to 5 seconds for now + // new monster + if not(self.monster_respawned) + { + self.level = 0; + self.speed = 1; + } + + self.spawnflags = MONSTERFLAG_NORESPAWN; + + self.goalentity = world; + self.enemy = world; + self.moveto = self.origin; + + self.respawntime = 10; // default to 10 seconds for now self.effects |= EF_SELECTABLE; self.monster_moveflags = MONSTER_MOVE_NOMOVE; @@ -166,33 +205,33 @@ MUTATOR_HOOKFUNCTION(rts_MonsterThink) self.heal_delay = time + 2; } - monster_speed_run = 150; - monster_speed_walk = 150; + monster_speed_run = 150 * self.speed; + monster_speed_walk = 150 * self.speed; + + if(monster_target.classname == "player") + monster_target = world; if(self.selected) self.colormod = color * 4; else self.colormod = color; - - if(self.goalentity) + + if(monster_target) self.enemy = world; // don't ignore our owner's commands - if(!self.sprite) + if not(self.sprite) { - WaypointSprite_Spawn(self.netname, 0, 0, self, '0 0 1' * self.sprite_height, world, self.team, self, sprite, FALSE, RADARICON_DANGER, ((teamplay) ? TeamColor(self.team) : '1 0 0')); + WaypointSprite_Spawn(self.netname, 0, 0, self, '0 0 1' * self.sprite_height, world, self.team, self, sprite, FALSE, RADARICON_DANGER, ((teamplay) ? TeamColor(self.team) : '1 0 0')); WaypointSprite_UpdateMaxHealth(self.sprite, self.max_health); WaypointSprite_UpdateHealth(self.sprite, self.health); } - if(!self.selected) if(self.owner) + if not(self.selected) self.owner = world; - if(!IsDifferentTeam(self, self.enemy)) + if not(IsDifferentTeam(self, self.enemy)) self.enemy = world; // no same team fighting - - if(!self.goalentity && !self.enemy && vlen(self.velocity) > 64) // wtf - self.moveto = self.origin; self.last_trace = time; // realtime moving? @@ -201,17 +240,28 @@ MUTATOR_HOOKFUNCTION(rts_MonsterThink) MUTATOR_HOOKFUNCTION(rts_MonsterDies) { - float otherteam = ((self.team == COLOR_TEAM1) ? COLOR_TEAM2 : COLOR_TEAM1); + if(IsDifferentTeam(frag_attacker, frag_target) && frag_attacker.team) + TeamScore_AddToTeam(frag_attacker.team, ST_SCORE, 1); - TeamScore_AddToTeam(otherteam, ST_SCORE, 1); + // need to keep the monster selected to get the points... hmm (TODO: realowners?) + if(frag_attacker.owner.classname == "player") + { + PlayerScore_Add(frag_attacker.owner, SP_SCORE, 5); + PlayerScore_Add(frag_attacker.owner, SP_KILLS, 1); + } + + if(frag_attacker.flags & FL_MONSTER) + { + frag_attacker.monster_score += 5; + if(frag_attacker.monster_score == 25) + Monster_LevelUp(frag_attacker); + } self.effects &~= EF_SELECTABLE; self.selected = FALSE; - if(self.goalentity) - { - remove(self.goalentity); - self.goalentity = world; - } + + self.goalentity = world; + self.enemy = world; return FALSE; } @@ -271,7 +321,7 @@ MUTATOR_HOOKFUNCTION(rts_PlayerDies) FOR_EACH_MONSTER(head) { if(head.owner != self) continue; - if(!head.selected) continue; + if not(head.selected) continue; if(IsDifferentTeam(self, head)) { diff --git a/qcsrc/server/mutators/gamemode_rts.qh b/qcsrc/server/mutators/gamemode_rts.qh index 8284c1f6c..c08a5c175 100644 --- a/qcsrc/server/mutators/gamemode_rts.qh +++ b/qcsrc/server/mutators/gamemode_rts.qh @@ -1,4 +1,7 @@ .vector oldorigin; .float selected; .float last_click; -.float heal_delay; \ No newline at end of file +.float heal_delay; +.float monster_score; +.float level; +.float rts_viewangle; \ No newline at end of file