From: Mario Date: Sun, 15 Sep 2013 07:14:33 +0000 (+1000) Subject: Merge branch 'master' into Mario/monsters X-Git-Tag: xonotic-v0.8.0~241^2^2~80 X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=2c0e35d3ee9fe6652c9c56f29dbbf546da0043b0;p=xonotic%2Fxonotic-data.pk3dir.git Merge branch 'master' into Mario/monsters --- 2c0e35d3ee9fe6652c9c56f29dbbf546da0043b0 diff --cc qcsrc/common/monsters/monster/cerberus.qc index bbd353acd,000000000..fabaa5a8e mode 100644,000000..100644 --- a/qcsrc/common/monsters/monster/cerberus.qc +++ b/qcsrc/common/monsters/monster/cerberus.qc @@@ -1,186 -1,0 +1,186 @@@ +#ifdef REGISTER_MONSTER +REGISTER_MONSTER( +/* MON_##id */ CERBERUS, +/* function */ m_cerberus, +/* spawnflags */ MON_FLAG_MELEE, +/* mins,maxs */ '-16 -16 -24', '16 16 12', +/* model */ "dog.dpm", +/* netname */ "cerberus", +/* fullname */ _("Cerberus") +); + +#define CERBERUS_SETTINGS(monster) \ + MON_ADD_CVAR(monster, health) \ + MON_ADD_CVAR(monster, attack_bite_damage) \ + MON_ADD_CVAR(monster, attack_jump_damage) \ + MON_ADD_CVAR(monster, speed_stop) \ + MON_ADD_CVAR(monster, speed_run) \ + MON_ADD_CVAR(monster, speed_walk) + +#ifdef SVQC +CERBERUS_SETTINGS(cerberus) +#endif // SVQC +#else +#ifdef SVQC +const float cerberus_anim_idle = 0; +const float cerberus_anim_walk = 1; +const float cerberus_anim_run = 2; +const float cerberus_anim_attack = 3; +const float cerberus_anim_die = 4; +const float cerberus_anim_pain = 5; + +.float cerberus_last_trace; + +void cerberus_findowner() +{ + if(time < self.cerberus_last_trace || self.monster_owner) + return; + + entity head; + + FOR_EACH_MONSTER(head) + if(head.health > 0) + if(head.monsterid == MON_BRUISER) + if(findentity(world, monster_owner, head) == world) + if(vlen(head.origin - self.origin) < self.target_range) - if(!IsDifferentTeam(head, self)) ++ if(SAME_TEAM(head, self)) + if(head.enemy == world) + { + self.monster_owner = head; + break; + } + + self.cerberus_last_trace = time + 3; +} + +void cerberus_checkowner() +{ + if(time < self.cerberus_last_trace) + return; + if(IS_PLAYER(self.monster_owner)) + return; // don't check player masters + + if(vlen(self.origin - self.monster_owner.origin) > self.target_range) + self.monster_owner = world; + if(self.monster_owner.health < 1) + self.monster_owner = world; - if(IsDifferentTeam(self.monster_owner, self)) ++ if(DIFF_TEAM(self.monster_owner, self)) + self.monster_owner = world; + + self.cerberus_last_trace = time + 3; +} + +void cerberus_touch_jump() +{ + if (other.takedamage) + if (vlen(self.velocity) > 300) + { + Damage(self.enemy, self, self, MON_CVAR(cerberus, attack_jump_damage) * monster_skill, DEATH_MONSTER_CERBERUS_JUMP, self.enemy.origin, normalize(self.enemy.origin - self.origin)); + self.touch = MonsterTouch; + } + + if(trace_dphitcontents) + self.touch = MonsterTouch; +} + +float cerberus_attack(float attack_type) +{ + switch(attack_type) + { + case MONSTER_ATTACK_MELEE: + { + return monster_melee(self.enemy, MON_CVAR(cerberus, attack_bite_damage), cerberus_anim_attack, self.attack_range, 0.7, DEATH_MONSTER_CERBERUS_BITE, TRUE); + } + case MONSTER_ATTACK_RANGED: + { + makevectors(self.angles); + return monster_leap(cerberus_anim_attack, cerberus_touch_jump, v_forward * 300 + '0 0 200', 0.8); + } + } + + return FALSE; +} + +void spawnfunc_monster_cerberus() +{ + self.classname = "monster_cerberus"; + + self.monster_spawnfunc = spawnfunc_monster_cerberus; + + if(Monster_CheckAppearFlags(self)) + return; + + if not(monster_initialize(MON_CERBERUS, FALSE)) { remove(self); return; } +} + +// compatibility with old spawns +void spawnfunc_monster_dog() { spawnfunc_monster_cerberus(); } + +float m_cerberus(float req) +{ + switch(req) + { + case MR_THINK: + { + if(self.monster_owner) + cerberus_checkowner(); + else + cerberus_findowner(); + monster_move(MON_CVAR(cerberus, speed_run), MON_CVAR(cerberus, speed_walk), MON_CVAR(cerberus, speed_stop), cerberus_anim_run, cerberus_anim_walk, cerberus_anim_idle); + return TRUE; + } + case MR_DEATH: + { + if(self.monster_owner.flags & FL_MONSTER) + self.monster_owner = world; + monsters_setframe(cerberus_anim_die); + return TRUE; + } + case MR_SETUP: + { + if not(self.health) self.health = MON_CVAR(cerberus, health); + + self.monster_loot = spawnfunc_item_health_small; + self.monster_attackfunc = cerberus_attack; + monsters_setframe(cerberus_anim_idle); + + return TRUE; + } + case MR_INIT: + { + // nothing + return TRUE; + } + case MR_CONFIG: + { + MON_CONFIG_SETTINGS(CERBERUS_SETTINGS(cerberus)) + return TRUE; + } + } + + return TRUE; +} + +#endif // SVQC +#ifdef CSQC +float m_cerberus(float req) +{ + switch(req) + { + case MR_DEATH: + { + // nothing + return TRUE; + } + case MR_INIT: + { + precache_model ("models/monsters/dog.dpm"); + return TRUE; + } + } + + return TRUE; +} + +#endif // CSQC +#endif // REGISTER_MONSTER diff --cc qcsrc/common/monsters/monster/mage.qc index 9b527b76a,000000000..fdba5c0a9 mode 100644,000000..100644 --- a/qcsrc/common/monsters/monster/mage.qc +++ b/qcsrc/common/monsters/monster/mage.qc @@@ -1,488 -1,0 +1,488 @@@ +#ifdef REGISTER_MONSTER +REGISTER_MONSTER( +/* MON_##id */ MAGE, +/* function */ m_mage, +/* spawnflags */ MON_FLAG_MELEE | MON_FLAG_RANGED, +/* mins,maxs */ '-36 -36 -24', '36 36 50', +/* model */ "mage.dpm", +/* netname */ "mage", +/* fullname */ _("Mage") +); + +#define MAGE_SETTINGS(monster) \ + MON_ADD_CVAR(monster, health) \ + MON_ADD_CVAR(monster, attack_spike_damage) \ + MON_ADD_CVAR(monster, attack_spike_radius) \ + MON_ADD_CVAR(monster, attack_spike_delay) \ + MON_ADD_CVAR(monster, attack_spike_accel) \ + MON_ADD_CVAR(monster, attack_spike_decel) \ + MON_ADD_CVAR(monster, attack_spike_turnrate) \ + MON_ADD_CVAR(monster, attack_spike_speed_max) \ + MON_ADD_CVAR(monster, attack_spike_smart) \ + MON_ADD_CVAR(monster, attack_spike_smart_trace_min) \ + MON_ADD_CVAR(monster, attack_spike_smart_trace_max) \ + MON_ADD_CVAR(monster, attack_spike_smart_mindist) \ + MON_ADD_CVAR(monster, attack_melee_damage) \ + MON_ADD_CVAR(monster, attack_melee_delay) \ + MON_ADD_CVAR(monster, attack_grenade_damage) \ + MON_ADD_CVAR(monster, attack_grenade_edgedamage) \ + MON_ADD_CVAR(monster, attack_grenade_force) \ + MON_ADD_CVAR(monster, attack_grenade_radius) \ + MON_ADD_CVAR(monster, attack_grenade_lifetime) \ + MON_ADD_CVAR(monster, attack_grenade_chance) \ + MON_ADD_CVAR(monster, attack_grenade_speed) \ + MON_ADD_CVAR(monster, attack_grenade_speed_up) \ + MON_ADD_CVAR(monster, heal_self) \ + MON_ADD_CVAR(monster, heal_allies) \ + MON_ADD_CVAR(monster, heal_minhealth) \ + MON_ADD_CVAR(monster, heal_range) \ + MON_ADD_CVAR(monster, heal_delay) \ + MON_ADD_CVAR(monster, shield_time) \ + MON_ADD_CVAR(monster, shield_delay) \ + MON_ADD_CVAR(monster, shield_blockpercent) \ + MON_ADD_CVAR(monster, speed_stop) \ + MON_ADD_CVAR(monster, speed_run) \ + MON_ADD_CVAR(monster, speed_walk) + +#ifdef SVQC +MAGE_SETTINGS(mage) +#endif // SVQC +#else +#ifdef SVQC +const float mage_anim_idle = 0; +const float mage_anim_walk = 1; +const float mage_anim_attack = 2; +const float mage_anim_pain = 3; +const float mage_anim_death = 4; +const float mage_anim_run = 5; + +void() mage_heal; +void() mage_shield; + +float friend_needshelp(entity e) +{ + if(e == world) + return FALSE; + if(e.health <= 0) + return FALSE; + if(vlen(e.origin - self.origin) > MON_CVAR(mage, heal_range)) + return FALSE; - if(IsDifferentTeam(e, self)) ++ if(DIFF_TEAM(e, self)) + return FALSE; + if(e.frozen) + return FALSE; + if(!IS_PLAYER(e)) + return (e.health < e.max_health); + if(e.items & IT_INVINCIBLE) + return FALSE; + + switch(self.skin) + { + case 0: return (e.health < autocvar_g_balance_health_regenstable); + case 1: return ((e.ammo_cells && e.ammo_cells < g_pickup_cells_max) || (e.ammo_rockets && e.ammo_rockets < g_pickup_rockets_max) || (e.ammo_nails && e.ammo_nails < g_pickup_nails_max) || (e.ammo_shells && e.ammo_shells < g_pickup_shells_max)); + case 2: return (e.armorvalue < autocvar_g_balance_armor_regenstable); + case 3: return (e.health > 0); + } + + return FALSE; +} + +void mageattack_melee() +{ + monster_melee(self.enemy, MON_CVAR(mage, attack_melee_damage), mage_anim_attack, self.attack_range, MON_CVAR(mage, attack_melee_delay) - 0.2, DEATH_MONSTER_MAGE, TRUE); +} + +void mage_grenade_explode() +{ + pointparticles(particleeffectnum("explosion_small"), self.origin, '0 0 0', 1); + + sound(self, CH_SHOTS, "weapons/grenade_impact.wav", VOL_BASE, ATTEN_NORM); + RadiusDamage (self, self.realowner, MON_CVAR(mage, attack_grenade_damage), MON_CVAR(mage, attack_grenade_edgedamage), MON_CVAR(mage, attack_grenade_radius), world, MON_CVAR(mage, attack_grenade_force), DEATH_MONSTER_MAGE, other); + remove(self); +} + +void mage_grenade_touch() +{ + if(IS_PLAYER(other)) + { + PROJECTILE_TOUCH; + mage_grenade_explode(); + return; + } +} + +void mage_throw_itemgrenade() +{ + makevectors(self.angles); + + entity gren = spawn (); + gren.owner = gren.realowner = self; + gren.classname = "grenade"; + gren.bot_dodge = FALSE; + gren.movetype = MOVETYPE_BOUNCE; + gren.solid = SOLID_TRIGGER; + gren.projectiledeathtype = DEATH_MONSTER_MAGE; + setorigin(gren, CENTER_OR_VIEWOFS(self)); + setsize(gren, '-64 -64 -64', '64 64 64'); + + gren.nextthink = time + MON_CVAR(mage, attack_grenade_lifetime); + gren.think = mage_grenade_explode; + gren.use = mage_grenade_explode; + gren.touch = mage_grenade_touch; + + gren.missile_flags = MIF_SPLASH | MIF_ARC; + W_SetupProjectileVelocityEx(gren, v_forward, v_up, MON_CVAR(mage, attack_grenade_speed), MON_CVAR(mage, attack_grenade_speed_up), 0, 0, FALSE); + + gren.flags = FL_PROJECTILE; + + setmodel(gren, "models/items/g_h50.md3"); + + self.attack_finished_single = time + 1.5; +} + +void mage_spike_explode() +{ + self.event_damage = func_null; + + sound(self, CH_SHOTS, "weapons/grenade_impact.wav", VOL_BASE, ATTEN_NORM); + + pointparticles(particleeffectnum("explosion_small"), self.origin, '0 0 0', 1); + RadiusDamage (self, self.realowner, MON_CVAR(mage, attack_spike_damage), MON_CVAR(mage, attack_spike_damage) * 0.5, MON_CVAR(mage, attack_spike_radius), world, 0, DEATH_MONSTER_MAGE, other); + + remove (self); +} + +void mage_spike_touch() +{ + PROJECTILE_TOUCH; + + mage_spike_explode(); +} + +// copied from W_Seeker_Think +void mage_spike_think() +{ + entity e; + vector desireddir, olddir, newdir, eorg; + float turnrate; + float dist; + float spd; + + if (time > self.ltime || self.enemy.health <= 0 || self.owner.health <= 0) + { + self.projectiledeathtype |= HITTYPE_SPLASH; + mage_spike_explode(); + } + + spd = vlen(self.velocity); + spd = bound( + spd - MON_CVAR(mage, attack_spike_decel) * frametime, + MON_CVAR(mage, attack_spike_speed_max), + spd + MON_CVAR(mage, attack_spike_accel) * frametime + ); + + if (self.enemy != world) + if (self.enemy.takedamage != DAMAGE_AIM || self.enemy.deadflag != DEAD_NO) + self.enemy = world; + + if (self.enemy != world) + { + e = self.enemy; + eorg = 0.5 * (e.absmin + e.absmax); + turnrate = MON_CVAR(mage, attack_spike_turnrate); // how fast to turn + desireddir = normalize(eorg - self.origin); + olddir = normalize(self.velocity); // get my current direction + dist = vlen(eorg - self.origin); + + // Do evasive maneuvers for world objects? ( this should be a cpu hog. :P ) + if (MON_CVAR(mage, attack_spike_smart) && (dist > MON_CVAR(mage, attack_spike_smart_mindist))) + { + // Is it a better idea (shorter distance) to trace to the target itself? + if ( vlen(self.origin + olddir * self.wait) < dist) + traceline(self.origin, self.origin + olddir * self.wait, FALSE, self); + else + traceline(self.origin, eorg, FALSE, self); + + // Setup adaptive tracelength + self.wait = bound(MON_CVAR(mage, attack_spike_smart_trace_min), vlen(self.origin - trace_endpos), self.wait = MON_CVAR(mage, attack_spike_smart_trace_max)); + + // Calc how important it is that we turn and add this to the desierd (enemy) dir. + desireddir = normalize(((trace_plane_normal * (1 - trace_fraction)) + (desireddir * trace_fraction)) * 0.5); + } + + newdir = normalize(olddir + desireddir * turnrate); // take the average of the 2 directions; not the best method but simple & easy + self.velocity = newdir * spd; // make me fly in the new direction at my flight speed + } + else + dist = 0; + + /////////////// + + //self.angles = vectoangles(self.velocity); // turn model in the new flight direction + self.nextthink = time;// + 0.05; // csqc projectiles + UpdateCSQCProjectile(self); +} + +void mage_spike() +{ + entity missile; + vector dir = normalize((self.enemy.origin + '0 0 10') - self.origin); + + makevectors(self.angles); + + missile = spawn (); + missile.owner = missile.realowner = self; + missile.think = mage_spike_think; + missile.ltime = time + 7; + missile.nextthink = time; + missile.solid = SOLID_BBOX; + missile.movetype = MOVETYPE_FLYMISSILE; + missile.flags = FL_PROJECTILE; + setorigin(missile, self.origin + v_forward * 14 + '0 0 30' + v_right * -14); + setsize (missile, '0 0 0', '0 0 0'); + missile.velocity = dir * 400; + missile.avelocity = '300 300 300'; + missile.enemy = self.enemy; + missile.touch = mage_spike_touch; + + CSQCProjectile(missile, TRUE, PROJECTILE_MAGE_SPIKE, TRUE); +} + +void mage_heal() +{ + entity head; + float washealed = FALSE; + + for(head = world; (head = findfloat(head, monster_attack, TRUE)); ) if(friend_needshelp(head)) + { + washealed = TRUE; + string fx = ""; + if(IS_PLAYER(head)) + { + switch(self.skin) + { + case 0: + if(head.health < autocvar_g_balance_health_regenstable) head.health = bound(0, head.health + MON_CVAR(mage, heal_allies), autocvar_g_balance_health_regenstable); + fx = "healing_fx"; + break; + case 1: + if(head.ammo_cells) head.ammo_cells = bound(head.ammo_cells, head.ammo_cells + 1, g_pickup_cells_max); + if(head.ammo_rockets) head.ammo_rockets = bound(head.ammo_rockets, head.ammo_rockets + 1, g_pickup_rockets_max); + if(head.ammo_shells) head.ammo_shells = bound(head.ammo_shells, head.ammo_shells + 2, g_pickup_shells_max); + if(head.ammo_nails) head.ammo_nails = bound(head.ammo_nails, head.ammo_nails + 5, g_pickup_nails_max); + fx = "ammoregen_fx"; + break; + case 2: + if(head.armorvalue < autocvar_g_balance_armor_regenstable) + { + head.armorvalue = bound(0, head.armorvalue + MON_CVAR(mage, heal_allies), autocvar_g_balance_armor_regenstable); + fx = "armorrepair_fx"; + } + break; + case 3: + head.health = bound(0, head.health - ((head == self) ? MON_CVAR(mage, heal_self) : MON_CVAR(mage, heal_allies)), autocvar_g_balance_health_regenstable); + fx = "rage"; + break; + } + + pointparticles(particleeffectnum(fx), head.origin, '0 0 0', 1); + } + else + { + pointparticles(particleeffectnum("healing_fx"), head.origin, '0 0 0', 1); + head.health = bound(0, head.health + MON_CVAR(mage, heal_allies), head.max_health); + head.SendFlags |= MSF_STATUS; + } + } + + if(washealed) + { + monsters_setframe(mage_anim_attack); + self.attack_finished_single = time + MON_CVAR(mage, heal_delay); + } +} + +void mage_shield_think() +{ + self.nextthink = time; + + if(time >= self.ltime || self.owner.health <= 0) + { + self.owner.armorvalue = 0; + self.owner.m_armor_blockpercent = autocvar_g_monsters_armor_blockpercent; + remove(self); + return; + } +} + +void mage_shield() +{ + if(self.weaponentity) + return; // already have a shield + + entity shield = spawn(); + + shield.owner = self; + shield.team = self.team; + shield.ltime = time + MON_CVAR(mage, shield_time); + shield.classname = "shield"; + shield.effects = EF_ADDITIVE; + shield.movetype = MOVETYPE_NOCLIP; + shield.solid = SOLID_TRIGGER; + shield.avelocity = '7 0 11'; + shield.scale = self.scale * 0.6; + shield.think = mage_shield_think; + shield.nextthink = time; + + setattachment(shield, self, ""); + setmodel(shield, "models/ctf/shield.md3"); + setsize(shield, shield.scale * shield.mins, shield.scale * shield.maxs); + + self.lastshielded = time + MON_CVAR(mage, shield_delay); + + monsters_setframe(mage_anim_attack); + self.attack_finished_single = time + 1; + + self.m_armor_blockpercent = MON_CVAR(mage, shield_blockpercent); + self.armorvalue = self.health; +} + +float mage_attack(float attack_type) +{ + switch(attack_type) + { + case MONSTER_ATTACK_MELEE: + { + monsters_setframe(mage_anim_attack); + self.attack_finished_single = time + MON_CVAR(mage, attack_melee_delay); + defer(0.2, mageattack_melee); + + return TRUE; + } + case MONSTER_ATTACK_RANGED: + { + if(random() < MON_CVAR(mage, attack_grenade_chance) / 100) + { + mage_throw_itemgrenade(); + return TRUE; + } + + monsters_setframe(mage_anim_attack); + self.attack_finished_single = time + MON_CVAR(mage, attack_spike_delay); + defer(0.2, mage_spike); + + return TRUE; + } + } + + return FALSE; +} + +void spawnfunc_monster_mage() +{ + self.classname = "monster_mage"; + + self.monster_spawnfunc = spawnfunc_monster_mage; + + if(Monster_CheckAppearFlags(self)) + return; + + if not(monster_initialize(MON_MAGE, FALSE)) { remove(self); return; } +} + +// compatibility with old spawns +void spawnfunc_monster_shalrath() { spawnfunc_monster_mage(); } + +float m_mage(float req) +{ + switch(req) + { + case MR_THINK: + { + entity head; + float need_help = FALSE; + + FOR_EACH_PLAYER(head) + if(friend_needshelp(head)) + { + need_help = TRUE; + break; // found 1 player near us who is low on health + } + if(!need_help) + FOR_EACH_MONSTER(head) + if(head != self) + if(friend_needshelp(head)) + { + need_help = TRUE; + break; // found 1 player near us who is low on health + } + + if(self.health < MON_CVAR(mage, heal_minhealth) || need_help) + if(time >= self.attack_finished_single) + if(random() < 0.5) + mage_heal(); + + if(self.enemy) + if(self.health < self.max_health) + if(time >= self.lastshielded) + if(random() < 0.5) + mage_shield(); + + monster_move(MON_CVAR(mage, speed_run), MON_CVAR(mage, speed_walk), MON_CVAR(mage, speed_stop), mage_anim_walk, mage_anim_run, mage_anim_idle); + return TRUE; + } + case MR_DEATH: + { + monsters_setframe(mage_anim_death); + return TRUE; + } + case MR_SETUP: + { + if not(self.health) self.health = MON_CVAR(mage, health); + + self.monster_loot = spawnfunc_item_health_large; + self.monster_attackfunc = mage_attack; + monsters_setframe(mage_anim_walk); + + return TRUE; + } + case MR_INIT: + { + precache_model ("models/items/g_h50.md3"); + precache_model ("models/ctf/shield.md3"); + precache_sound ("weapons/grenade_impact.wav"); + return TRUE; + } + case MR_CONFIG: + { + MON_CONFIG_SETTINGS(MAGE_SETTINGS(mage)) + return TRUE; + } + } + + return TRUE; +} + +#endif // SVQC +#ifdef CSQC +float m_mage(float req) +{ + switch(req) + { + case MR_DEATH: + { + // nothing + return TRUE; + } + case MR_INIT: + { + precache_model ("models/monsters/mage.dpm"); + return TRUE; + } + } + + return TRUE; +} + +#endif // CSQC +#endif // REGISTER_MONSTER diff --cc qcsrc/common/monsters/sv_monsters.qc index 3bb91e13c,000000000..f6856edee mode 100644,000000..100644 --- a/qcsrc/common/monsters/sv_monsters.qc +++ b/qcsrc/common/monsters/sv_monsters.qc @@@ -1,1128 -1,0 +1,1128 @@@ +// ========================= +// SVQC Monster Properties +// ========================= + + +void monster_item_spawn() +{ + if(self.monster_loot) + self.monster_loot(); + + self.gravity = 1; + self.velocity = randomvec() * 175 + '0 0 325'; + self.classname = "droppedweapon"; // hax + + SUB_SetFade(self, time + autocvar_g_monsters_drop_time, 1); +} + +void monster_dropitem() +{ + if(!self.candrop || !self.monster_loot) + return; + + vector org = self.origin + ((self.mins + self.maxs) * 0.5); + entity e = spawn(); + + setorigin(e, org); + + e.monster_loot = self.monster_loot; + + other = e; + MUTATOR_CALLHOOK(MonsterDropItem); + e = other; + + if(e) + { + e.think = monster_item_spawn; + e.nextthink = time + 0.3; + } +} + +void monsters_setframe(float _frame) +{ + if(self.frame == _frame) + return; + + self.anim_start_time = time; + self.frame = _frame; + self.SendFlags |= MSF_ANIM; +} + +float monster_isvalidtarget (entity targ, entity ent) +{ + if(!targ || !ent) + return FALSE; // someone doesn't exist + + if(targ == ent) + return FALSE; // don't attack ourselves + + traceline(ent.origin, targ.origin, MOVE_NORMAL, ent); + + if(trace_ent != targ) + return FALSE; + + if(targ.vehicle_flags & VHF_ISVEHICLE) + if not((get_monsterinfo(ent.monsterid)).spawnflags & MON_FLAG_RANGED) + return FALSE; // melee attacks are useless against vehicles + + if(time < game_starttime) + return FALSE; // monsters do nothing before the match has started + + if(vlen(targ.origin - ent.origin) >= ent.target_range) + return FALSE; // enemy is too far away + + if(targ.takedamage == DAMAGE_NO) + return FALSE; // enemy can't be damaged + + if(targ.items & IT_INVISIBILITY) + return FALSE; // enemy is invisible + + if(substring(targ.classname, 0, 10) == "onslaught_") + return FALSE; // don't attack onslaught targets + + if(IS_SPEC(targ) || IS_OBSERVER(targ)) + return FALSE; // enemy is a spectator + + if not(targ.vehicle_flags & VHF_ISVEHICLE) + if(targ.deadflag != DEAD_NO || ent.deadflag != DEAD_NO || targ.health <= 0 || ent.health <= 0) + return FALSE; // enemy/self is dead + + if(ent.monster_owner == targ) + return FALSE; // don't attack our master + + if(targ.monster_owner == ent) + return FALSE; // don't attack our pet + + if not(targ.vehicle_flags & VHF_ISVEHICLE) + if(targ.flags & FL_NOTARGET) + return FALSE; // enemy can't be targeted + + if not(autocvar_g_monsters_typefrag) + if(targ.BUTTON_CHAT) + return FALSE; // no typefragging! + - if not(IsDifferentTeam(targ, ent)) ++ if(SAME_TEAM(targ, ent)) + return FALSE; // enemy is on our team + + if(autocvar_g_monsters_target_infront || ent.spawnflags & MONSTERFLAG_INFRONT) + if(ent.enemy != targ) + { + float dot; + + makevectors (ent.angles); + dot = normalize (targ.origin - ent.origin) * v_forward; + + if(dot <= 0.3) + return FALSE; + } + + return TRUE; +} + +entity FindTarget (entity ent) +{ + if(MUTATOR_CALLHOOK(MonsterFindTarget)) { return ent.enemy; } // Handled by a mutator + + entity head, closest_target = world; + head = findradius(ent.origin, ent.target_range); + + while(head) // find the closest acceptable target to pass to + { + if(head.monster_attack) + if(monster_isvalidtarget(head, ent)) + { + // if it's a player, use the view origin as reference (stolen from RadiusDamage functions in g_damage.qc) + vector head_center = CENTER_OR_VIEWOFS(head); + vector ent_center = CENTER_OR_VIEWOFS(ent); + + //if(ctf_CheckPassDirection(head_center, ent_center, ent.v_angle, head.WarpZone_findradius_nearest)) + if(closest_target) + { + vector closest_target_center = CENTER_OR_VIEWOFS(closest_target); + if(vlen(ent_center - head_center) < vlen(ent_center - closest_target_center)) + { closest_target = head; } + } + else { closest_target = head; } + } + + head = head.chain; + } + + return closest_target; +} + +void MonsterTouch () +{ + if(other == world) + return; + + if(self.enemy != other) + if not(other.flags & FL_MONSTER) + if(monster_isvalidtarget(other, self)) + self.enemy = other; +} + +string get_monster_model_datafilename(string m, float sk, string fil) +{ + if(m) + m = strcat(m, "_"); + else + m = "models/monsters/*_"; + if(sk >= 0) + m = strcat(m, ftos(sk)); + else + m = strcat(m, "*"); + return strcat(m, ".", fil); +} + +void PrecacheMonsterSounds(string f) +{ + float fh; + string s; + fh = fopen(f, FILE_READ); + if(fh < 0) + return; + while((s = fgets(fh))) + { + if(tokenize_console(s) != 3) + { + dprint("Invalid sound info line: ", s, "\n"); + continue; + } + PrecacheGlobalSound(strcat(argv(1), " ", argv(2))); + } + fclose(fh); +} + +void precache_monstersounds() +{ + string m = (get_monsterinfo(self.monsterid)).model; + float globhandle, n, i; + string f; + + globhandle = search_begin(strcat(m, "_*.sounds"), TRUE, FALSE); + if (globhandle < 0) + return; + n = search_getsize(globhandle); + for (i = 0; i < n; ++i) + { + //print(search_getfilename(globhandle, i), "\n"); + f = search_getfilename(globhandle, i); + PrecacheMonsterSounds(f); + } + search_end(globhandle); +} + +void ClearMonsterSounds() +{ +#define _MSOUND(m) if(self.monstersound_##m) { strunzone(self.monstersound_##m); self.monstersound_##m = string_null; } + ALLMONSTERSOUNDS +#undef _MSOUND +} + +.string GetMonsterSoundSampleField(string type) +{ + GetMonsterSoundSampleField_notFound = 0; + switch(type) + { +#define _MSOUND(m) case #m: return monstersound_##m; + ALLMONSTERSOUNDS +#undef _MSOUND + } + GetMonsterSoundSampleField_notFound = 1; + return string_null; +} + +float LoadMonsterSounds(string f, float first) +{ + float fh; + string s; + var .string field; + fh = fopen(f, FILE_READ); + if(fh < 0) + { + dprint("Monster sound file not found: ", f, "\n"); + return 0; + } + while((s = fgets(fh))) + { + if(tokenize_console(s) != 3) + continue; + field = GetMonsterSoundSampleField(argv(0)); + if(GetMonsterSoundSampleField_notFound) + continue; + if(self.field) + strunzone(self.field); + self.field = strzone(strcat(argv(1), " ", argv(2))); + } + fclose(fh); + return 1; +} + +.float skin_for_monstersound; +void UpdateMonsterSounds() +{ + entity mon = get_monsterinfo(self.monsterid); + + if(self.skin == self.skin_for_monstersound) + return; + self.skin_for_monstersound = self.skin; + ClearMonsterSounds(); + //LoadMonsterSounds("sound/monsters/default.sounds", 1); + if(!autocvar_g_debug_defaultsounds) + if(!LoadMonsterSounds(get_monster_model_datafilename(mon.model, self.skin, "sounds"), 0)) + LoadMonsterSounds(get_monster_model_datafilename(mon.model, 0, "sounds"), 0); +} + +void MonsterSound(.string samplefield, float sound_delay, float delaytoo, float chan) +{ + if(delaytoo && time < self.msound_delay) + return; // too early + GlobalSound(self.samplefield, chan, VOICETYPE_PLAYERSOUND); + + self.msound_delay = time + sound_delay; +} + +void monster_makevectors(entity e) +{ + vector v; + + v = CENTER_OR_VIEWOFS(e); + self.v_angle = vectoangles(v - (self.origin + self.view_ofs)); + self.v_angle_x = -self.v_angle_x; + + makevectors(self.v_angle); +} + +float monster_melee(entity targ, float damg, float anim, float er, float anim_finished, float deathtype, float dostop) +{ + float rdmg = damg * random(); + + if (self.health <= 0) + return FALSE; // attacking while dead?! + + if(dostop) + { + self.velocity_x = 0; + self.velocity_y = 0; + self.state = MONSTER_STATE_ATTACK_MELEE; + self.SendFlags |= MSF_MOVE; + } + + monsters_setframe(anim); + + if(anim_finished != 0) + self.attack_finished_single = time + anim_finished; + + monster_makevectors(targ); + + traceline(self.origin + self.view_ofs, self.origin + v_forward * er, 0, self); + + if(trace_ent.takedamage) + Damage(trace_ent, self, self, rdmg * monster_skill, deathtype, trace_ent.origin, normalize(trace_ent.origin - self.origin)); + + return TRUE; +} + +void Monster_CheckMinibossFlag () +{ + if(MUTATOR_CALLHOOK(MonsterCheckBossFlag)) + return; + + float chance = random() * 100; + + // g_monsters_miniboss_chance cvar or spawnflags 64 causes a monster to be a miniboss + if ((self.spawnflags & MONSTERFLAG_MINIBOSS) || (chance < autocvar_g_monsters_miniboss_chance)) + { + self.health += autocvar_g_monsters_miniboss_healthboost; + if not(self.weapon) + self.weapon = WEP_NEX; + } +} + +float Monster_CanRespawn(entity ent) +{ + other = ent; + if(MUTATOR_CALLHOOK(MonsterRespawn)) + return TRUE; // enabled by a mutator + + if(ent.spawnflags & MONSTERFLAG_NORESPAWN) + return FALSE; + + if not(autocvar_g_monsters_respawn) + return FALSE; + + return TRUE; +} + +void Monster_Fade () +{ + if(Monster_CanRespawn(self)) + { + self.monster_respawned = TRUE; + self.think = self.monster_spawnfunc; + self.nextthink = time + self.respawntime; + self.deadflag = DEAD_RESPAWNING; + if(self.spawnflags & MONSTER_RESPAWN_DEATHPOINT) + { + self.pos1 = self.origin; + self.pos2 = self.angles; + } + self.event_damage = func_null; + self.takedamage = DAMAGE_NO; + setorigin(self, self.pos1); + self.angles = self.pos2; + self.health = self.max_health; + + self.SendFlags |= MSF_MOVE; + self.SendFlags |= MSF_STATUS; + } + else + SUB_SetFade(self, time + 3, 1); +} + +float Monster_CanJump (vector vel) +{ + if(self.state) + return FALSE; // already attacking + if not(self.flags & FL_ONGROUND) + return FALSE; // not on the ground + if(self.health <= 0) + return FALSE; // called when dead? + if(time < self.attack_finished_single) + return FALSE; // still attacking + + vector old = self.velocity; + + self.velocity = vel; + tracetoss(self, self); + self.velocity = old; + if (trace_ent != self.enemy) + return FALSE; + + return TRUE; +} + +float monster_leap (float anm, void() touchfunc, vector vel, float anim_finished) +{ + if(!Monster_CanJump(vel)) + return FALSE; + + monsters_setframe(anm); + self.state = MONSTER_STATE_ATTACK_LEAP; + self.touch = touchfunc; + self.origin_z += 1; + self.velocity = vel; + self.flags &= ~FL_ONGROUND; + + self.attack_finished_single = time + anim_finished; + + return TRUE; +} + +void monster_checkattack(entity e, entity targ) +{ + if(e == world) + return; + if(targ == world) + return; + + if not(e.monster_attackfunc) + return; + + if(time < e.attack_finished_single) + return; + + if(vlen(targ.origin - e.origin) <= e.attack_range) + if(e.monster_attackfunc(MONSTER_ATTACK_MELEE)) + { + MonsterSound(monstersound_melee, 0, FALSE, CH_VOICE); + return; + } + + if(vlen(targ.origin - e.origin) > e.attack_range) + if(e.monster_attackfunc(MONSTER_ATTACK_RANGED)) + { + MonsterSound(monstersound_ranged, 0, FALSE, CH_VOICE); + return; + } +} + +void monster_use () +{ + if not(self.enemy) + if(self.health > 0) + if(monster_isvalidtarget(activator, self)) + self.enemy = activator; +} + +.float last_trace; +.float last_enemycheck; // for checking enemy +vector monster_pickmovetarget(entity targ) +{ + // enemy is always preferred target + if(self.enemy) + { + makevectors(self.angles); + self.monster_movestate = MONSTER_MOVE_ENEMY; + self.last_trace = time + 1.2; + return self.enemy.origin; + } + + switch(self.monster_moveflags) + { + case MONSTER_MOVE_OWNER: + { + self.monster_movestate = MONSTER_MOVE_OWNER; + self.last_trace = time + 0.3; + return (self.monster_owner) ? self.monster_owner.origin : self.origin; + } + case MONSTER_MOVE_SPAWNLOC: + { + self.monster_movestate = MONSTER_MOVE_SPAWNLOC; + self.last_trace = time + 2; + return self.pos1; + } + case MONSTER_MOVE_NOMOVE: + { + self.monster_movestate = MONSTER_MOVE_NOMOVE; + self.last_trace = time + 2; + return self.origin; + } + default: + case MONSTER_MOVE_WANDER: + { + vector pos; + self.monster_movestate = MONSTER_MOVE_WANDER; + self.last_trace = time + 2; + + self.angles_y = rint(random() * 500); + makevectors(self.angles); + pos = self.origin + v_forward * 600; + + if(self.flags & FL_FLY || self.flags & FL_SWIM) + if(self.spawnflags & MONSTERFLAG_FLY_VERTICAL) + { + pos_z = random() * 200; + if(random() >= 0.5) + pos_z *= -1; + } + + if(targ) + { + self.last_trace = time + 0.5; + pos = targ.origin; + } + + return pos; + } + } +} + +void monster_move(float runspeed, float walkspeed, float stopspeed, float manim_run, float manim_walk, float manim_idle) +{ + fixedmakevectors(self.angles); + + if(self.target2) + self.goalentity = find(world, targetname, self.target2); + + entity targ; + + if(self.frozen) + { + self.revive_progress = bound(0, self.revive_progress + frametime * self.revive_speed, 1); + self.health = max(1, self.max_health * self.revive_progress); + + self.SendFlags |= MSF_STATUS; + + movelib_beak_simple(stopspeed); + + self.velocity = '0 0 0'; + self.enemy = world; + self.nextthink = time + 0.1; + + if(self.revive_progress >= 1) + Unfreeze(self); // wait for next think before attacking + + // don't bother updating angles here? + if(self.origin != self.oldorigin) + { + self.oldorigin = self.origin; + self.SendFlags |= MSF_MOVE; + } + + return; // no moving while frozen + } + + if(self.flags & FL_SWIM) + { + if(self.waterlevel < WATERLEVEL_WETFEET) + { + if(time >= self.last_trace) + { + self.fish_wasdrowning = TRUE; + self.last_trace = time + 0.4; + + Damage (self, world, world, 2, DEATH_DROWN, self.origin, '0 0 0'); + self.angles = '90 90 0'; + if(random() < 0.5) + { + self.velocity_y += random() * 50; + self.velocity_x -= random() * 50; + } + else + { + self.velocity_y -= random() * 50; + self.velocity_x += random() * 50; + } + self.velocity_z += random() * 150; + } + + + self.movetype = MOVETYPE_BOUNCE; + //self.velocity_z = -200; + + self.SendFlags |= MSF_MOVE | MSF_ANG; + + return; + } + else if(self.fish_wasdrowning) + { + self.fish_wasdrowning = FALSE; + self.angles_x = 0; + self.movetype = MOVETYPE_WALK; + } + } + + targ = self.goalentity; + + monster_target = targ; + monster_speed_run = runspeed; + monster_speed_walk = walkspeed; + + if(MUTATOR_CALLHOOK(MonsterMove) || gameover || (round_handler_IsActive() && !round_handler_IsRoundStarted()) || time < game_starttime || (autocvar_g_campaign && !campaign_bots_may_start) || time < self.spawn_time) + { + runspeed = walkspeed = 0; + if(time >= self.spawn_time) + monsters_setframe(manim_idle); + movelib_beak_simple(stopspeed); + if(self.oldorigin != self.origin) + { + self.oldorigin = self.origin; + self.SendFlags |= MSF_MOVE; + } + return; + } + + targ = monster_target; + runspeed = monster_speed_run; + walkspeed = monster_speed_walk; + + if(teamplay) + if(autocvar_g_monsters_teams) - if(IsDifferentTeam(self.monster_owner, self)) ++ if(DIFF_TEAM(self.monster_owner, self)) + self.monster_owner = world; + + if(self.enemy && self.enemy.health < 1) + self.enemy = world; // enough! + + if(time >= self.last_enemycheck) + { + if not(monster_isvalidtarget(self.enemy, self)) + self.enemy = world; + + if not(self.enemy) + { + self.enemy = FindTarget(self); + if(self.enemy) + MonsterSound(monstersound_sight, 0, FALSE, CH_VOICE); + } + + self.last_enemycheck = time + 0.5; + } + + if(self.state == MONSTER_STATE_ATTACK_MELEE && time >= self.attack_finished_single) + self.state = 0; + + if(self.state != MONSTER_STATE_ATTACK_MELEE) // don't move if set + if(time >= self.last_trace || self.enemy) // update enemy instantly + self.moveto = monster_pickmovetarget(targ); + + if not(self.enemy) + MonsterSound(monstersound_idle, 5, TRUE, CH_VOICE); + + if(self.state != MONSTER_STATE_ATTACK_LEAP && self.state != MONSTER_STATE_ATTACK_MELEE) + self.steerto = steerlib_attract2(self.moveto, 0.5, 500, 0.95); + + if(self.state == MONSTER_STATE_ATTACK_LEAP && (self.flags & FL_ONGROUND)) + { + self.state = 0; + self.touch = MonsterTouch; + } + + //self.steerto = steerlib_attract2(self.moveto, 0.5, 500, 0.95); + + float turny = 0; + vector real_angle = vectoangles(self.steerto) - self.angles; + + if(self.state != MONSTER_STATE_ATTACK_LEAP && self.state != MONSTER_STATE_ATTACK_MELEE) + turny = 20; + + if(self.flags & FL_SWIM) + turny = vlen(self.angles - self.moveto); + + if(turny) + { + turny = bound(turny * -1, shortangle_f(real_angle_y, self.angles_y), turny); + self.angles_y += turny; + } + + if(self.state == MONSTER_STATE_ATTACK_MELEE) + self.moveto = self.origin; + + if(self.enemy && self.enemy.vehicle) + runspeed = 0; + + if(((self.flags & FL_FLY) || (self.flags & FL_SWIM)) && self.spawnflags & MONSTERFLAG_FLY_VERTICAL) + v_forward = normalize(self.moveto - self.origin); + else + self.moveto_z = self.origin_z; + + if(vlen(self.origin - self.moveto) > 64) + { + if(self.flags & FL_FLY || self.flags & FL_SWIM) + movelib_move_simple(v_forward, ((self.enemy) ? runspeed : walkspeed), 0.6); + else + movelib_move_simple_gravity(v_forward, ((self.enemy) ? runspeed : walkspeed), 0.6); + + if(time > self.pain_finished) + if(time > self.attack_finished_single) + if(vlen(self.velocity) > 10) + monsters_setframe((self.enemy) ? manim_run : manim_walk); + else + monsters_setframe(manim_idle); + } + else + { + entity e = find(world, targetname, self.target2); + if(e.target2) + self.target2 = e.target2; + else if(e.target) + self.target2 = e.target; + + movelib_beak_simple(stopspeed); + if(time > self.attack_finished_single) + if(time > self.pain_finished) + if (vlen(self.velocity) <= 30) + monsters_setframe(manim_idle); + } + + monster_checkattack(self, self.enemy); + + if(self.angles != self.oldangles) + { + self.oldangles = self.angles; + self.SendFlags |= MSF_ANG; + } + + if(self.origin != self.oldorigin) + { + self.oldorigin = self.origin; + self.SendFlags |= MSF_MOVE; + } +} + +void monster_dead_think() +{ + self.think = monster_dead_think; + self.nextthink = time + self.ticrate; + + self.deadflag = DEAD_DEAD; + + if(self.ltime != 0) + if(time >= self.ltime) + { + Monster_Fade(); + return; + } + + if(self.oldorigin != self.origin) + { + self.oldorigin = self.origin; + self.SendFlags |= MSF_MOVE; + } +} + +void monsters_setstatus() +{ + self.stat_monsters_total = monsters_total; + self.stat_monsters_killed = monsters_killed; +} + +void Monster_Appear() +{ + self.enemy = activator; + self.spawnflags &= ~MONSTERFLAG_APPEAR; + self.monster_spawnfunc(); +} + +float Monster_CheckAppearFlags(entity ent) +{ + if not(ent.spawnflags & MONSTERFLAG_APPEAR) + return FALSE; + + ent.think = func_null; + ent.nextthink = 0; + ent.use = Monster_Appear; + ent.flags = FL_MONSTER; // set so this monster can get butchered + + return TRUE; +} + +void monsters_reset() +{ + setorigin(self, self.pos1); + self.angles = self.pos2; + + self.health = self.max_health; + self.velocity = '0 0 0'; + self.enemy = world; + self.goalentity = world; + self.attack_finished_single = 0; + self.moveto = self.origin; + + self.SendFlags |= MSF_STATUS; +} + +float monster_send(entity to, float sf) +{ + WriteByte(MSG_ENTITY, ENT_CLIENT_MONSTER); + WriteByte(MSG_ENTITY, sf); + if(sf & MSF_SETUP) + { + WriteByte(MSG_ENTITY, self.monsterid); + + WriteCoord(MSG_ENTITY, self.origin_x); + WriteCoord(MSG_ENTITY, self.origin_y); + WriteCoord(MSG_ENTITY, self.origin_z); + + WriteAngle(MSG_ENTITY, self.angles_x); + WriteAngle(MSG_ENTITY, self.angles_y); + + WriteByte(MSG_ENTITY, self.skin); + WriteByte(MSG_ENTITY, self.team); + } + + if(sf & MSF_ANG) + { + WriteShort(MSG_ENTITY, rint(self.angles_x)); + WriteShort(MSG_ENTITY, rint(self.angles_y)); + } + + if(sf & MSF_MOVE) + { + WriteShort(MSG_ENTITY, rint(self.origin_x)); + WriteShort(MSG_ENTITY, rint(self.origin_y)); + WriteShort(MSG_ENTITY, rint(self.origin_z)); + + WriteShort(MSG_ENTITY, rint(self.velocity_x)); + WriteShort(MSG_ENTITY, rint(self.velocity_y)); + WriteShort(MSG_ENTITY, rint(self.velocity_z)); + + WriteShort(MSG_ENTITY, rint(self.angles_y)); + } + + if(sf & MSF_ANIM) + { + WriteCoord(MSG_ENTITY, self.anim_start_time); + WriteByte(MSG_ENTITY, self.frame); + } + + if(sf & MSF_STATUS) + { + WriteByte(MSG_ENTITY, self.skin); + + WriteByte(MSG_ENTITY, self.team); + + WriteByte(MSG_ENTITY, self.deadflag); + + if(self.health <= 0) + WriteByte(MSG_ENTITY, 0); + else + WriteByte(MSG_ENTITY, ceil((self.health / self.max_health) * 255)); + } + + return TRUE; +} + +void monster_link(void() spawnproc) +{ + Net_LinkEntity(self, TRUE, 0, monster_send); + self.think = spawnproc; + self.nextthink = time; +} + +void monsters_corpse_damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force) +{ + self.health -= damage; + + Violence_GibSplash_At(hitloc, force, 2, bound(0, damage, 200) / 16, self, attacker); + + if(self.health <= -100) // 100 health until gone? + { + Violence_GibSplash_At(hitloc, force, 2, bound(0, damage, 200) / 16, self, attacker); + + self.think = SUB_Remove; + self.nextthink = time + 0.1; + } +} + +void monster_die() +{ + self.think = monster_dead_think; + self.nextthink = self.ticrate; + self.ltime = time + 5; + + monster_dropitem(); + + MonsterSound(monstersound_death, 0, FALSE, CH_VOICE); + + if(!(self.spawnflags & MONSTERFLAG_SPAWNED) && !self.monster_respawned) + monsters_killed += 1; + + if(self.candrop && self.weapon) + W_ThrowNewWeapon(self, self.weapon, 0, self.origin, randomvec() * 150 + '0 0 325'); + + if(IS_CLIENT(self.realowner)) + if not(self.monster_respawned) + self.realowner.monstercount -= 1; + + self.event_damage = monsters_corpse_damage; + self.solid = SOLID_CORPSE; + self.takedamage = DAMAGE_AIM; + self.enemy = world; + self.movetype = MOVETYPE_TOSS; + self.moveto = self.origin; + self.touch = MonsterTouch; // reset incase monster was pouncing + self.reset = func_null; + self.state = 0; + self.attack_finished_single = 0; + + if not(self.flags & FL_FLY) + self.velocity = '0 0 0'; + + self.SendFlags |= MSF_MOVE; + + // number of monsters spawned with mobspawn command + totalspawned -= 1; + + MON_ACTION(self.monsterid, MR_DEATH); +} + +void monsters_damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force) +{ + if(self.frozen && deathtype != DEATH_KILL) + return; + + if(time < self.pain_finished && deathtype != DEATH_KILL) + return; + + if(time < self.spawnshieldtime) + return; + + vector v; + float take, save; + + v = healtharmor_applydamage(self.armorvalue, self.m_armor_blockpercent, damage); + take = v_x; + save = v_y; + + self.health -= take; + + self.dmg_time = time; + + if(sound_allowed(MSG_BROADCAST, attacker) && deathtype != DEATH_DROWN) + spamsound (self, CH_PAIN, "misc/bodyimpact1.wav", VOL_BASE, ATTEN_NORM); // FIXME: PLACEHOLDER + + self.velocity += force * self.damageforcescale; + + if(deathtype != DEATH_DROWN) + { + Violence_GibSplash_At(hitloc, force, 2, bound(0, take, 200) / 16, self, attacker); + if (take > 50) + Violence_GibSplash_At(hitloc, force * -0.1, 3, 1, self, attacker); + if (take > 100) + Violence_GibSplash_At(hitloc, force * -0.2, 3, 1, self, attacker); + } + + if(self.health <= 0) + { + if(deathtype == DEATH_KILL) + self.candrop = FALSE; // killed by mobkill command + + // TODO: fix this? + activator = attacker; + other = self.enemy; + SUB_UseTargets(); + self.target2 = self.oldtarget2; // reset to original target on death, incase we respawn + + monster_die(); + + frag_attacker = attacker; + frag_target = self; + MUTATOR_CALLHOOK(MonsterDies); + + if(self.health <= -100) // check if we're already gibbed + { + Violence_GibSplash(self, 1, 0.5, attacker); + + self.think = SUB_Remove; + self.nextthink = time + 0.1; + } + } + + self.SendFlags |= MSF_STATUS; +} + +void monster_think() +{ + self.think = monster_think; + self.nextthink = self.ticrate; + + MON_ACTION(self.monsterid, MR_THINK); +} + +void monster_spawn() +{ + MON_ACTION(self.monsterid, MR_SETUP); + + if not(self.monster_respawned) + Monster_CheckMinibossFlag(); + + self.max_health = self.health; + self.pain_finished = self.nextthink; + self.anim_start_time = time; + + if not(self.noalign) + { + setorigin(self, self.origin + '0 0 20'); + tracebox(self.origin + '0 0 100', self.mins, self.maxs, self.origin - '0 0 10000', MOVE_WORLDONLY, self); + setorigin(self, trace_endpos); + } + + if not(self.monster_respawned) + if not(self.skin) + self.skin = rint(random() * 4); + + if not(self.attack_range) + self.attack_range = autocvar_g_monsters_attack_range; + + self.pos1 = self.origin; + + //monster_setupsounds(self.netname); + precache_monstersounds(); + UpdateMonsterSounds(); + //monster_precachesounds(self); + + if(teamplay) + self.monster_attack = TRUE; // we can have monster enemies in team games + + MonsterSound(monstersound_spawn, 0, FALSE, CH_VOICE); + + self.think = monster_think; + self.nextthink = time + self.ticrate; + + self.SendFlags |= MSF_SETUP; + + MUTATOR_CALLHOOK(MonsterSpawn); +} + +float monster_initialize(float mon_id, float nodrop) +{ + if not(autocvar_g_monsters) + return FALSE; + + entity mon = get_monsterinfo(mon_id); + + // support for quake style removing monsters based on skill + switch(monster_skill) + { + case 0: + case 1: if(self.spawnflags & MONSTERSKILL_NOTEASY) return FALSE; break; + case 2: if(self.spawnflags & MONSTERSKILL_NOTMEDIUM) return FALSE; break; + default: + case 3: if(self.spawnflags & MONSTERSKILL_NOTHARD) return FALSE; break; + } + + if(self.team && !teamplay) + self.team = 0; + + if not(self.spawnflags & MONSTERFLAG_SPAWNED) // naturally spawned monster + if not(self.monster_respawned) + monsters_total += 1; + + setsize(self, mon.mins, mon.maxs); + self.flags = FL_MONSTER; + self.takedamage = DAMAGE_AIM; + self.bot_attack = TRUE; + self.iscreature = TRUE; + self.teleportable = TRUE; + self.damagedbycontents = TRUE; + self.monsterid = mon_id; + self.damageforcescale = 0; + self.event_damage = monsters_damage; + self.touch = MonsterTouch; + self.use = monster_use; + self.solid = SOLID_BBOX; + self.movetype = MOVETYPE_WALK; + self.spawnshieldtime = time + autocvar_g_monsters_spawnshieldtime; + self.enemy = world; + self.velocity = '0 0 0'; + self.moveto = self.origin; + self.pos2 = self.angles; + self.reset = monsters_reset; + self.netname = mon.netname; + self.monster_name = M_NAME(mon_id); + self.candrop = TRUE; + self.view_ofs = '0 0 1' * (self.maxs_z * 0.5); + self.oldtarget2 = self.target2; + self.deadflag = DEAD_NO; + self.scale = 1; + self.noalign = nodrop; + self.spawn_time = time; + self.gravity = 1; + self.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_BOTCLIP | DPCONTENTS_MONSTERCLIP; + + if(mon.spawnflags & MONSTER_TYPE_SWIM) + self.flags |= FL_SWIM; + + if(mon.spawnflags & MONSTER_TYPE_FLY) + { + self.flags |= FL_FLY; + self.movetype = MOVETYPE_FLY; + } + + if(mon.spawnflags & MONSTER_SIZE_BROKEN) + self.scale = 1.3; + + if not(self.ticrate) + self.ticrate = autocvar_g_monsters_think_delay; + + self.ticrate = bound(sys_frametime, self.ticrate, 60); + + if not(self.m_armor_blockpercent) + self.m_armor_blockpercent = 0.5; + + if not(self.target_range) + self.target_range = autocvar_g_monsters_target_range; + + if not(self.respawntime) + self.respawntime = autocvar_g_monsters_respawn_delay; + + if not(self.monster_moveflags) + self.monster_moveflags = MONSTER_MOVE_WANDER; + + monster_link(monster_spawn); + + return TRUE; +} diff --cc qcsrc/common/notifications.qh index e5f04994b,95341c1fa..1809eadcf --- a/qcsrc/common/notifications.qh +++ b/qcsrc/common/notifications.qh @@@ -245,208 -327,183 +327,208 @@@ void Send_Notification_WOCOVA MSG_INFO_NOTIF(default, prefix##PINK, strnum, flnum, args, hudargs, sprintf(icon, strtolower(STATIC_NAME_TEAM_4)), TCR(normal, COL_TEAM_4, strtoupper(NAME_TEAM_4)), TCR(gentle, COL_TEAM_4, strtoupper(NAME_TEAM_4))) \ #endif #define MSG_INFO_NOTIFICATIONS \ - MULTITEAM_INFO(1, INFO_CTF_CAPTURE_, 2, 1, 0, "s1", "s1", "notify_%s_captured", _("^BG%s^BG captured the ^TC^TT^BG flag\n"), "") \ - MULTITEAM_INFO(1, INFO_CTF_CAPTURE_BROKEN_, 2, 2, 2, "s1 f1p2dec s2 f2p2dec", "s1", "notify_%s_captured", _("^BG%s^BG captured the ^TC^TT^BG flag in ^F1%s^BG seconds, breaking ^BG%s^BG's previous record of ^F2%s^BG seconds\n"), "") \ - MULTITEAM_INFO(1, INFO_CTF_CAPTURE_TIME_, 2, 1, 1, "s1 f1p2dec", "s1", "notify_%s_captured", _("^BG%s^BG captured the ^TC^TT^BG flag in ^F1%s^BG seconds\n"), "") \ - MULTITEAM_INFO(1, INFO_CTF_CAPTURE_UNBROKEN_, 2, 2, 2, "s1 f1p2dec s2 f2p2dec", "s1", "notify_%s_captured", _("^BG%s^BG captured the ^TC^TT^BG flag in ^F2%s^BG seconds, failing to break ^BG%s^BG's previous record of ^F1%s^BG seconds\n"), "") \ - MULTITEAM_INFO(1, INFO_CTF_FLAGRETURN_ABORTRUN_, 2, 0, 0, "", "", "", _("^BGThe ^TC^TT^BG flag was returned to base by its owner\n"), "") \ - MULTITEAM_INFO(1, INFO_CTF_FLAGRETURN_DAMAGED_, 2, 0, 0, "", "", "", _("^BGThe ^TC^TT^BG flag was destroyed and returned to base\n"), "") \ - MULTITEAM_INFO(1, INFO_CTF_FLAGRETURN_DROPPED_, 2, 0, 0, "", "", "", _("^BGThe ^TC^TT^BG flag was dropped in the base and returned itself\n"), "") \ - MULTITEAM_INFO(1, INFO_CTF_FLAGRETURN_NEEDKILL_, 2, 0, 0, "", "", "", _("^BGThe ^TC^TT^BG flag fell somewhere it couldn't be reached and returned to base\n"), "") \ - MULTITEAM_INFO(1, INFO_CTF_FLAGRETURN_SPEEDRUN_, 2, 0, 1, "f1p2dec", "", "", _("^BGThe ^TC^TT^BG flag became impatient after ^F1%.2f^BG seconds and returned itself\n"), "") \ - MULTITEAM_INFO(1, INFO_CTF_FLAGRETURN_TIMEOUT_, 2, 0, 0, "", "", "", _("^BGThe ^TC^TT^BG flag has returned to the base\n"), "") \ - MULTITEAM_INFO(1, INFO_CTF_LOST_, 2, 1, 0, "s1", "s1", "notify_%s_lost", _("^BG%s^BG lost the ^TC^TT^BG flag\n"), "") \ - MULTITEAM_INFO(1, INFO_CTF_PICKUP_, 2, 1, 0, "s1", "s1", "notify_%s_taken", _("^BG%s^BG got the ^TC^TT^BG flag\n"), "") \ - MULTITEAM_INFO(1, INFO_CTF_RETURN_, 2, 1, 0, "s1", "s1", "notify_%s_returned", _("^BG%s^BG returned the ^TC^TT^BG flag\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_CHEAT, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_death", _("^BG%s%s^K1 was unfairly eliminated by ^BG%s^K1%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_DROWN, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_water", _("^BG%s%s^K1 was drowned by ^BG%s^K1%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_FALL, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_fall", _("^BG%s%s^K1 was grounded by ^BG%s^K1%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_FIRE, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_death", _("^BG%s%s^K1 was burnt up into a crisp by ^BG%s^K1%s%s\n"), _("^BG%s%s^K1 felt a little hot from ^BG%s^K1's fire^K1%s%s\n")) \ - MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_LAVA, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_lava", _("^BG%s%s^K1 was cooked by ^BG%s^K1%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_MONSTER, 3, 2, "spree_inf s1 s2 s3loc spree_end", "", "", _("^BG%s%s^K1 was pushed infront of a monster by ^BG%s^K1%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_NADE, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_death", _("^BG%s%s^K1 was blown up by ^BG%s^K1's Nade%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_SHOOTING_STAR, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_shootingstar", _("^BG%s%s^K1 was shot into space by ^BG%s^K1%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_SLIME, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_slime", _("^BG%s%s^K1 was slimed by ^BG%s^K1%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_SWAMP, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_slime", _("^BG%s%s^K1 was preserved by ^BG%s^K1%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_TELEFRAG, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_telefrag", _("^BG%s%s^K1 was telefragged by ^BG%s^K1%s%s\n"), _("^BG%s%s^K1 tried to occupy ^BG%s^K1's teleport destination space%s%s\n")) \ - MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_TOUCHEXPLODE, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_death", _("^BG%s%s^K1 died in an accident with ^BG%s^K1%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_VH_BUMB_DEATH, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_death", _("^BG%s%s^K1 got caught in the blast when ^BG%s^K1's Bumblebee exploded%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_VH_BUMB_GUN, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_death", _("^BG%s%s^K1 saw the pretty lights of ^BG%s^K1's Bumblebee gun%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_VH_CRUSH, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_death", _("^BG%s%s^K1 was crushed by ^BG%s^K1%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_VH_RAPT_BOMB, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_death", _("^BG%s%s^K1 was cluster bombed by ^BG%s^K1's Raptor%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_VH_RAPT_CANNON, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_death", _("^BG%s%s^K1 couldn't resist ^BG%s^K1's purple blobs%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_VH_RAPT_DEATH, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_death", _("^BG%s%s^K1 got caught in the blast when ^BG%s^K1's Raptor exploded%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_VH_SPID_DEATH, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_death", _("^BG%s%s^K1 got caught in the blast when ^BG%s^K1's Spiderbot exploded%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_VH_SPID_MINIGUN, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_death", _("^BG%s%s^K1 got shredded by ^BG%s^K1's Spiderbot%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_VH_SPID_ROCKET, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_death", _("^BG%s%s^K1 was blasted to bits by ^BG%s^K1's Spiderbot%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_VH_WAKI_DEATH, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_death", _("^BG%s%s^K1 got caught in the blast when ^BG%s^K1's Racer exploded%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_VH_WAKI_GUN, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_death", _("^BG%s%s^K1 was bolted down by ^BG%s^K1's Racer%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_VH_WAKI_ROCKET, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_death", _("^BG%s%s^K1 couldn't find shelter from ^BG%s^K1's Racer%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_VOID, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_void", _("^BG%s%s^K1 was thrown into a world of hurt by ^BG%s^K1%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_SELF_AUTOTEAMCHANGE, 2, 1, "s1 s2loc death_team", "", "", _("^BG%s^K1 was moved into the %s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_SELF_BETRAYAL, 2, 1, "s1 s2loc spree_lost", "s1", "notify_teamkill_red", _("^BG%s^K1 became enemies with the Lord of Teamplay%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_SELF_CAMP, 2, 1, "s1 s2loc spree_lost", "s1", "notify_camping", _("^BG%s^K1 thought they found a nice camping ground%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_SELF_CHEAT, 2, 1, "s1 s2loc spree_lost", "s1", "notify_selfkill", _("^BG%s^K1 unfairly eliminated themself%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_SELF_CUSTOM, 3, 1, "s1 s2 s3loc spree_lost", "s1", "notify_void", _("^BG%s^K1 %s^K1%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_SELF_DROWN, 2, 1, "s1 s2loc spree_lost", "s1", "notify_water", _("^BG%s^K1 couldn't catch their breath%s%s\n"), _("^BG%s^K1 was in the water for too long%s%s\n")) \ - MSG_INFO_NOTIF(1, INFO_DEATH_SELF_FALL, 2, 1, "s1 s2loc spree_lost", "s1", "notify_fall", _("^BG%s^K1 hit the ground with a crunch%s%s\n"), _("^BG%s^K1 hit the ground with a bit too much force%s%s\n")) \ - MSG_INFO_NOTIF(1, INFO_DEATH_SELF_FIRE, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 became a bit too crispy%s%s\n"), _("^BG%s^K1 felt a little hot%s%s\n")) \ - MSG_INFO_NOTIF(1, INFO_DEATH_SELF_GENERIC, 2, 1, "s1 s2loc spree_lost", "s1", "notify_selfkill", _("^BG%s^K1 died%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_SELF_LAVA, 2, 1, "s1 s2loc spree_lost", "s1", "notify_lava", _("^BG%s^K1 turned into hot slag%s%s\n"), _("^BG%s^K1 found a hot place%s%s\n")) \ - MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_CERBERUS_BITE, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was mauled by a Cerberus%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_CERBERUS_JUMP, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 didn't see the pouncing Cerberus%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_ANIMUS, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was eviscerated by an Animus%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_STINGRAY, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was fatally wounded by a Stingray%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_KNIGHT_CRUSH, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was crushed by a pouncing Knight%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_KNIGHT_FBALL, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was turned to ash by a Knight%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_KNIGHT_INFERNO, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was burned to death by a Knight%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_KNIGHT_MELEE, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was slain by a Knight%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_KNIGHT_SPIKE, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was cursed by a Knight%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_BRUISER, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was beaten in a fistfight by a Bruiser%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_BRUTE_BLADE, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was cut down by a Brute%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_BRUTE_GRENADE, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 almost dodged a Brute's grenade%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_BRUTE_UZI, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was nailed by a Brute%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_MAGE, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was exploded by a Mage%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_SHAMBLER_CLAW, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1's innards became outwards by a Shambler%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_SHAMBLER_SMASH, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was smashed by a Shambler%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_SHAMBLER_ZAP, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was zapped to death by a Shambler%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_SPIDER, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was bitten by a Spider%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_SPIDER_FIRE, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was incinerated by a Spider%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_SLIME, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was blown up by a Slime%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_WYVERN, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was fireballed by a Wyvern%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_ZOMBIE_JUMP, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 joins the Zombies%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_ZOMBIE_MELEE, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was given kung fu lessons by a Zombie%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_SELF_NADE, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 mastered the art of self-nading%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_SELF_NOAMMO, 2, 1, "s1 s2loc spree_lost", "s1", "notify_outofammo", _("^BG%s^K1 died%s%s. What's the point of living without ammo?\n"), _("^BG%s^K1 ran out of ammo%s%s\n")) \ - MSG_INFO_NOTIF(1, INFO_DEATH_SELF_ROT, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 rotted away%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_SELF_SHOOTING_STAR, 2, 1, "s1 s2loc spree_lost", "s1", "notify_shootingstar", _("^BG%s^K1 became a shooting star%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_SELF_SLIME, 2, 1, "s1 s2loc spree_lost", "s1", "notify_slime", _("^BG%s^K1 was slimed%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_SELF_SUICIDE, 2, 1, "s1 s2loc spree_lost", "s1", "notify_selfkill", _("^BG%s^K1 couldn't take it anymore%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_SELF_SWAMP, 2, 1, "s1 s2loc spree_lost", "s1", "notify_slime", _("^BG%s^K1 is now preserved for centuries to come%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_SELF_TEAMCHANGE, 2, 1, "s1 s2loc death_team", "", "", _("^BG%s^K1 switched to the %s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_SELF_TOUCHEXPLODE, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 died in an accident%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_SELF_TURRET, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 ran into a turret%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_SELF_TURRET_EWHEEL, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was blasted away by an eWheel turret%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_SELF_TURRET_FLAC, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 got caught up in the FLAC turret fire%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_SELF_TURRET_HELLION, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was blasted away by a Hellion turret%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_SELF_TURRET_HK, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 could not hide from the Hunter turret%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_SELF_TURRET_MACHINEGUN, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was riddled full of holes by a Machinegun turret%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_SELF_TURRET_MLRS, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 got turned into smoldering gibs by an MLRS turret%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_SELF_TURRET_PHASER, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was phased out by a turret%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_SELF_TURRET_PLASMA, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 got served some superheated plasma from a turret%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_SELF_TURRET_TESLA, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was electrocuted by a Tesla turret%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_SELF_TURRET_WALK_GUN, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 got served a lead enrichment by a Walker turret%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_SELF_TURRET_WALK_MEELE, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was impaled by a Walker turret%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_SELF_TURRET_WALK_ROCKET, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was blasted away by a Walker turret%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_SELF_VH_BUMB_DEATH, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 got caught in the blast of a Bumblebee explosion%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_SELF_VH_CRUSH, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was crushed by a vehicle%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_SELF_VH_RAPT_BOMB, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was caught in a Raptor cluster bomb%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_SELF_VH_RAPT_DEATH, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 got caught in the blast of a Raptor explosion%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_SELF_VH_SPID_DEATH, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 got caught in the blast of a Spiderbot explosion%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_SELF_VH_SPID_ROCKET, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was blasted to bits by a Spiderbot rocket%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_SELF_VH_WAKI_DEATH, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 got caught in the blast of a Racer explosion%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_SELF_VH_WAKI_ROCKET, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 couldn't find shelter from a Racer rocket%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_DEATH_SELF_VOID, 2, 1, "s1 s2loc spree_lost", "s1", "notify_void", _("^BG%s^K1 was in the wrong place%s%s\n"), "") \ - MULTITEAM_INFO(1, INFO_DEATH_TEAMKILL_, 4, 3, 1, "s1 s2 s3loc spree_end", "s2 s1", "notify_teamkill_%s", _("^BG%s^K1 was betrayed by ^BG%s^K1%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_FREEZETAG_FREEZE, 2, 0, "s1 s2", "", "", _("^BG%s^K1 was frozen by ^BG%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_FREEZETAG_REVIVED, 2, 0, "s1 s2", "", "", _("^BG%s^K3 was revived by ^BG%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_FREEZETAG_REVIVED_FALL, 1, 0, "s1", "", "", _("^BG%s^K3 was revived by falling\n"), "") \ - MSG_INFO_NOTIF(1, INFO_FREEZETAG_AUTO_REVIVED, 1, 1, "s1 f1", "", "", _("^BG%s^K3 was automatically revived after %s second(s)\n"), "") \ - MULTITEAM_INFO(1, INFO_ROUND_TEAM_WIN_, 4, 0, 0, "", "", "", _("^TC^TT^BG team wins the round\n"), "") \ - MSG_INFO_NOTIF(1, INFO_ROUND_PLAYER_WIN, 1, 0, "s1", "", "", _("^BG%s^BG wins the round\n"), "") \ - MSG_INFO_NOTIF(1, INFO_ROUND_TIED, 0, 0, "", "", "", _("^BGRound tied\n"), "") \ - MSG_INFO_NOTIF(1, INFO_ROUND_OVER, 0, 0, "", "", "", _("^BGRound over, there's no winner\n"), "") \ - MSG_INFO_NOTIF(1, INFO_FREEZETAG_SELF, 1, 0, "s1", "", "", _("^BG%s^K1 froze themself\n"), "") \ - MSG_INFO_NOTIF(1, INFO_GODMODE_OFF, 0, 1, "f1", "", "", _("^BGGodmode saved you %s units of damage, cheater!\n"), "") \ - MSG_INFO_NOTIF(0, INFO_ITEM_WEAPON_DONTHAVE, 0, 1, "item_wepname", "", "", _("^BGYou do not have the ^F1%s\n"), "") \ - MSG_INFO_NOTIF(0, INFO_ITEM_WEAPON_DROP, 1, 1, "item_wepname item_wepammo", "", "", _("^BGYou dropped the ^F1%s^BG%s\n"), "") \ - MSG_INFO_NOTIF(0, INFO_ITEM_WEAPON_GOT, 0, 1, "item_wepname", "", "", _("^BGYou got the ^F1%s\n"), "") \ - MSG_INFO_NOTIF(0, INFO_ITEM_WEAPON_NOAMMO, 0, 1, "item_wepname", "", "", _("^BGYou don't have enough ammo for the ^F1%s\n"), "") \ - MSG_INFO_NOTIF(0, INFO_ITEM_WEAPON_PRIMORSEC, 0, 3, "item_wepname f2primsec f3primsec", "", "", _("^F1%s %s^BG is unable to fire, but its ^F1%s^BG can\n"), "") \ - MSG_INFO_NOTIF(0, INFO_ITEM_WEAPON_UNAVAILABLE, 0, 1, "item_wepname", "", "", _("^F1%s^BG is ^F4not available^BG on this map\n"), "") \ - MSG_INFO_NOTIF(2, INFO_JOIN_CONNECT, 1, 0, "s1", "", "", _("^BG%s^F3 connected%s\n"), "") \ - MULTITEAM_INFO(2, INFO_JOIN_CONNECT_TEAM_, 4, 1, 0, "s1", "", "", _("^BG%s^F3 connected and joined the ^TC^TT team\n"), "") \ - MSG_INFO_NOTIF(1, INFO_JOIN_PLAY, 1, 0, "s1", "", "", _("^BG%s^F3 is now playing\n"), "") \ - MSG_INFO_NOTIF(1, INFO_KEEPAWAY_DROPPED, 1, 0, "s1", "s1", "notify_balldropped", _("^BG%s^BG has dropped the ball!\n"), "") \ - MSG_INFO_NOTIF(1, INFO_KEEPAWAY_PICKUP, 1, 0, "s1", "s1", "notify_ballpickedup", _("^BG%s^BG has picked up the ball!\n"), "") \ - MULTITEAM_INFO(1, INFO_KEYHUNT_CAPTURE_, 4, 1, 0, "s1", "", "", _("^BG%s^BG captured the keys for the ^TC^TT team\n"), "") \ - MULTITEAM_INFO(1, INFO_KEYHUNT_DROP_, 4, 1, 0, "s1", "", "", _("^BG%s^BG dropped the ^TC^TT Key\n"), "") \ - MULTITEAM_INFO(1, INFO_KEYHUNT_LOST_, 4, 1, 0, "s1", "", "", _("^BG%s^BG lost the ^TC^TT Key\n"), "") \ - MULTITEAM_INFO(1, INFO_KEYHUNT_PICKUP_, 4, 1, 0, "s1", "", "", _("^BG%s^BG picked up the ^TC^TT Key\n"), "") \ - MSG_INFO_NOTIF(1, INFO_LMS_FORFEIT, 1, 0, "s1", "", "", _("^BG%s^F3 forfeited\n"), "") \ - MSG_INFO_NOTIF(1, INFO_LMS_NOLIVES, 1, 0, "s1", "", "", _("^BG%s^F3 has no more lives left\n"), "") \ - MSG_INFO_NOTIF(1, INFO_MONSTERS_DISABLED, 0, 0, "", "", "", _("^BGMonsters are currently disabled\n"), "") \ - MSG_INFO_NOTIF(1, INFO_POWERUP_INVISIBILITY, 1, 0, "s1", "s1", "strength", _("^BG%s^K1 picked up Invisibility\n"), "") \ - MSG_INFO_NOTIF(1, INFO_POWERUP_SHIELD, 1, 0, "s1", "s1", "shield", _("^BG%s^K1 picked up Shield\n"), "") \ - MSG_INFO_NOTIF(1, INFO_POWERUP_SPEED, 1, 0, "s1", "s1", "shield", _("^BG%s^K1 picked up Speed\n"), "") \ - MSG_INFO_NOTIF(1, INFO_POWERUP_STRENGTH, 1, 0, "s1", "s1", "strength", _("^BG%s^K1 picked up Strength\n"), "") \ - MSG_INFO_NOTIF(2, INFO_QUIT_DISCONNECT, 1, 0, "s1", "", "", _("^BG%s^F3 disconnected\n"), "") \ - MSG_INFO_NOTIF(2, INFO_QUIT_KICK_IDLING, 1, 0, "s1", "", "", _("^BG%s^F3 was kicked for idling\n"), "") \ - MSG_INFO_NOTIF(1, INFO_QUIT_KICK_SPECTATING, 0, 0, "", "", "", _("^F2You were kicked from the server because you are a spectator and spectators aren't allowed at the moment.\n"), "") \ - MSG_INFO_NOTIF(1, INFO_QUIT_SPECTATE, 1, 0, "s1", "", "", _("^BG%s^F3 is now spectating\n"), "") \ - MSG_INFO_NOTIF(1, INFO_RACE_ABANDONED, 1, 0, "s1", "", "", _("^BG%s^BG has abandoned the race\n"), "") \ - MSG_INFO_NOTIF(1, INFO_RACE_FAIL_RANKED, 1, 3, "s1 race_col f1ord race_col f3race_time race_diff", "s1", "race_newfail", _("^BG%s^BG couldn't break their %s%s^BG place record of %s%s %s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_RACE_FAIL_UNRANKED, 1, 3, "s1 race_col f1ord race_col f3race_time race_diff", "s1", "race_newfail", _("^BG%s^BG couldn't break the %s%s^BG place record of %s%s %s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_RACE_FINISHED, 1, 0, "s1", "", "", _("^BG%s^BG has finished the race\n"), "") \ - MSG_INFO_NOTIF(1, INFO_RACE_NEW_BROKEN, 2, 3, "s1 s2 race_col f1ord race_col f2race_time race_diff", "s1 s2", "race_newrankyellow", _("^BG%s^BG broke %s^BG's %s%s^BG place record with %s%s %s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_RACE_NEW_IMPROVED, 1, 3, "s1 race_col f1ord race_col f2race_time race_diff", "s1", "race_newtime", _("^BG%s^BG improved their %s%s^BG place record with %s%s %s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_RACE_NEW_MISSING_UID, 1, 1, "s1 f1race_time", "s1", "race_newfail", _("^BG%s^BG scored a new record with ^F2%s^BG, but unfortunately lacks a UID and will be lost.\n"), "") \ - MSG_INFO_NOTIF(1, INFO_RACE_NEW_SET, 1, 2, "s1 race_col f1ord race_col f2race_time", "s1", "race_newrecordserver", _("^BG%s^BG set the %s%s^BG place record with %s%s\n"), "") \ - MULTITEAM_INFO(1, INFO_SCORES_, 4, 0, 0, "", "", "", _("^TC^TT ^BGteam scores!\n"), "") \ - MSG_INFO_NOTIF(1, INFO_SPECTATE_WARNING, 0, 1, "f1secs", "", "", _("^F2You have to become a player within the next %s, otherwise you will be kicked, because spectating isn't allowed at this time!\n"), "") \ - MSG_INFO_NOTIF(1, INFO_SUPERWEAPON_PICKUP, 1, 0, "s1", "s1", "strength", _("^BG%s^K1 picked up a Superweapon\n"), "") \ - MSG_INFO_NOTIF(2, INFO_VERSION_BETA, 2, 0, "s1 s2", "", "", _("^F4NOTE: ^BGThe server is running ^F1Xonotic %s (beta)^BG, you have ^F2Xonotic %s\n"), "") \ - MSG_INFO_NOTIF(2, INFO_VERSION_OLD, 2, 0, "s1 s2", "", "", _("^F4NOTE: ^BGThe server is running ^F1Xonotic %s^BG, you have ^F2Xonotic %s\n"), "") \ - MSG_INFO_NOTIF(2, INFO_VERSION_OUTDATED, 2, 0, "s1 s2", "", "", _("^F4NOTE: ^F1Xonotic %s^BG is out, and you still have ^F2Xonotic %s^BG - get the update from ^F3http://www.xonotic.org/^BG!\n"), "") \ - MSG_INFO_NOTIF(1, INFO_WATERMARK, 1, 0, "s1", "", "", _("^F3SVQC Build information: ^F4%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_WEAPON_ACCORDEON_MURDER, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weapontuba", _("^BG%s%s^K1 died of ^BG%s^K1's great playing on the @!#%%'n Accordeon%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_WEAPON_ACCORDEON_SUICIDE, 2, 1, "s1 s2loc spree_lost", "s1", "weapontuba", _("^BG%s^K1 hurt their own ears with the @!#%%'n Accordeon%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_WEAPON_CRYLINK_MURDER, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponcrylink", _("^BG%s%s^K1 felt the strong pull of ^BG%s^K1's Crylink%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_WEAPON_CRYLINK_SUICIDE, 2, 1, "s1 s2loc spree_lost", "s1", "weaponcrylink", _("^BG%s^K1 felt the strong pull of their Crylink%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_WEAPON_ELECTRO_MURDER_BOLT, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponelectro", _("^BG%s%s^K1 was blasted by ^BG%s^K1's Electro bolt%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_WEAPON_ELECTRO_MURDER_COMBO, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponelectro", _("^BG%s%s^K1 felt the electrifying air of ^BG%s^K1's Electro combo%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_WEAPON_ELECTRO_MURDER_ORBS, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponelectro", _("^BG%s%s^K1 got too close to ^BG%s^K1's Electro plasma%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_WEAPON_ELECTRO_SUICIDE_BOLT, 2, 1, "s1 s2loc spree_lost", "s1", "weaponelectro", _("^BG%s^K1 played with Electro plasma%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_WEAPON_ELECTRO_SUICIDE_ORBS, 2, 1, "s1 s2loc spree_lost", "s1", "weaponelectro", _("^BG%s^K1 could not remember where they put their Electro plasma%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_WEAPON_FIREBALL_MURDER_BLAST, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponfireball", _("^BG%s%s^K1 got too close to ^BG%s^K1's fireball%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_WEAPON_FIREBALL_MURDER_FIREMINE, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponfireball", _("^BG%s%s^K1 got burnt by ^BG%s^K1's firemine%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_WEAPON_FIREBALL_SUICIDE_BLAST, 2, 1, "s1 s2loc spree_lost", "s1", "weaponfireball", _("^BG%s^K1 should have used a smaller gun%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_WEAPON_FIREBALL_SUICIDE_FIREMINE, 2, 1, "s1 s2loc spree_lost", "s1", "weaponfireball", _("^BG%s^K1 forgot about their firemine%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_WEAPON_HAGAR_MURDER_BURST, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponhagar", _("^BG%s%s^K1 was pummeled by a burst of ^BG%s^K1's Hagar rockets%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_WEAPON_HAGAR_MURDER_SPRAY, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponhagar", _("^BG%s%s^K1 was pummeled by ^BG%s^K1's Hagar rockets%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_WEAPON_HAGAR_SUICIDE, 2, 1, "s1 s2loc spree_lost", "s1", "weaponhagar", _("^BG%s^K1 played with tiny Hagar rockets%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_WEAPON_HLAC_MURDER, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponhlac", _("^BG%s%s^K1 was cut down with ^BG%s^K1's HLAC%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_WEAPON_HLAC_SUICIDE, 2, 1, "s1 s2loc spree_lost", "s1", "weaponhlac", _("^BG%s^K1 got a little jumpy with their HLAC%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_WEAPON_HOOK_MURDER, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponhook", _("^BG%s%s^K1 was caught in ^BG%s^K1's Hook gravity bomb%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_WEAPON_KLEINBOTTLE_MURDER, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weapontuba", _("^BG%s%s^K1 died of ^BG%s^K1's great playing on the @!#%%'n Klein Bottle%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_WEAPON_KLEINBOTTLE_SUICIDE, 2, 1, "s1 s2loc spree_lost", "s1", "weapontuba", _("^BG%s^K1 hurt their own ears with the @!#%%'n Klein Bottle%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_WEAPON_LASER_MURDER, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponlaser", _("^BG%s%s^K1 was shot to death by ^BG%s^K1's Laser%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_WEAPON_LASER_SUICIDE, 2, 1, "s1 s2loc spree_lost", "s1", "weaponlaser", _("^BG%s^K1 shot themself to hell with their Laser%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_WEAPON_MINELAYER_MURDER, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponminelayer", _("^BG%s%s^K1 got too close to ^BG%s^K1's mine%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_WEAPON_MINELAYER_SUICIDE, 2, 1, "s1 s2loc spree_lost", "s1", "weaponminelayer", _("^BG%s^K1 forgot about their mine%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_WEAPON_MINSTANEX_MURDER, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponminstanex", _("^BG%s%s^K1 has been vaporized by ^BG%s^K1's Minstanex%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_WEAPON_MORTAR_MURDER_BOUNCE, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weapongrenadelauncher", _("^BG%s%s^K1 got too close to ^BG%s^K1's Mortar grenade%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_WEAPON_MORTAR_MURDER_EXPLODE, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weapongrenadelauncher", _("^BG%s%s^K1 ate ^BG%s^K1's Mortar grenade%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_WEAPON_MORTAR_SUICIDE_BOUNCE, 2, 1, "s1 s2loc spree_lost", "s1", "weapongrenadelauncher", _("^BG%s^K1 didn't see their own Mortar grenade%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_WEAPON_MORTAR_SUICIDE_EXPLODE, 2, 1, "s1 s2loc spree_lost", "s1", "weapongrenadelauncher", _("^BG%s^K1 blew themself up with their own Mortar%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_WEAPON_NEX_MURDER, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponnex", _("^BG%s%s^K1 has been vaporized by ^BG%s^K1's Nex%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_WEAPON_RIFLE_MURDER, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponrifle", _("^BG%s%s^K1 was sniped with a Rifle by ^BG%s^K1%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_WEAPON_RIFLE_MURDER_HAIL, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponrifle", _("^BG%s%s^K1 died in ^BG%s^K1's Rifle bullet hail%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_WEAPON_RIFLE_MURDER_HAIL_PIERCING, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponrifle", _("^BG%s%s^K1 failed to hide from ^BG%s^K1's Rifle bullet hail%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_WEAPON_RIFLE_MURDER_PIERCING, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponrifle", _("^BG%s%s^K1 failed to hide from ^BG%s^K1's Rifle%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_WEAPON_ROCKETLAUNCHER_MURDER_DIRECT, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponrocketlauncher", _("^BG%s%s^K1 ate ^BG%s^K1's rocket%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_WEAPON_ROCKETLAUNCHER_MURDER_SPLASH, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponrocketlauncher", _("^BG%s%s^K1 got too close ^BG%s^K1's rocket%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_WEAPON_ROCKETLAUNCHER_SUICIDE, 2, 1, "s1 s2loc spree_lost", "s1", "weaponrocketlauncher", _("^BG%s^K1 blew themself up with their Rocketlauncher%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_WEAPON_SEEKER_MURDER_SPRAY, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponseeker", _("^BG%s%s^K1 was pummeled by ^BG%s^K1's Seeker rockets%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_WEAPON_SEEKER_MURDER_TAG, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponseeker", _("^BG%s%s^K1 was tagged by ^BG%s^K1's Seeker%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_WEAPON_SEEKER_SUICIDE, 2, 1, "s1 s2loc spree_lost", "s1", "weaponseeker", _("^BG%s^K1 played with tiny Seeker rockets%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_WEAPON_SHOTGUN_MURDER, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponshotgun", _("^BG%s%s^K1 was gunned down by ^BG%s^K1's Shotgun%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_WEAPON_SHOTGUN_MURDER_SLAP, 3, 2, "spree_inf s2 s1 s3loc spree_end", "s2 s1", "notify_melee_shotgun", _("^BG%s%s^K1 slapped ^BG%s^K1 around a bit with a large Shotgun%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_WEAPON_THINKING_WITH_PORTALS, 2, 1, "s1 s2loc spree_lost", "s1", "notify_selfkill", _("^BG%s^K1 is now thinking with portals%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_WEAPON_TUBA_MURDER, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weapontuba", _("^BG%s%s^K1 died of ^BG%s^K1's great playing on the @!#%%'n Tuba%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_WEAPON_TUBA_SUICIDE, 2, 1, "s1 s2loc spree_lost", "s1", "weapontuba", _("^BG%s^K1 hurt their own ears with the @!#%%'n Tuba%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_WEAPON_UZI_MURDER_SNIPE, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponuzi", _("^BG%s%s^K1 was sniped by ^BG%s^K1's Machine Gun%s%s\n"), "") \ - MSG_INFO_NOTIF(1, INFO_WEAPON_UZI_MURDER_SPRAY, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponuzi", _("^BG%s%s^K1 was riddled full of holes by ^BG%s^K1's Machine Gun%s%s\n"), "") + MULTITEAM_INFO(1, INFO_CTF_CAPTURE_, 2, 1, 0, "s1", "s1", "notify_%s_captured", _("^BG%s^BG captured the ^TC^TT^BG flag"), "") \ + MULTITEAM_INFO(1, INFO_CTF_CAPTURE_BROKEN_, 2, 2, 2, "s1 f1p2dec s2 f2p2dec", "s1", "notify_%s_captured", _("^BG%s^BG captured the ^TC^TT^BG flag in ^F1%s^BG seconds, breaking ^BG%s^BG's previous record of ^F2%s^BG seconds"), "") \ + MULTITEAM_INFO(1, INFO_CTF_CAPTURE_TIME_, 2, 1, 1, "s1 f1p2dec", "s1", "notify_%s_captured", _("^BG%s^BG captured the ^TC^TT^BG flag in ^F1%s^BG seconds"), "") \ + MULTITEAM_INFO(1, INFO_CTF_CAPTURE_UNBROKEN_, 2, 2, 2, "s1 f1p2dec s2 f2p2dec", "s1", "notify_%s_captured", _("^BG%s^BG captured the ^TC^TT^BG flag in ^F2%s^BG seconds, failing to break ^BG%s^BG's previous record of ^F1%s^BG seconds"), "") \ + MULTITEAM_INFO(1, INFO_CTF_FLAGRETURN_ABORTRUN_, 2, 0, 0, "", "", "", _("^BGThe ^TC^TT^BG flag was returned to base by its owner"), "") \ + MULTITEAM_INFO(1, INFO_CTF_FLAGRETURN_DAMAGED_, 2, 0, 0, "", "", "", _("^BGThe ^TC^TT^BG flag was destroyed and returned to base"), "") \ + MULTITEAM_INFO(1, INFO_CTF_FLAGRETURN_DROPPED_, 2, 0, 0, "", "", "", _("^BGThe ^TC^TT^BG flag was dropped in the base and returned itself"), "") \ + MULTITEAM_INFO(1, INFO_CTF_FLAGRETURN_NEEDKILL_, 2, 0, 0, "", "", "", _("^BGThe ^TC^TT^BG flag fell somewhere it couldn't be reached and returned to base"), "") \ + MULTITEAM_INFO(1, INFO_CTF_FLAGRETURN_SPEEDRUN_, 2, 0, 1, "f1p2dec", "", "", _("^BGThe ^TC^TT^BG flag became impatient after ^F1%.2f^BG seconds and returned itself"), "") \ + MULTITEAM_INFO(1, INFO_CTF_FLAGRETURN_TIMEOUT_, 2, 0, 0, "", "", "", _("^BGThe ^TC^TT^BG flag has returned to the base"), "") \ + MULTITEAM_INFO(1, INFO_CTF_LOST_, 2, 1, 0, "s1", "s1", "notify_%s_lost", _("^BG%s^BG lost the ^TC^TT^BG flag"), "") \ + MULTITEAM_INFO(1, INFO_CTF_PICKUP_, 2, 1, 0, "s1", "s1", "notify_%s_taken", _("^BG%s^BG got the ^TC^TT^BG flag"), "") \ + MULTITEAM_INFO(1, INFO_CTF_RETURN_, 2, 1, 0, "s1", "s1", "notify_%s_returned", _("^BG%s^BG returned the ^TC^TT^BG flag"), "") \ + MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_CHEAT, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_death", _("^BG%s%s^K1 was unfairly eliminated by ^BG%s^K1%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_DROWN, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_water", _("^BG%s%s^K1 was drowned by ^BG%s^K1%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_FALL, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_fall", _("^BG%s%s^K1 was grounded by ^BG%s^K1%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_FIRE, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_death", _("^BG%s%s^K1 was burnt up into a crisp by ^BG%s^K1%s%s"), _("^BG%s%s^K1 felt a little hot from ^BG%s^K1's fire^K1%s%s")) \ + MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_LAVA, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_lava", _("^BG%s%s^K1 was cooked by ^BG%s^K1%s%s"), "") \ ++ MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_MONSTER, 3, 2, "spree_inf s1 s2 s3loc spree_end", "", "", _("^BG%s%s^K1 was pushed infront of a monster by ^BG%s^K1%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_NADE, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_death", _("^BG%s%s^K1 was blown up by ^BG%s^K1's Nade%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_SHOOTING_STAR, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_shootingstar", _("^BG%s%s^K1 was shot into space by ^BG%s^K1%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_SLIME, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_slime", _("^BG%s%s^K1 was slimed by ^BG%s^K1%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_SWAMP, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_slime", _("^BG%s%s^K1 was preserved by ^BG%s^K1%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_TELEFRAG, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_telefrag", _("^BG%s%s^K1 was telefragged by ^BG%s^K1%s%s"), _("^BG%s%s^K1 tried to occupy ^BG%s^K1's teleport destination space%s%s")) \ + MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_TOUCHEXPLODE, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_death", _("^BG%s%s^K1 died in an accident with ^BG%s^K1%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_VH_BUMB_DEATH, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_death", _("^BG%s%s^K1 got caught in the blast when ^BG%s^K1's Bumblebee exploded%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_VH_BUMB_GUN, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_death", _("^BG%s%s^K1 saw the pretty lights of ^BG%s^K1's Bumblebee gun%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_VH_CRUSH, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_death", _("^BG%s%s^K1 was crushed by ^BG%s^K1%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_VH_RAPT_BOMB, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_death", _("^BG%s%s^K1 was cluster bombed by ^BG%s^K1's Raptor%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_VH_RAPT_CANNON, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_death", _("^BG%s%s^K1 couldn't resist ^BG%s^K1's purple blobs%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_VH_RAPT_DEATH, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_death", _("^BG%s%s^K1 got caught in the blast when ^BG%s^K1's Raptor exploded%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_VH_SPID_DEATH, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_death", _("^BG%s%s^K1 got caught in the blast when ^BG%s^K1's Spiderbot exploded%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_VH_SPID_MINIGUN, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_death", _("^BG%s%s^K1 got shredded by ^BG%s^K1's Spiderbot%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_VH_SPID_ROCKET, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_death", _("^BG%s%s^K1 was blasted to bits by ^BG%s^K1's Spiderbot%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_VH_WAKI_DEATH, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_death", _("^BG%s%s^K1 got caught in the blast when ^BG%s^K1's Racer exploded%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_VH_WAKI_GUN, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_death", _("^BG%s%s^K1 was bolted down by ^BG%s^K1's Racer%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_VH_WAKI_ROCKET, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_death", _("^BG%s%s^K1 couldn't find shelter from ^BG%s^K1's Racer%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_VOID, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_void", _("^BG%s%s^K1 was thrown into a world of hurt by ^BG%s^K1%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_DEATH_SELF_AUTOTEAMCHANGE, 2, 1, "s1 s2loc death_team", "", "", _("^BG%s^K1 was moved into the %s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_DEATH_SELF_BETRAYAL, 2, 1, "s1 s2loc spree_lost", "s1", "notify_teamkill_red", _("^BG%s^K1 became enemies with the Lord of Teamplay%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_DEATH_SELF_CAMP, 2, 1, "s1 s2loc spree_lost", "s1", "notify_camping", _("^BG%s^K1 thought they found a nice camping ground%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_DEATH_SELF_CHEAT, 2, 1, "s1 s2loc spree_lost", "s1", "notify_selfkill", _("^BG%s^K1 unfairly eliminated themself%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_DEATH_SELF_CUSTOM, 3, 1, "s1 s2 s3loc spree_lost", "s1", "notify_void", _("^BG%s^K1 %s^K1%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_DEATH_SELF_DROWN, 2, 1, "s1 s2loc spree_lost", "s1", "notify_water", _("^BG%s^K1 couldn't catch their breath%s%s"), _("^BG%s^K1 was in the water for too long%s%s")) \ + MSG_INFO_NOTIF(1, INFO_DEATH_SELF_FALL, 2, 1, "s1 s2loc spree_lost", "s1", "notify_fall", _("^BG%s^K1 hit the ground with a crunch%s%s"), _("^BG%s^K1 hit the ground with a bit too much force%s%s")) \ + MSG_INFO_NOTIF(1, INFO_DEATH_SELF_FIRE, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 became a bit too crispy%s%s"), _("^BG%s^K1 felt a little hot%s%s")) \ + MSG_INFO_NOTIF(1, INFO_DEATH_SELF_GENERIC, 2, 1, "s1 s2loc spree_lost", "s1", "notify_selfkill", _("^BG%s^K1 died%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_DEATH_SELF_LAVA, 2, 1, "s1 s2loc spree_lost", "s1", "notify_lava", _("^BG%s^K1 turned into hot slag%s%s"), _("^BG%s^K1 found a hot place%s%s")) \ + MSG_INFO_NOTIF(1, INFO_DEATH_SELF_NADE, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 mastered the art of self-nading%s%s"), "") \ ++ MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_CERBERUS_BITE, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was mauled by a Cerberus%s%s"), "") \ ++ MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_CERBERUS_JUMP, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 didn't see the pouncing Cerberus%s%s"), "") \ ++ MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_ANIMUS, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was eviscerated by an Animus%s%s"), "") \ ++ MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_STINGRAY, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was fatally wounded by a Stingray%s%s"), "") \ ++ MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_KNIGHT_CRUSH, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was crushed by a pouncing Knight%s%s"), "") \ ++ MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_KNIGHT_FBALL, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was turned to ash by a Knight%s%s"), "") \ ++ MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_KNIGHT_INFERNO, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was burned to death by a Knight%s%s"), "") \ ++ MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_KNIGHT_MELEE, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was slain by a Knight%s%s"), "") \ ++ MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_KNIGHT_SPIKE, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was cursed by a Knight%s%s"), "") \ ++ MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_BRUISER, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was beaten in a fistfight by a Bruiser%s%s"), "") \ ++ MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_BRUTE_BLADE, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was cut down by a Brute%s%s"), "") \ ++ MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_BRUTE_GRENADE, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 almost dodged a Brute's grenade%s%s"), "") \ ++ MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_BRUTE_UZI, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was nailed by a Brute%s%s"), "") \ ++ MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_MAGE, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was exploded by a Mage%s%s"), "") \ ++ MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_SHAMBLER_CLAW, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1's innards became outwards by a Shambler%s%s"), "") \ ++ MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_SHAMBLER_SMASH, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was smashed by a Shambler%s%s"), "") \ ++ MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_SHAMBLER_ZAP, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was zapped to death by a Shambler%s%s"), "") \ ++ MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_SPIDER, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was bitten by a Spider%s%s"), "") \ ++ MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_SPIDER_FIRE, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was incinerated by a Spider%s%s"), "") \ ++ MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_SLIME, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was blown up by a Slime%s%s"), "") \ ++ MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_WYVERN, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was fireballed by a Wyvern%s%s"), "") \ ++ MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_ZOMBIE_JUMP, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 joins the Zombies%s%s"), "") \ ++ MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_ZOMBIE_MELEE, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was given kung fu lessons by a Zombie%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_DEATH_SELF_NOAMMO, 2, 1, "s1 s2loc spree_lost", "s1", "notify_outofammo", _("^BG%s^K1 died%s%s. What's the point of living without ammo?"), _("^BG%s^K1 ran out of ammo%s%s")) \ + MSG_INFO_NOTIF(1, INFO_DEATH_SELF_ROT, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 rotted away%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_DEATH_SELF_SHOOTING_STAR, 2, 1, "s1 s2loc spree_lost", "s1", "notify_shootingstar", _("^BG%s^K1 became a shooting star%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_DEATH_SELF_SLIME, 2, 1, "s1 s2loc spree_lost", "s1", "notify_slime", _("^BG%s^K1 was slimed%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_DEATH_SELF_SUICIDE, 2, 1, "s1 s2loc spree_lost", "s1", "notify_selfkill", _("^BG%s^K1 couldn't take it anymore%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_DEATH_SELF_SWAMP, 2, 1, "s1 s2loc spree_lost", "s1", "notify_slime", _("^BG%s^K1 is now preserved for centuries to come%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_DEATH_SELF_TEAMCHANGE, 2, 1, "s1 s2loc death_team", "", "", _("^BG%s^K1 switched to the %s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_DEATH_SELF_TOUCHEXPLODE, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 died in an accident%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_DEATH_SELF_TURRET, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 ran into a turret%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_DEATH_SELF_TURRET_EWHEEL, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was blasted away by an eWheel turret%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_DEATH_SELF_TURRET_FLAC, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 got caught up in the FLAC turret fire%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_DEATH_SELF_TURRET_HELLION, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was blasted away by a Hellion turret%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_DEATH_SELF_TURRET_HK, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 could not hide from the Hunter turret%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_DEATH_SELF_TURRET_MACHINEGUN, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was riddled full of holes by a Machinegun turret%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_DEATH_SELF_TURRET_MLRS, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 got turned into smoldering gibs by an MLRS turret%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_DEATH_SELF_TURRET_PHASER, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was phased out by a turret%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_DEATH_SELF_TURRET_PLASMA, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 got served some superheated plasma from a turret%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_DEATH_SELF_TURRET_TESLA, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was electrocuted by a Tesla turret%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_DEATH_SELF_TURRET_WALK_GUN, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 got served a lead enrichment by a Walker turret%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_DEATH_SELF_TURRET_WALK_MEELE, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was impaled by a Walker turret%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_DEATH_SELF_TURRET_WALK_ROCKET, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was blasted away by a Walker turret%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_DEATH_SELF_VH_BUMB_DEATH, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 got caught in the blast of a Bumblebee explosion%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_DEATH_SELF_VH_CRUSH, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was crushed by a vehicle%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_DEATH_SELF_VH_RAPT_BOMB, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was caught in a Raptor cluster bomb%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_DEATH_SELF_VH_RAPT_DEATH, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 got caught in the blast of a Raptor explosion%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_DEATH_SELF_VH_SPID_DEATH, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 got caught in the blast of a Spiderbot explosion%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_DEATH_SELF_VH_SPID_ROCKET, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was blasted to bits by a Spiderbot rocket%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_DEATH_SELF_VH_WAKI_DEATH, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 got caught in the blast of a Racer explosion%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_DEATH_SELF_VH_WAKI_ROCKET, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 couldn't find shelter from a Racer rocket%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_DEATH_SELF_VOID, 2, 1, "s1 s2loc spree_lost", "s1", "notify_void", _("^BG%s^K1 was in the wrong place%s%s"), "") \ + MULTITEAM_INFO(1, INFO_DEATH_TEAMKILL_, 4, 3, 1, "s1 s2 s3loc spree_end", "s2 s1", "notify_teamkill_%s", _("^BG%s^K1 was betrayed by ^BG%s^K1%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_FREEZETAG_FREEZE, 2, 0, "s1 s2", "", "", _("^BG%s^K1 was frozen by ^BG%s"), "") \ + MSG_INFO_NOTIF(1, INFO_FREEZETAG_REVIVED, 2, 0, "s1 s2", "", "", _("^BG%s^K3 was revived by ^BG%s"), "") \ + MSG_INFO_NOTIF(1, INFO_FREEZETAG_REVIVED_FALL, 1, 0, "s1", "", "", _("^BG%s^K3 was revived by falling"), "") \ + MSG_INFO_NOTIF(1, INFO_FREEZETAG_AUTO_REVIVED, 1, 1, "s1 f1", "", "", _("^BG%s^K3 was automatically revived after %s second(s)"), "") \ + MULTITEAM_INFO(1, INFO_ROUND_TEAM_WIN_, 4, 0, 0, "", "", "", _("^TC^TT^BG team wins the round"), "") \ + MSG_INFO_NOTIF(1, INFO_ROUND_PLAYER_WIN, 1, 0, "s1", "", "", _("^BG%s^BG wins the round"), "") \ + MSG_INFO_NOTIF(1, INFO_ROUND_TIED, 0, 0, "", "", "", _("^BGRound tied"), "") \ + MSG_INFO_NOTIF(1, INFO_ROUND_OVER, 0, 0, "", "", "", _("^BGRound over, there's no winner"), "") \ + MSG_INFO_NOTIF(1, INFO_FREEZETAG_SELF, 1, 0, "s1", "", "", _("^BG%s^K1 froze themself"), "") \ + MSG_INFO_NOTIF(1, INFO_GODMODE_OFF, 0, 1, "f1", "", "", _("^BGGodmode saved you %s units of damage, cheater!"), "") \ + MSG_INFO_NOTIF(0, INFO_ITEM_WEAPON_DONTHAVE, 0, 1, "item_wepname", "", "", _("^BGYou do not have the ^F1%s"), "") \ + MSG_INFO_NOTIF(0, INFO_ITEM_WEAPON_DROP, 1, 1, "item_wepname item_wepammo", "", "", _("^BGYou dropped the ^F1%s^BG%s"), "") \ + MSG_INFO_NOTIF(0, INFO_ITEM_WEAPON_GOT, 0, 1, "item_wepname", "", "", _("^BGYou got the ^F1%s"), "") \ + MSG_INFO_NOTIF(0, INFO_ITEM_WEAPON_NOAMMO, 0, 1, "item_wepname", "", "", _("^BGYou don't have enough ammo for the ^F1%s"), "") \ + MSG_INFO_NOTIF(0, INFO_ITEM_WEAPON_PRIMORSEC, 0, 3, "item_wepname f2primsec f3primsec", "", "", _("^F1%s %s^BG is unable to fire, but its ^F1%s^BG can"), "") \ + MSG_INFO_NOTIF(0, INFO_ITEM_WEAPON_UNAVAILABLE, 0, 1, "item_wepname", "", "", _("^F1%s^BG is ^F4not available^BG on this map"), "") \ + MSG_INFO_NOTIF(2, INFO_JOIN_CONNECT, 1, 0, "s1", "", "", _("^BG%s^F3 connected%s"), "") \ + MULTITEAM_INFO(2, INFO_JOIN_CONNECT_TEAM_, 4, 1, 0, "s1", "", "", _("^BG%s^F3 connected and joined the ^TC^TT team"), "") \ + MSG_INFO_NOTIF(1, INFO_JOIN_PLAY, 1, 0, "s1", "", "", _("^BG%s^F3 is now playing"), "") \ + MSG_INFO_NOTIF(1, INFO_KEEPAWAY_DROPPED, 1, 0, "s1", "s1", "notify_balldropped", _("^BG%s^BG has dropped the ball!"), "") \ + MSG_INFO_NOTIF(1, INFO_KEEPAWAY_PICKUP, 1, 0, "s1", "s1", "notify_ballpickedup", _("^BG%s^BG has picked up the ball!"), "") \ + MULTITEAM_INFO(1, INFO_KEYHUNT_CAPTURE_, 4, 1, 0, "s1", "", "", _("^BG%s^BG captured the keys for the ^TC^TT team"), "") \ + MULTITEAM_INFO(1, INFO_KEYHUNT_DROP_, 4, 1, 0, "s1", "", "", _("^BG%s^BG dropped the ^TC^TT Key"), "") \ + MULTITEAM_INFO(1, INFO_KEYHUNT_LOST_, 4, 1, 0, "s1", "", "", _("^BG%s^BG lost the ^TC^TT Key"), "") \ + MULTITEAM_INFO(1, INFO_KEYHUNT_PICKUP_, 4, 1, 0, "s1", "", "", _("^BG%s^BG picked up the ^TC^TT Key"), "") \ + MSG_INFO_NOTIF(1, INFO_LMS_FORFEIT, 1, 0, "s1", "", "", _("^BG%s^F3 forfeited"), "") \ + MSG_INFO_NOTIF(1, INFO_LMS_NOLIVES, 1, 0, "s1", "", "", _("^BG%s^F3 has no more lives left"), "") \ ++ MSG_INFO_NOTIF(1, INFO_MONSTERS_DISABLED, 0, 0, "", "", "", _("^BGMonsters are currently disabled"), "") \ + MSG_INFO_NOTIF(1, INFO_POWERUP_INVISIBILITY, 1, 0, "s1", "s1", "strength", _("^BG%s^K1 picked up Invisibility"), "") \ + MSG_INFO_NOTIF(1, INFO_POWERUP_SHIELD, 1, 0, "s1", "s1", "shield", _("^BG%s^K1 picked up Shield"), "") \ + MSG_INFO_NOTIF(1, INFO_POWERUP_SPEED, 1, 0, "s1", "s1", "shield", _("^BG%s^K1 picked up Speed"), "") \ + MSG_INFO_NOTIF(1, INFO_POWERUP_STRENGTH, 1, 0, "s1", "s1", "strength", _("^BG%s^K1 picked up Strength"), "") \ + MSG_INFO_NOTIF(2, INFO_QUIT_DISCONNECT, 1, 0, "s1", "", "", _("^BG%s^F3 disconnected"), "") \ + MSG_INFO_NOTIF(2, INFO_QUIT_KICK_IDLING, 1, 0, "s1", "", "", _("^BG%s^F3 was kicked for idling"), "") \ + MSG_INFO_NOTIF(1, INFO_QUIT_KICK_SPECTATING, 0, 0, "", "", "", _("^F2You were kicked from the server because you are a spectator and spectators aren't allowed at the moment."), "") \ + MSG_INFO_NOTIF(1, INFO_QUIT_SPECTATE, 1, 0, "s1", "", "", _("^BG%s^F3 is now spectating"), "") \ + MSG_INFO_NOTIF(1, INFO_RACE_ABANDONED, 1, 0, "s1", "", "", _("^BG%s^BG has abandoned the race"), "") \ + MSG_INFO_NOTIF(1, INFO_RACE_FAIL_RANKED, 1, 3, "s1 race_col f1ord race_col f3race_time race_diff", "s1", "race_newfail", _("^BG%s^BG couldn't break their %s%s^BG place record of %s%s %s"), "") \ + MSG_INFO_NOTIF(1, INFO_RACE_FAIL_UNRANKED, 1, 3, "s1 race_col f1ord race_col f3race_time race_diff", "s1", "race_newfail", _("^BG%s^BG couldn't break the %s%s^BG place record of %s%s %s"), "") \ + MSG_INFO_NOTIF(1, INFO_RACE_FINISHED, 1, 0, "s1", "", "", _("^BG%s^BG has finished the race"), "") \ + MSG_INFO_NOTIF(1, INFO_RACE_NEW_BROKEN, 2, 3, "s1 s2 race_col f1ord race_col f2race_time race_diff", "s1 s2", "race_newrankyellow", _("^BG%s^BG broke %s^BG's %s%s^BG place record with %s%s %s"), "") \ + MSG_INFO_NOTIF(1, INFO_RACE_NEW_IMPROVED, 1, 3, "s1 race_col f1ord race_col f2race_time race_diff", "s1", "race_newtime", _("^BG%s^BG improved their %s%s^BG place record with %s%s %s"), "") \ + MSG_INFO_NOTIF(1, INFO_RACE_NEW_MISSING_UID, 1, 1, "s1 f1race_time", "s1", "race_newfail", _("^BG%s^BG scored a new record with ^F2%s^BG, but unfortunately lacks a UID and will be lost."), "") \ + MSG_INFO_NOTIF(1, INFO_RACE_NEW_SET, 1, 2, "s1 race_col f1ord race_col f2race_time", "s1", "race_newrecordserver", _("^BG%s^BG set the %s%s^BG place record with %s%s"), "") \ + MULTITEAM_INFO(1, INFO_SCORES_, 4, 0, 0, "", "", "", _("^TC^TT ^BGteam scores!"), "") \ + MSG_INFO_NOTIF(1, INFO_SPECTATE_WARNING, 0, 1, "f1secs", "", "", _("^F2You have to become a player within the next %s, otherwise you will be kicked, because spectating isn't allowed at this time!"), "") \ + MSG_INFO_NOTIF(1, INFO_SUPERWEAPON_PICKUP, 1, 0, "s1", "s1", "strength", _("^BG%s^K1 picked up a Superweapon"), "") \ + MSG_INFO_NOTIF(2, INFO_VERSION_BETA, 2, 0, "s1 s2", "", "", _("^F4NOTE: ^BGThe server is running ^F1Xonotic %s (beta)^BG, you have ^F2Xonotic %s"), "") \ + MSG_INFO_NOTIF(2, INFO_VERSION_OLD, 2, 0, "s1 s2", "", "", _("^F4NOTE: ^BGThe server is running ^F1Xonotic %s^BG, you have ^F2Xonotic %s"), "") \ + MSG_INFO_NOTIF(2, INFO_VERSION_OUTDATED, 2, 0, "s1 s2", "", "", _("^F4NOTE: ^F1Xonotic %s^BG is out, and you still have ^F2Xonotic %s^BG - get the update from ^F3http://www.xonotic.org/^BG!"), "") \ + MSG_INFO_NOTIF(1, INFO_WATERMARK, 1, 0, "s1", "", "", _("^F3SVQC Build information: ^F4%s"), "") \ + MSG_INFO_NOTIF(1, INFO_WEAPON_ACCORDEON_MURDER, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weapontuba", _("^BG%s%s^K1 died of ^BG%s^K1's great playing on the @!#%%'n Accordeon%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_WEAPON_ACCORDEON_SUICIDE, 2, 1, "s1 s2loc spree_lost", "s1", "weapontuba", _("^BG%s^K1 hurt their own ears with the @!#%%'n Accordeon%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_WEAPON_CRYLINK_MURDER, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponcrylink", _("^BG%s%s^K1 felt the strong pull of ^BG%s^K1's Crylink%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_WEAPON_CRYLINK_SUICIDE, 2, 1, "s1 s2loc spree_lost", "s1", "weaponcrylink", _("^BG%s^K1 felt the strong pull of their Crylink%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_WEAPON_ELECTRO_MURDER_BOLT, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponelectro", _("^BG%s%s^K1 was blasted by ^BG%s^K1's Electro bolt%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_WEAPON_ELECTRO_MURDER_COMBO, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponelectro", _("^BG%s%s^K1 felt the electrifying air of ^BG%s^K1's Electro combo%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_WEAPON_ELECTRO_MURDER_ORBS, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponelectro", _("^BG%s%s^K1 got too close to ^BG%s^K1's Electro plasma%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_WEAPON_ELECTRO_SUICIDE_BOLT, 2, 1, "s1 s2loc spree_lost", "s1", "weaponelectro", _("^BG%s^K1 played with Electro plasma%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_WEAPON_ELECTRO_SUICIDE_ORBS, 2, 1, "s1 s2loc spree_lost", "s1", "weaponelectro", _("^BG%s^K1 could not remember where they put their Electro plasma%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_WEAPON_FIREBALL_MURDER_BLAST, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponfireball", _("^BG%s%s^K1 got too close to ^BG%s^K1's fireball%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_WEAPON_FIREBALL_MURDER_FIREMINE, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponfireball", _("^BG%s%s^K1 got burnt by ^BG%s^K1's firemine%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_WEAPON_FIREBALL_SUICIDE_BLAST, 2, 1, "s1 s2loc spree_lost", "s1", "weaponfireball", _("^BG%s^K1 should have used a smaller gun%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_WEAPON_FIREBALL_SUICIDE_FIREMINE, 2, 1, "s1 s2loc spree_lost", "s1", "weaponfireball", _("^BG%s^K1 forgot about their firemine%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_WEAPON_HAGAR_MURDER_BURST, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponhagar", _("^BG%s%s^K1 was pummeled by a burst of ^BG%s^K1's Hagar rockets%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_WEAPON_HAGAR_MURDER_SPRAY, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponhagar", _("^BG%s%s^K1 was pummeled by ^BG%s^K1's Hagar rockets%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_WEAPON_HAGAR_SUICIDE, 2, 1, "s1 s2loc spree_lost", "s1", "weaponhagar", _("^BG%s^K1 played with tiny Hagar rockets%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_WEAPON_HLAC_MURDER, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponhlac", _("^BG%s%s^K1 was cut down with ^BG%s^K1's HLAC%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_WEAPON_HLAC_SUICIDE, 2, 1, "s1 s2loc spree_lost", "s1", "weaponhlac", _("^BG%s^K1 got a little jumpy with their HLAC%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_WEAPON_HOOK_MURDER, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponhook", _("^BG%s%s^K1 was caught in ^BG%s^K1's Hook gravity bomb%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_WEAPON_KLEINBOTTLE_MURDER, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weapontuba", _("^BG%s%s^K1 died of ^BG%s^K1's great playing on the @!#%%'n Klein Bottle%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_WEAPON_KLEINBOTTLE_SUICIDE, 2, 1, "s1 s2loc spree_lost", "s1", "weapontuba", _("^BG%s^K1 hurt their own ears with the @!#%%'n Klein Bottle%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_WEAPON_LASER_MURDER, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponlaser", _("^BG%s%s^K1 was shot to death by ^BG%s^K1's Laser%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_WEAPON_LASER_SUICIDE, 2, 1, "s1 s2loc spree_lost", "s1", "weaponlaser", _("^BG%s^K1 shot themself to hell with their Laser%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_WEAPON_MINELAYER_MURDER, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponminelayer", _("^BG%s%s^K1 got too close to ^BG%s^K1's mine%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_WEAPON_MINELAYER_SUICIDE, 2, 1, "s1 s2loc spree_lost", "s1", "weaponminelayer", _("^BG%s^K1 forgot about their mine%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_WEAPON_MINSTANEX_MURDER, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponminstanex", _("^BG%s%s^K1 has been vaporized by ^BG%s^K1's Minstanex%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_WEAPON_MORTAR_MURDER_BOUNCE, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weapongrenadelauncher", _("^BG%s%s^K1 got too close to ^BG%s^K1's Mortar grenade%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_WEAPON_MORTAR_MURDER_EXPLODE, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weapongrenadelauncher", _("^BG%s%s^K1 ate ^BG%s^K1's Mortar grenade%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_WEAPON_MORTAR_SUICIDE_BOUNCE, 2, 1, "s1 s2loc spree_lost", "s1", "weapongrenadelauncher", _("^BG%s^K1 didn't see their own Mortar grenade%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_WEAPON_MORTAR_SUICIDE_EXPLODE, 2, 1, "s1 s2loc spree_lost", "s1", "weapongrenadelauncher", _("^BG%s^K1 blew themself up with their own Mortar%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_WEAPON_NEX_MURDER, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponnex", _("^BG%s%s^K1 has been vaporized by ^BG%s^K1's Nex%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_WEAPON_RIFLE_MURDER, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponrifle", _("^BG%s%s^K1 was sniped with a Rifle by ^BG%s^K1%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_WEAPON_RIFLE_MURDER_HAIL, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponrifle", _("^BG%s%s^K1 died in ^BG%s^K1's Rifle bullet hail%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_WEAPON_RIFLE_MURDER_HAIL_PIERCING, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponrifle", _("^BG%s%s^K1 failed to hide from ^BG%s^K1's Rifle bullet hail%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_WEAPON_RIFLE_MURDER_PIERCING, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponrifle", _("^BG%s%s^K1 failed to hide from ^BG%s^K1's Rifle%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_WEAPON_ROCKETLAUNCHER_MURDER_DIRECT, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponrocketlauncher", _("^BG%s%s^K1 ate ^BG%s^K1's rocket%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_WEAPON_ROCKETLAUNCHER_MURDER_SPLASH, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponrocketlauncher", _("^BG%s%s^K1 got too close ^BG%s^K1's rocket%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_WEAPON_ROCKETLAUNCHER_SUICIDE, 2, 1, "s1 s2loc spree_lost", "s1", "weaponrocketlauncher", _("^BG%s^K1 blew themself up with their Rocketlauncher%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_WEAPON_SEEKER_MURDER_SPRAY, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponseeker", _("^BG%s%s^K1 was pummeled by ^BG%s^K1's Seeker rockets%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_WEAPON_SEEKER_MURDER_TAG, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponseeker", _("^BG%s%s^K1 was tagged by ^BG%s^K1's Seeker%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_WEAPON_SEEKER_SUICIDE, 2, 1, "s1 s2loc spree_lost", "s1", "weaponseeker", _("^BG%s^K1 played with tiny Seeker rockets%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_WEAPON_SHOTGUN_MURDER, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponshotgun", _("^BG%s%s^K1 was gunned down by ^BG%s^K1's Shotgun%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_WEAPON_SHOTGUN_MURDER_SLAP, 3, 2, "spree_inf s2 s1 s3loc spree_end", "s2 s1", "notify_melee_shotgun", _("^BG%s%s^K1 slapped ^BG%s^K1 around a bit with a large Shotgun%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_WEAPON_THINKING_WITH_PORTALS, 2, 1, "s1 s2loc spree_lost", "s1", "notify_selfkill", _("^BG%s^K1 is now thinking with portals%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_WEAPON_TUBA_MURDER, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weapontuba", _("^BG%s%s^K1 died of ^BG%s^K1's great playing on the @!#%%'n Tuba%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_WEAPON_TUBA_SUICIDE, 2, 1, "s1 s2loc spree_lost", "s1", "weapontuba", _("^BG%s^K1 hurt their own ears with the @!#%%'n Tuba%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_WEAPON_UZI_MURDER_SNIPE, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponuzi", _("^BG%s%s^K1 was sniped by ^BG%s^K1's Machine Gun%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_WEAPON_UZI_MURDER_SPRAY, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponuzi", _("^BG%s%s^K1 was riddled full of holes by ^BG%s^K1's Machine Gun%s%s"), "") #define MULTITEAM_CENTER(default,prefix,teams,strnum,flnum,args,cpid,durcnt,normal,gentle) \ MSG_CENTER_NOTIF(default, prefix##RED, strnum, flnum, args, cpid, durcnt, TCR(normal, COL_TEAM_1, strtoupper(NAME_TEAM_1)), TCR(gentle, COL_TEAM_1, strtoupper(NAME_TEAM_1))) \ @@@ -594,8 -659,7 +685,8 @@@ MSG_MULTI_NOTIF(1, DEATH_MURDER_FALL, NO_MSG, INFO_DEATH_MURDER_FALL, NO_MSG) \ MSG_MULTI_NOTIF(1, DEATH_MURDER_FIRE, NO_MSG, INFO_DEATH_MURDER_FIRE, NO_MSG) \ MSG_MULTI_NOTIF(1, DEATH_MURDER_LAVA, NO_MSG, INFO_DEATH_MURDER_LAVA, NO_MSG) \ + MSG_MULTI_NOTIF(1, DEATH_MURDER_MONSTER, NO_MSG, INFO_DEATH_MURDER_MONSTER, CENTER_DEATH_SELF_MONSTER) \ - MSG_MULTI_NOTIF(1, DEATH_MURDER_NADE, NO_MSG, INFO_DEATH_MURDER_NADE, NO_MSG) \ + MSG_MULTI_NOTIF(1, DEATH_MURDER_NADE, NO_MSG, INFO_DEATH_MURDER_NADE, NO_MSG) \ MSG_MULTI_NOTIF(1, DEATH_MURDER_SHOOTING_STAR, NO_MSG, INFO_DEATH_MURDER_SHOOTING_STAR, NO_MSG) \ MSG_MULTI_NOTIF(1, DEATH_MURDER_SLIME, NO_MSG, INFO_DEATH_MURDER_SLIME, NO_MSG) \ MSG_MULTI_NOTIF(1, DEATH_MURDER_SWAMP, NO_MSG, INFO_DEATH_MURDER_SWAMP, NO_MSG) \ diff --cc qcsrc/server/accuracy.qc index 24cc20e17,dfc923b2b..c7d851b6e --- a/qcsrc/server/accuracy.qc +++ b/qcsrc/server/accuracy.qc @@@ -109,13 -109,10 +109,14 @@@ void accuracy_add(entity e, float w, fl float accuracy_isgooddamage(entity attacker, entity targ) { + float targ_isvalid = ((g_invasion) ? targ.flags & FL_MONSTER : IS_CLIENT(targ)); + - if(!inWarmupStage) + if(!warmup_stage) + if(targ_isvalid) + if not(attacker.flags & FL_MONSTER) // no accuracy for monsters + if(IS_CLIENT(targ)) if(targ.deadflag == DEAD_NO) - if(IsDifferentTeam(attacker, targ)) + if(DIFF_TEAM(attacker, targ)) return TRUE; return FALSE; } diff --cc qcsrc/server/cl_client.qc index e4d349d7b,baf696f6e..0c27100fe --- a/qcsrc/server/cl_client.qc +++ b/qcsrc/server/cl_client.qc @@@ -168,11 -168,9 +168,11 @@@ void PutObserverInServer (void Portal_ClearAll(self); + Unfreeze(self); + if(self.alivetime) { - if(!inWarmupStage) + if(!warmup_stage) PlayerStats_Event(self, PLAYERSTATS_ALIVETIME, time - self.alivetime); self.alivetime = 0; } diff --cc qcsrc/server/g_damage.qc index 5b310818c,6a6587ec8..4cae47770 --- a/qcsrc/server/g_damage.qc +++ b/qcsrc/server/g_damage.qc @@@ -800,9 -732,9 +809,9 @@@ void Damage (entity targ, entity inflic else victim = targ; - if(IS_PLAYER(victim) || victim.turrcaps_flags & TFL_TURRCAPS_ISTURRET) + if(IS_PLAYER(victim) || victim.turrcaps_flags & TFL_TURRCAPS_ISTURRET || victim.flags & FL_MONSTER) { - if(IsDifferentTeam(victim, attacker)) + if(DIFF_TEAM(victim, attacker)) { if(damage > 0) { diff --cc qcsrc/server/mutators/gamemode_ctf.qc index f09a0c262,f95d956c0..a5de5b276 --- a/qcsrc/server/mutators/gamemode_ctf.qc +++ b/qcsrc/server/mutators/gamemode_ctf.qc @@@ -852,18 -803,18 +814,18 @@@ void ctf_FlagTouch( { case FLAG_BASE: { - if(!IsDifferentTeam(toucher, self) && (toucher.flagcarried) && IsDifferentTeam(toucher.flagcarried, self) && !(toucher.flags & FL_MONSTER)) - if(SAME_TEAM(toucher, self) && (toucher.flagcarried) && DIFF_TEAM(toucher.flagcarried, self)) ++ if(SAME_TEAM(toucher, self) && (toucher.flagcarried) && DIFF_TEAM(toucher.flagcarried, self) && !(toucher.flags & FL_MONSTER)) ctf_Handle_Capture(self, toucher, CAPTURE_NORMAL); // toucher just captured the enemies flag to his base - else if(IsDifferentTeam(toucher, self) && (!toucher.flagcarried) && (!toucher.ctf_captureshielded) && (time > toucher.next_take_time) && !(toucher.flags & FL_MONSTER)) - else if(DIFF_TEAM(toucher, self) && (!toucher.flagcarried) && (!toucher.ctf_captureshielded) && (time > toucher.next_take_time)) ++ else if(DIFF_TEAM(toucher, self) && (!toucher.flagcarried) && (!toucher.ctf_captureshielded) && (time > toucher.next_take_time) && !(toucher.flags & FL_MONSTER)) ctf_Handle_Pickup(self, toucher, PICKUP_BASE); // toucher just stole the enemies flag break; } case FLAG_DROPPED: { - if(!IsDifferentTeam(toucher, self)) + if(SAME_TEAM(toucher, self)) ctf_Handle_Return(self, toucher); // toucher just returned his own flag - else if((!toucher.flagcarried) && ((toucher != self.ctf_dropper) || (time > self.ctf_droptime + autocvar_g_ctf_flag_collect_delay))) + else if(!(toucher.flags & FL_MONSTER) && (!toucher.flagcarried) && ((toucher != self.ctf_dropper) || (time > self.ctf_droptime + autocvar_g_ctf_flag_collect_delay))) ctf_Handle_Pickup(self, toucher, PICKUP_DROPPED); // toucher just picked up a dropped enemy flag break; } diff --cc qcsrc/server/mutators/gamemode_freezetag.qc index 95c384919,0c22db05b..c1cb5b851 --- a/qcsrc/server/mutators/gamemode_freezetag.qc +++ b/qcsrc/server/mutators/gamemode_freezetag.qc @@@ -406,9 -448,9 +406,9 @@@ MUTATOR_HOOKFUNCTION(freezetag_PlayerPr n = 0; FOR_EACH_PLAYER(other) if(self != other) { - if(other.freezetag_frozen == 0) + if(other.frozen == 0) { - if(!IsDifferentTeam(other, self)) - if(other.team == self.team) ++ if(SAME_TEAM(other, self)) { if(boxesoverlap(self.absmin - revive_extra_size, self.absmax + revive_extra_size, other.absmin, other.absmax)) { diff --cc qcsrc/server/tturrets/units/unit_fusionreactor.qc index 5954384b2,8118b8f23..32e4a24dc --- a/qcsrc/server/tturrets/units/unit_fusionreactor.qc +++ b/qcsrc/server/tturrets/units/unit_fusionreactor.qc @@@ -38,15 -38,15 +38,15 @@@ float turret_fusionreactor_firecheck( return 0; if (self.ammo < self.shot_dmg) - return 0; - - if (self.enemy.ammo >= self.enemy.ammo_max) - return 0; + return 0; if (vlen(self.enemy.origin - self.origin) > self.target_range) - return 0; + return 0; + + if (self.enemy.ammo >= self.enemy.ammo_max) + return 0; - if(IsDifferentTeam(self, self.enemy)) - if(self.team != self.enemy.team) ++ if(DIFF_TEAM(self, self.enemy)) return 0; if not (self.enemy.ammo_flags & TFL_AMMO_ENERGY)