]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/common/monsters/sv_monsters.qc
Merge branch 'master' into Mario/monsters
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / monsters / sv_monsters.qc
index 695d1101952e9d3f531aceef9c073324322b1669..f693ee4513456d0f84ae3905af6d8671ed9da95e 100644 (file)
@@ -82,6 +82,7 @@ bool Monster_ValidTarget(entity this, entity targ)
        || (IS_VEHICLE(targ) && !((Monsters_from(this.monsterid)).spawnflags & MON_FLAG_RANGED)) // melee vs vehicle is useless
        || (time < game_starttime) // monsters do nothing before match has started
        || (targ.takedamage == DAMAGE_NO)
+       || (game_stopped)
        || (targ.items & IT_INVISIBILITY)
        || (IS_SPEC(targ) || IS_OBSERVER(targ)) // don't attack spectators
        || (!IS_VEHICLE(targ) && (IS_DEAD(targ) || IS_DEAD(this) || targ.health <= 0 || this.health <= 0))
@@ -99,7 +100,7 @@ bool Monster_ValidTarget(entity this, entity targ)
        }
 
        vector targ_origin = ((targ.absmin + targ.absmax) * 0.5);
-       traceline(this.origin + this.view_ofs, targ_origin, MOVE_NOMONSTERS, this);
+       traceline(this.origin + this.view_ofs, targ_origin, MOVE_NOMONSTERS, this); // TODO: maybe we can rely a bit on PVS data instead?
 
        if(trace_fraction < 1 && trace_ent != targ)
                return false; // solid
@@ -124,21 +125,27 @@ entity Monster_FindTarget(entity this)
        vector my_center = CENTER_OR_VIEWOFS(this);
 
        // find the closest acceptable target to pass to
-       IL_EACH(g_monster_targets, it.monster_attack && vdist(it.origin - this.origin, <, this.target_range),
+       IL_EACH(g_monster_targets, it.monster_attack,
        {
-               if(Monster_ValidTarget(this, it))
-               {
-                       // if it's a player, use the view origin as reference (stolen from RadiusDamage functions in g_damage.qc)
-                       vector targ_center = CENTER_OR_VIEWOFS(it);
+               float trange = this.target_range;
+               if(PHYS_INPUT_BUTTON_CROUCH(it))
+                       trange *= 0.75; // TODO cvar this
+               vector theirmid = (it.absmin + it.absmax) * 0.5;
+               if(vdist(theirmid - this.origin, >, trange))
+                       continue;
+               if(!Monster_ValidTarget(this, it))
+                       continue;
 
-                       if(closest_target)
-                       {
-                               vector closest_target_center = CENTER_OR_VIEWOFS(closest_target);
-                               if(vlen2(my_center - targ_center) < vlen2(my_center - closest_target_center))
-                                       { closest_target = it; }
-                       }
-                       else { closest_target = it; }
+               // if it's a player, use the view origin as reference (stolen from RadiusDamage functions in g_damage.qc)
+               vector targ_center = CENTER_OR_VIEWOFS(it);
+
+               if(closest_target)
+               {
+                       vector closest_target_center = CENTER_OR_VIEWOFS(closest_target);
+                       if(vlen2(my_center - targ_center) < vlen2(my_center - closest_target_center))
+                               { closest_target = it; }
                }
+               else { closest_target = it; }
        });
 
        return closest_target;
@@ -165,6 +172,11 @@ void monster_setupcolors(entity this)
                else
                        this.colormap = 1024;
        }
+
+       if(this.colormap > 0)
+               this.glowmod = colormapPaletteColor(this.colormap & 0x0F, false);
+       else
+               this.glowmod = '1 1 1';
 }
 
 void monster_changeteam(entity this, int newteam)
@@ -275,7 +287,7 @@ void Monster_Sounds_Precache(entity this)
 
 void Monster_Sounds_Clear(entity this)
 {
-#define _MSOUND(m) if(this.monstersound_##m) { strunzone(this.monstersound_##m); this.monstersound_##m = string_null; }
+#define _MSOUND(m) strfree(this.monstersound_##m);
        ALLMONSTERSOUNDS
 #undef _MSOUND
 }
@@ -310,9 +322,7 @@ bool Monster_Sounds_Load(entity this, string f, int first)
                field = Monster_Sound_SampleField(argv(0));
                if(GetMonsterSoundSampleField_notFound)
                        continue;
