#include "sv_monsters.qh"
-#include <server/g_subs.qh>
#include <lib/warpzone/common.qh>
#include "../constants.qh"
#include "../teams.qh"
#include "../vehicles/all.qh"
#include <server/campaign.qh>
#include <server/command/_mod.qh>
-#include "../triggers/triggers.qh"
+#include "../mapobjects/triggers.qh"
#include <lib/csqcmodel/sv_model.qh>
#include <server/round_handler.qh>
#include <server/weapons/_mod.qh>
return;
vector org = CENTER_OR_VIEWOFS(this);
- entity e = new(droppedweapon); // use weapon handling to remove it on touch
+ entity e = spawn();
+ Item_SetLoot(e, true);
e.spawnfunc_checked = true;
e.monster_loot = this.monster_loot;
e.noalign = true;
StartItem(e, e.monster_loot);
e.gravity = 1;
- set_movetype(e, MOVETYPE_TOSS);
- e.reset = SUB_Remove;
setorigin(e, org);
e.velocity = randomvec() * 175 + '0 0 325';
e.item_spawnshieldtime = time + 0.7;
|| (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))
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
}
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;
if(delaytoo)
if(time < this.msound_delay)
return; // too early
- GlobalSound_string(this, this.(samplefield), chan, VOL_BASE, VOICETYPE_PLAYERSOUND);
+ string sample = this.(samplefield);
+ if (sample != "") sample = GlobalSound_sample(sample, random());
+ float myscale = ((this.scale) ? this.scale : 1); // safety net
+ // TODO: change volume depending on size too?
+ sound7(this, chan, sample, VOL_BASE, ATTEN_NORM, 100 / myscale, 0);
this.msound_delay = time + sound_delay;
}
traceline(this.origin + this.view_ofs, this.origin + v_forward * er, 0, this);
if(trace_ent.takedamage)
- Damage(trace_ent, this, this, damg * MONSTER_SKILLMOD(this), deathtype, trace_ent.origin, normalize(trace_ent.origin - this.origin));
+ Damage(trace_ent, this, this, damg * MONSTER_SKILLMOD(this), deathtype, DMG_NOWEP, trace_ent.origin, normalize(trace_ent.origin - this.origin));
return true;
}
{
this.last_trace = time + 0.4;
- Damage (this, NULL, NULL, 2, DEATH_DROWN.m_id, this.origin, '0 0 0');
+ Damage (this, NULL, NULL, 2, DEATH_DROWN.m_id, DMG_NOWEP, this.origin, '0 0 0');
this.angles = '90 90 0';
if(random() < 0.5)
{
this.moveto = this.origin;
}
-void Monster_Dead_Damage(entity this, entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
+void Monster_Dead_Damage(entity this, entity inflictor, entity attacker, float damage, int deathtype, .entity weaponentity, vector hitloc, vector force)
{
this.health -= damage;
if(IS_PLAYER(attacker))
if(autocvar_g_monsters_score_spawned || !((this.spawnflags & MONSTERFLAG_SPAWNED) || (this.spawnflags & MONSTERFLAG_RESPAWNED)))
- PlayerScore_Add(attacker, SP_SCORE, +autocvar_g_monsters_score_kill);
+ GameRules_scoring_add(attacker, SCORE, +autocvar_g_monsters_score_kill);
if(gibbed)
{
}
}
-void Monster_Damage(entity this, entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
+void Monster_Damage(entity this, entity inflictor, entity attacker, float damage, int deathtype, .entity weaponentity, vector hitloc, vector force)
{
if((this.spawnflags & MONSTERFLAG_INVINCIBLE) && deathtype != DEATH_KILL.m_id && !ITEM_DAMAGE_NEEDKILL(deathtype))
return;
{
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);
Unfreeze(this);
this.health = 0;
if(this.event_damage)
- this.event_damage(this, this, this.frozen_by, 1, DEATH_NADE_ICE_FREEZE.m_id, this.origin, '0 0 0');
+ 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!
if(this.monster_lifetime && time >= this.monster_lifetime)
{
- Damage(this, this, this, this.health + this.max_health, DEATH_KILL.m_id, this.origin, this.origin);
+ Damage(this, this, this, this.health + this.max_health, DEATH_KILL.m_id, DMG_NOWEP, this.origin, this.origin);
return;
}