-               if (this.(field))
-                       strunzone(this.(field));
-               this.(field) = strzone(strcat(argv(1), " ", argv(2)));
+               strcpy(this.(field), strcat(argv(1), " ", argv(2)));
        }
        fclose(fh);
        return true;
@@ -1151,20 +1161,20 @@ void Monster_Frozen_Think(entity this)
 {
        if(STAT(FROZEN, this) == 2)
        {
-               this.revive_progress = bound(0, this.revive_progress + this.ticrate * this.revive_speed, 1);
-               this.health = max(1, this.revive_progress * this.max_health);
-               this.iceblock.alpha = bound(0.2, 1 - this.revive_progress, 1);
+               STAT(REVIVE_PROGRESS, this) = bound(0, STAT(REVIVE_PROGRESS, this) + this.ticrate * this.revive_speed, 1);
+               this.health = max(1, STAT(REVIVE_PROGRESS, this) * this.max_health);
+               this.iceblock.alpha = bound(0.2, 1 - STAT(REVIVE_PROGRESS, this), 1);
 
                if(!(this.spawnflags & MONSTERFLAG_INVINCIBLE) && this.sprite)
                        WaypointSprite_UpdateHealth(this.sprite, this.health);
 
-               if(this.revive_progress >= 1)
+               if(STAT(REVIVE_PROGRESS, this) >= 1)
                        Unfreeze(this);
        }
        else if(STAT(FROZEN, this) == 3)
        {
-               this.revive_progress = bound(0, this.revive_progress - this.ticrate * this.revive_speed, 1);
-               this.health = max(0, autocvar_g_nades_ice_health + (this.max_health-autocvar_g_nades_ice_health) * this.revive_progress );
+               STAT(REVIVE_PROGRESS, this) = bound(0, STAT(REVIVE_PROGRESS, this) - this.ticrate * this.revive_speed, 1);
+               this.health = max(0, autocvar_g_nades_ice_health + (this.max_health-autocvar_g_nades_ice_health) * STAT(REVIVE_PROGRESS, this) );
 
                if(!(this.spawnflags & MONSTERFLAG_INVINCIBLE) && this.sprite)
                        WaypointSprite_UpdateHealth(this.sprite, this.health);
@@ -1177,7 +1187,7 @@ void Monster_Frozen_Think(entity this)
                                this.event_damage(this, this, this.frozen_by, 1, DEATH_NADE_ICE_FREEZE.m_id, DMG_NOWEP, this.origin, '0 0 0');
                }
 
-               else if ( this.revive_progress <= 0 )
+               else if ( STAT(REVIVE_PROGRESS, this) <= 0 )
                        Unfreeze(this);
        }
        // otherwise, no revival!
@@ -1387,7 +1397,7 @@ bool Monster_Spawn(entity this, bool check_appear, int mon_id)
        if(autocvar_g_nodepthtestplayers) { this.effects |= EF_NODEPTHTEST; }
        if(mon.spawnflags & MONSTER_TYPE_SWIM) { this.flags |= FL_SWIM; }
 
-       if(autocvar_g_playerclip_collisions)
+       if(autocvar_g_monsters_playerclip_collisions)
                this.dphitcontentsmask |= DPCONTENTS_PLAYERCLIP;
 
        if(mon.spawnflags & MONSTER_TYPE_FLY)
@@ -1396,15 +1406,8 @@ bool Monster_Spawn(entity this, bool check_appear, int mon_id)
                set_movetype(this, MOVETYPE_FLY);
        }
 
-       if(!(this.spawnflags & MONSTERFLAG_RESPAWNED))
-       {
-               if(mon.spawnflags & MONSTER_SIZE_BROKEN)
-                       this.scale *= 1.3;
-
-               if(mon.spawnflags & MONSTER_SIZE_QUAKE)
-               if(autocvar_g_monsters_quake_resize)
-                       this.scale *= 1.3;
-       }
+       if((mon.spawnflags & MONSTER_SIZE_QUAKE) && autocvar_g_monsters_quake_resize && !(this.spawnflags & MONSTERFLAG_RESPAWNED))
+               this.scale *= 1.3;
 
        setsize(this, mon.m_mins * this.scale, mon.m_maxs * this.scale);