From: Mario Date: Tue, 5 Mar 2013 10:51:36 +0000 (+1100) Subject: Merge branch 'master' into mario/monsters X-Git-Tag: xonotic-v0.8.0~241^2^2~484 X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=967b6f037d11a823dad929627a9b20f779e130b2;p=xonotic%2Fxonotic-data.pk3dir.git Merge branch 'master' into mario/monsters --- 967b6f037d11a823dad929627a9b20f779e130b2 diff --cc defaultXonotic.cfg index a7c08d194,e1b16f435..23329b718 --- a/defaultXonotic.cfg +++ b/defaultXonotic.cfg @@@ -1558,8 -1554,7 +1560,9 @@@ exec turrets.cf exec vehicles.cfg exec crosshairs.cfg exec gamemodes.cfg + exec notifications.cfg +exec monsters.cfg +exec za.cfg // load console command aliases and settings exec commands.cfg diff --cc gamemodes.cfg index 9a62eb26c,05aaf3df4..adb9ad9a9 --- a/gamemodes.cfg +++ b/gamemodes.cfg @@@ -482,42 -475,3 +485,42 @@@ set g_balance_rune_speed_highspeed 1. set g_balance_curse_slow_highspeed 0.6 set g_balance_rune_speed_combo_highspeed 0.9 +// =============== +// tower defense +// =============== +set g_td 0 "Tower Defense: protect the generator/s from waves of monsters" +set g_td_force_settings 0 "if enabled, don't use map settings (monster count, start wave etc.)" +set g_td_start_wave 1 +set g_td_generator_health 700 +set g_td_generator_damaged_points 20 "player loses this many points if the generator was damaged during the wave" +set g_td_current_monsters 10 "maximum monsters that can be spawned simultaneously" +set g_td_monster_count 10 +set g_td_monster_count_increment 5 +set g_td_buildphase_time 20 +set g_td_generator_dontend 0 "don't change maps when a generator is destroyed (only if there is more than 1 generator)" +set g_td_pvp 0 +set g_td_monsters_skill_start 1 "set to 0 to use g_monsters_skill instead" +set g_td_monsters_skill_increment 0.1 +set g_td_monsters_spawnshield_time 2 +set g_td_monsters_ignore_turrets 0 +set g_td_max_waves 8 +set g_td_kill_points 5 +set g_td_turretkill_points 3 +set g_td_turret_max 4 +set g_td_turret_plasma_cost 50 +set g_td_turret_mlrs_cost 80 +set g_td_turret_walker_cost 100 +set g_td_tower_buff_cost 70 +set g_td_barricade_damage 10 +set g_td_barricade_cost 20 +set g_td_turret_flac_cost 40 +set g_td_turret_upgrade_cost 100 +set g_td_turret_repair_cost 20 +set g_td_monsters_speed_walk 75 +set g_td_monsters_speed_run 110 +set g_td_monsters_spawn_delay 3 + +// ==================== +// real-time strategy +// ==================== - set g_rts 0 "Real-Time Strategy: defend your generator & turrets by controlling monsters" ++set g_rts 0 "Real-Time Strategy: defend your generator & turrets by controlling monsters" diff --cc qcsrc/client/hud.qc index 548e05548,82467348e..ea7770e0a --- a/qcsrc/client/hud.qc +++ b/qcsrc/client/hud.qc @@@ -1617,618 -1629,25 +1629,94 @@@ void HUD_HealthArmor(void // Notification area (#4) // - string Weapon_SuicideMessage(float deathtype) + void HUD_Notify_Push(string icon, string attacker, string victim) { - w_deathtype = deathtype; - get_weaponinfo(DEATH_WEAPONOF(deathtype)).weapon_func(WR_SUICIDEMESSAGE); - return w_deathtypestring; - } - - string Weapon_KillMessage(float deathtype) - { - w_deathtype = deathtype; - get_weaponinfo(DEATH_WEAPONOF(deathtype)).weapon_func(WR_KILLMESSAGE); - return w_deathtypestring; - } + if(icon != "") + { + --kn_index; + if (kn_index == -1) { kn_index = KN_MAX_ENTRIES-1; } + notify_times[kn_index] = time; - #define KN_MAX_ENTRIES 10 - float kn_index; - float killnotify_times[KN_MAX_ENTRIES]; - float killnotify_deathtype[KN_MAX_ENTRIES]; - float killnotify_actiontype[KN_MAX_ENTRIES]; // 0 = "Y [used by] X", 1 = "X [did action to] Y" - string killnotify_attackers[KN_MAX_ENTRIES]; - string killnotify_victims[KN_MAX_ENTRIES]; - void HUD_KillNotify_Push(string attacker, string victim, float actiontype, float wpn) - { - --kn_index; - if (kn_index == -1) - kn_index = KN_MAX_ENTRIES-1; - killnotify_times[kn_index] = time; - killnotify_deathtype[kn_index] = wpn; - killnotify_actiontype[kn_index] = actiontype; - if(killnotify_attackers[kn_index]) - strunzone(killnotify_attackers[kn_index]); - killnotify_attackers[kn_index] = strzone(attacker); - if(killnotify_victims[kn_index]) - strunzone(killnotify_victims[kn_index]); - killnotify_victims[kn_index] = strzone(victim); - } + // icon + if(notify_icon[kn_index]) { strunzone(notify_icon[kn_index]); } + notify_icon[kn_index] = strzone(icon); - void HUD_KillNotify(string s1, string s2, string s3, float type, float msg) // s1 = attacker, s2 = victim - { - float w; - float alsoprint, gentle; - alsoprint = (autocvar_hud_panel_notify_print || !panel_enabled); // print message to console if: notify panel disabled, or cvar to do so enabled - gentle = (autocvar_cl_gentle || autocvar_cl_gentle_messages); - - if ((msg == MSG_SUICIDE || msg == MSG_KILL || msg == MSG_KILL_ACTION) && gametype == MAPINFO_TYPE_CTS) // selfkill isn't interesting in CTS and only spams up the notify panel - return; + // attacker + if(notify_attackers[kn_index]) { strunzone(notify_attackers[kn_index]); } + notify_attackers[kn_index] = strzone(attacker); - if(msg == MSG_SUICIDE) { - w = DEATH_WEAPONOF(type); - if(WEP_VALID(w)) { - HUD_KillNotify_Push(s1, "", 0, DEATH_GENERIC); - if (alsoprint) - print("^1", sprintf(Weapon_SuicideMessage(type), strcat(s1, "^1")), "\n"); - } else if (type == DEATH_KILL) { - HUD_KillNotify_Push(s1, "", 0, DEATH_KILL); - if (alsoprint) - print (sprintf(_("^1%s^1 couldn't take it anymore\n"), s1)); - } else if (type == DEATH_ROT) { - HUD_KillNotify_Push(s1, "", 0, DEATH_GENERIC); - if (alsoprint) - print (sprintf(_("^1%s^1 died\n"), s1)); - } else if (type == DEATH_NOAMMO) { - HUD_KillNotify_Push(s1, "", 0, DEATH_NOAMMO); - if (alsoprint) - print (sprintf(_("^7%s^7 committed suicide. What's the point of living without ammo?\n"), s1)); - } else if (type == DEATH_CAMP) { - HUD_KillNotify_Push(s1, "", 0, DEATH_CAMP); - if (alsoprint) - print (sprintf(_("^1%s^1 thought they found a nice camping ground\n"), s1)); - } else if (type == KILL_TEAM_RED || type == KILL_TEAM_BLUE) { - HUD_KillNotify_Push(s1, "", 0, type); - if (alsoprint) - print (sprintf(_("^1%s^1 didn't become friends with the Lord of Teamplay\n"), s1)); - } else if (type == DEATH_CHEAT) { - HUD_KillNotify_Push(s1, "", 0, DEATH_GENERIC); - if (alsoprint) - print (sprintf(_("^1%s^1 unfairly eliminated themself\n"), s1)); - } else if (type == DEATH_FIRE) { - HUD_KillNotify_Push(s1, "", 0, DEATH_GENERIC); - if (alsoprint) - print (sprintf(_("^1%s^1 burned to death\n"), s1)); - } else if (type != DEATH_TEAMCHANGE && type != DEATH_QUIET) { - HUD_KillNotify_Push(s1, "", 0, DEATH_GENERIC); - if (alsoprint) - print (sprintf(_("^1%s^1 couldn't resist the urge to self-destruct\n"), s1)); - } - - if (stof(s2) > 2) // killcount > 2 - print (sprintf(_("^1%s^1 ended it all after a %d kill spree\n"), s1, stof(s2))); - } else if(msg == MSG_KILL) { - w = DEATH_WEAPONOF(type); - if(WEP_VALID(w)) { - HUD_KillNotify_Push(s1, s2, 1, type); - if (alsoprint) - print("^1", sprintf(Weapon_KillMessage(type), strcat(s2, "^1"), strcat(s1, "^1")), "\n"); // default order: victim, killer - } - else if(type == KILL_TEAM_RED || type == KILL_TEAM_BLUE || type == KILL_TEAM_SPREE) { - HUD_KillNotify_Push(s1, s2, 1, type); - if(alsoprint) - { - if(gentle) { - print (sprintf(_("^1%s^1 took action against a team mate\n"), s1)); - } else { - print (sprintf(_("^1%s^1 mows down a team mate\n"), s1)); - } - } - if (stof(s2) > 2 && type == KILL_TEAM_SPREE) { - if(gentle) - print (sprintf(_("^1%s^1 ended a %d scoring spree by going against a team mate\n"), s1, stof(s3))); - else - print (sprintf(_("^1%s^1 ended a %d kill spree by killing a team mate\n"), s1, stof(s3))); - } - else if (stof(s2) > 2) { - if(gentle) - print (sprintf(_("^1%s^1's %s scoring spree was ended by a team mate!\n"), s1, stof(s3))); - else - print (sprintf(_("^1%s^1's %s kill spree was ended by a team mate!\n"), s1, stof(s3))); - } - } - else if(type == KILL_FIRST_BLOOD) - print(sprintf(_("^1%s^1 drew first blood\n"), s1)); - else if (type == DEATH_TELEFRAG) { - HUD_KillNotify_Push(s1, s2, 1, DEATH_TELEFRAG); - if(gentle) - print (sprintf(_("^1%s^1 tried to occupy %s^1's teleport destination space\n"), s2, s1)); - else - print (sprintf(_("^1%s^1 was telefragged by %s\n"), s2, s1)); - } - else if (type == DEATH_DROWN) { - HUD_KillNotify_Push(s1, s2, 1, DEATH_DROWN); - if(alsoprint) - print (sprintf(_("^1%s^1 was drowned by %s\n"), s2, s1)); - } - else if (type == DEATH_SLIME) { - HUD_KillNotify_Push(s1, s2, 1, DEATH_SLIME); - if(alsoprint) - print (sprintf(_("^1%s^1 was slimed by %s\n"), s2, s1)); - } - else if (type == DEATH_LAVA) { - HUD_KillNotify_Push(s1, s2, 1, DEATH_LAVA); - if(alsoprint) - print (sprintf(_("^1%s^1 was cooked by %s\n"), s2, s1)); - } - else if (type == DEATH_FALL) { - HUD_KillNotify_Push(s1, s2, 1, DEATH_FALL); - if(alsoprint) - print (sprintf(_("^1%s^1 was grounded by %s\n"), s2, s1)); - } - else if (type == DEATH_SHOOTING_STAR) { - HUD_KillNotify_Push(s1, s2, 1, DEATH_SHOOTING_STAR); - if(alsoprint) - print (sprintf(_("^1%s^1 was shot into space by %s\n"), s2, s1)); - } - else if (type == DEATH_SWAMP) { - HUD_KillNotify_Push(s1, s2, 1, DEATH_GENERIC); - if(alsoprint) - print (sprintf(_("^1%s^1 was conserved by %s\n"), s2, s1)); - } - else if (type == DEATH_HURTTRIGGER) - { - HUD_KillNotify_Push(s1, s2, 1, DEATH_HURTTRIGGER); - if(alsoprint) - print(sprintf(_("^1%s^1 was thrown into a world of hurt by %s\n"), s2, s1)); - } else if(type == DEATH_VHCRUSH) { - HUD_KillNotify_Push(s1, s2, 1, DEATH_GENERIC); - if(alsoprint) - print (sprintf(_("^1%s^1 was crushed by %s\n"), s2, s1)); - } else if(type == DEATH_SBMINIGUN) { - HUD_KillNotify_Push(s1, s2, 1, DEATH_GENERIC); - if(alsoprint) - print (sprintf(_("^1%s^1 got shredded by %s\n"), s2, s1)); - } else if(type == DEATH_SBROCKET) { - HUD_KillNotify_Push(s1, s2, 1, DEATH_GENERIC); - if(alsoprint) - print (sprintf(_("^1%s^1 was blasted to bits by %s\n"), s2, s1)); - } else if(type == DEATH_SBBLOWUP) { - HUD_KillNotify_Push(s1, s2, 1, DEATH_GENERIC); - if(alsoprint) - print (sprintf(_("^1%s^1 got caught in the blast when %s^1's destroys a vehicle\n"), s2, s1)); - } else if(type == DEATH_WAKIGUN) { - HUD_KillNotify_Push(s1, s2, 1, DEATH_GENERIC); - if(alsoprint) - print (sprintf(_("^1%s^1 was bolted down by %s\n"), s2, s1)); - } else if(type == DEATH_BUMB_GUN) { - HUD_KillNotify_Push(s1, s2, 1, DEATH_GENERIC); - if(alsoprint) - print (sprintf(_("^1%s^1 saw %s's preddy lights.\n"), s2, s1)); - } else if(type == DEATH_WAKIROCKET) { - HUD_KillNotify_Push(s1, s2, 1, DEATH_GENERIC); - if(alsoprint) - print (sprintf(_("^1%s^1 could find no shelter from %s^1's rockets\n"), s2, s1)); - } else if(type == DEATH_WAKIBLOWUP) { - HUD_KillNotify_Push(s1, s2, 1, DEATH_GENERIC); - if(alsoprint) - print (sprintf(_("^1%s^1 got caught in the blast when %s^1's destroys a vehicle\n"), s2, s1)); - } else if(type == DEATH_RAPTOR_CANNON) { - HUD_KillNotify_Push(s1, s2, 1, DEATH_GENERIC); - if(alsoprint) - print (sprintf(_("^1%s^1 nailed to hell by %s\n"), s2, s1)); - } else if(type == DEATH_RAPTOR_BOMB) { - HUD_KillNotify_Push(s1, s2, 1, DEATH_GENERIC); - if(alsoprint) - print (sprintf(_("^1%s^1 cluster crushed by %s\n"), s2, s1)); - } else if(type == DEATH_RAPTOR_DEATH) { - HUD_KillNotify_Push(s1, s2, 1, DEATH_GENERIC); - if(alsoprint) - print (sprintf(_("^1%s^1 got caught in the blast when %s^1's destroys a vehicle\n"), s2, s1)); - } else if(type == DEATH_TURRET) { - HUD_KillNotify_Push(s1, s2, 1, DEATH_GENERIC); - if(alsoprint) - print (sprintf(_("^1%s^1 was pushed into the line of fire by %s\n"), s2, s1)); - } else if(type == DEATH_TOUCHEXPLODE) { - HUD_KillNotify_Push(s1, s2, 1, DEATH_GENERIC); - if(alsoprint) - print (sprintf(_("^1%s^1 was pushed into an accident by %s\n"), s2, s1)); - } else if(type == DEATH_CHEAT) { - HUD_KillNotify_Push(s1, s2, 1, DEATH_GENERIC); - if(alsoprint) - print (sprintf(_("^1%s^1 was unfairly eliminated by %s\n"), s2, s1)); - } else if (type == DEATH_FIRE) { - HUD_KillNotify_Push(s1, s2, 1, DEATH_GENERIC); - if(alsoprint) - print (sprintf(_("^1%s^1 was burnt to death by %s\n"), s2, s1)); - } else if (type == DEATH_CUSTOM) { - HUD_KillNotify_Push(s1, s2, 1, DEATH_CUSTOM); - if(alsoprint) - print("^1", sprintf(s3, strcat(s2, "^1"), strcat(s1, "^1")), "\n"); - } else if (type == DEATH_HURTTRIGGER) { - HUD_KillNotify_Push(s1, s2, 1, DEATH_HURTTRIGGER); - if(alsoprint) - print("^1", sprintf(s3, strcat(s2, "^1"), strcat(s1, "^1")), "\n"); - } else { - HUD_KillNotify_Push(s1, s2, 1, DEATH_GENERIC); - if(alsoprint) - print (sprintf(_("^1%s^1 was fragged by %s\n"), s2, s1)); - } - } else if(msg == MSG_SPREE) { - if(type == KILL_END_SPREE) { - if(gentle) - print (sprintf(_("^1%s^1's %s scoring spree was ended by %s\n"), s1, s2, s3)); - else - print (sprintf(_("^1%s^1's %s kill spree was ended by %s\n"), s1, s2, s3)); - } else if(type == KILL_SPREE) { - if(gentle) - print (sprintf(_("^1%s^1 made %s scores in a row\n"), s1, s2)); - else - print (sprintf(_("^1%s^1 has %s frags in a row\n"), s1, s2)); - } else if(type == KILL_SPREE_3) { - if(gentle) - print (sprintf(_("%s^7 made a ^1TRIPLE SCORE\n"), s1)); - else - print (sprintf(_("%s^7 made a ^1TRIPLE FRAG\n"), s1)); - } else if(type == KILL_SPREE_5) { - if(gentle) - print (sprintf(_("%s^7 unleashes ^1SCORING RAGE\n"), s1)); - else - print (sprintf(_("%s^7 unleashes ^1RAGE\n"), s1)); - } else if(type == KILL_SPREE_10) { - if(gentle) - print (sprintf(_("%s^7 made ^1TEN SCORES IN A ROW!\n"), s1)); - else - print (sprintf(_("%s^7 starts the ^1MASSACRE!\n"), s1)); - } else if(type == KILL_SPREE_15) { - if(gentle) - print (sprintf(_("%s^7 made ^1FIFTEEN SCORES IN A ROW!\n"), s1)); - else - print (sprintf(_("%s^7 executes ^1MAYHEM!\n"), s1)); - } else if(type == KILL_SPREE_20) { - if(gentle) - print (sprintf(_("%s^7 made ^1TWENTY SCORES IN A ROW!\n"), s1)); - else - print (sprintf(_("%s^7 is a ^1BERSERKER!\n"), s1)); - } else if(type == KILL_SPREE_25) { - if(gentle) - print (sprintf(_("%s^7 made ^1TWENTY FIVE SCORES IN A ROW!\n"), s1)); - else - print (sprintf(_("%s^7 inflicts ^1CARNAGE!\n"), s1)); - } else if(type == KILL_SPREE_30) { - if(gentle) - print (sprintf(_("%s^7 made ^1THIRTY SCORES IN A ROW!\n"), s1)); - else - print (sprintf(_("%s^7 unleashes ^1ARMAGEDDON!\n"), s1)); - } - } else if(msg == MSG_KILL_ACTION) { // wtf is this? isnt it basically the same as MSG_SUICIDE? - if (type == DEATH_DROWN) { - HUD_KillNotify_Push(s1, "", 0, DEATH_DROWN); - if(alsoprint) - { - if(gentle) - print (sprintf(_("^1%s^1 was in the water for too long\n"), s1)); - else - print (sprintf(_("^1%s^1 drowned\n"), s1)); - } - } else if (type == DEATH_SLIME) { - HUD_KillNotify_Push(s1, "", 0, DEATH_SLIME); - if(alsoprint) - print (sprintf(_("^1%s^1 was slimed\n"), s1)); - } else if (type == DEATH_LAVA) { - HUD_KillNotify_Push(s1, "", 0, DEATH_LAVA); - if(alsoprint) - { - if(gentle) - print (sprintf(_("^1%s^1 found a hot place\n"), s1)); - else - print (sprintf(_("^1%s^1 turned into hot slag\n"), s1)); - } - } else if (type == DEATH_FALL) { - HUD_KillNotify_Push(s1, "", 0, DEATH_GENERIC); - if(alsoprint) - { - if(gentle) - print (sprintf(_("^1%s^1 tested gravity (and it worked)\n"), s1)); - else - print (sprintf(_("^1%s^1 hit the ground with a crunch\n"), s1)); - } - } else if (type == DEATH_SHOOTING_STAR) { - HUD_KillNotify_Push(s1, "", 0, DEATH_SHOOTING_STAR); - if(alsoprint) - print (sprintf(_("^1%s^1 became a shooting star\n"), s1)); - } else if (type == DEATH_SWAMP) { - HUD_KillNotify_Push(s1, "", 0, DEATH_GENERIC); - if(alsoprint) - { - if(gentle) - print (sprintf(_("^1%s^1 discovered a swamp\n"), s1)); - else - print (sprintf(_("^1%s^1 is now conserved for centuries to come\n"), s1)); - } - } else if(DEATH_ISTURRET(type)) { - HUD_KillNotify_Push(s1, "", 0, DEATH_GENERIC); - if(alsoprint) - { - if(gentle) - print (sprintf(_("^1%s^1 ran into a turret\n"), s1)); - else - { - switch(type) - { - case DEATH_TURRET_EWHEEL: - print (sprintf(_("^1%s^1 was laserd down by a eWheel turret \n"), s1)); - break; - case DEATH_TURRET_FLAC: - print (sprintf(_("^1%s^1 got caught in the flac \n"), s1)); - break; - case DEATH_TURRET_MACHINEGUN: - print (sprintf(_("^1%s^1 was riddeld full of riddled by a machinegun turret \n"), s1)); - break; - case DEATH_TURRET_WALKER_GUN: - print (sprintf(_("^1%s^1 got served a led enrichment by a walker turret \n"), s1)); - break; - case DEATH_TURRET_WALKER_MEELE: - print (sprintf(_("^1%s^1 was impaled by a walker turret \n"), s1)); - break; - case DEATH_TURRET_WALKER_ROCKET: - print (sprintf(_("^1%s^1 was rocketed to hell by a walker turret \n"), s1)); - break; - case DEATH_TURRET_HELLION: - print (sprintf(_("^1%s^1 was blasted away hellion turret \n"), s1)); - break; - case DEATH_TURRET_HK: - print (sprintf(_("^1%s^1 could not hide from the hunter turret \n"), s1)); - break; - case DEATH_TURRET_MLRS: - print (sprintf(_("^1%s^1 got turned into smoldering gibs by a mlrs turret \n"), s1)); - break; - case DEATH_TURRET_PLASMA: - print (sprintf(_("^1%s^1 got served some superheated plasma from a plasma turret \n"), s1)); - break; - case DEATH_TURRET_PHASER: - print (sprintf(_("^1%s^1 was phased out \n"), s1)); - break; - case DEATH_TURRET_TESLA: - print (sprintf(_("^1%s^1 was electrocuted by a tesla turret \n"), s1)); - break; - } - } - } - } else if(DEATH_ISMONSTER(type)) { ++ if(msg == MSG_KILL_ACTION) { // wtf is this? isnt it basically the same as MSG_SUICIDE? ++ if(DEATH_ISMONSTER(type)) { + HUD_KillNotify_Push(s1, "", 0, DEATH_GENERIC); + if(alsoprint) + { + if(gentle) + print (sprintf(_("^1%s^1 hit a monster, and the monster hit back\n"), s1)); + else + { + switch(type) + { + case DEATH_MONSTER_DEMON_MELEE: + print (sprintf(_("^1%s^1 was eviscerated by a Fiend \n"), s1)); + break; + case DEATH_MONSTER_DEMON_JUMP: + print (sprintf(_("^1%s^1 didn't see the Fiend pouncing at them \n"), s1)); + break; + case DEATH_MONSTER_SHAMBLER_MELEE: + print (sprintf(_("^1%s^1 was smashed by a Shambler \n"), s1)); + break; + case DEATH_MONSTER_SHAMBLER_CLAW: + print (sprintf(_("^1%s^1's insides were ripped out by a Shambler \n"), s1)); + break; + case DEATH_MONSTER_SHAMBLER_LIGHTNING: + print (sprintf(_("^1%s^1 was zapped to death by a Shambler \n"), s1)); + break; + case DEATH_MONSTER_SOLDIER_NAIL: + print (sprintf(_("^1%s^1 was riddled full of holes by a Soldier \n"), s1)); + break; + case DEATH_MONSTER_ENFORCER_NAIL: + print (sprintf(_("^1%s^1 was riddled full of holes by an Enforcer \n"), s1)); + break; + case DEATH_MONSTER_DOG_BITE: + print (sprintf(_("^1%s^1 was mauled by a Rottweiler \n"), s1)); + break; + case DEATH_MONSTER_DOG_JUMP: + print (sprintf(_("^1%s^1 didn't see the pouncing Rottweiler \n"), s1)); + break; + case DEATH_MONSTER_TARBABY_BLOWUP: + print (sprintf(_("^1%s^1 was slimed by a Spawn \n"), s1)); + break; + case DEATH_MONSTER_FISH_BITE: + print (sprintf(_("^1%s^1 was fed to the Rotfish \n"), s1)); + break; + case DEATH_MONSTER_HELLFISH_BITE: + print (sprintf(_("^1%s^1 was eaten alive by a Hellfish \n"), s1)); + break; + case DEATH_MONSTER_SHALRATH_MELEE: + print (sprintf(_("^1%s^1 was exploded by a Vore \n"), s1)); + break; + case DEATH_MONSTER_OGRE_CHAINSAW: + print (sprintf(_("^1%s^1 was destroyed by an Ogre \n"), s1)); + break; + case DEATH_MONSTER_OGRE_NAIL: + print (sprintf(_("^1%s^1 was riddled full of holes by an Ogre \n"), s1)); + break; + case DEATH_MONSTER_ZOMBIE: + print (sprintf(_("^1%s^1's brains were eaten by a Zombie \n"), s1)); + break; + case DEATH_MONSTER_HELLKNIGHT_FIREBALL: + print (sprintf(_("^1%s^1 was exploded by a Hell-Knight's fireball \n"), s1)); + case DEATH_MONSTER_MELEE: + print (sprintf(_("^1%s^1 was killed by a monster \n"), s1)); + break; + } + } + } - } - else if (type == DEATH_CUSTOM) { - HUD_KillNotify_Push(s1, "", 0, DEATH_CUSTOM); - if(alsoprint) - print("^1", sprintf(s2, strcat(s1, "^1")), "\n"); - } else if (type == DEATH_HURTTRIGGER) { - HUD_KillNotify_Push(s1, "", 0, DEATH_HURTTRIGGER); - if(alsoprint) - print("^1", sprintf(s2, strcat(s1, "^1")), "\n"); - } else if(type == DEATH_TOUCHEXPLODE) { - HUD_KillNotify_Push(s1, "", 0, DEATH_GENERIC); - if(alsoprint) - print (sprintf(_("^1%s^1 died in an accident\n"), s1)); - } else if(type == DEATH_CHEAT) { - HUD_KillNotify_Push(s1, "", 0, DEATH_GENERIC); - if(alsoprint) - print (sprintf(_("^1%s^1 was unfairly eliminated\n"), s1)); - } else if(type == DEATH_FIRE) { - HUD_KillNotify_Push(s1, "", 0, DEATH_GENERIC); - if(alsoprint) - { - if(gentle) - print (sprintf(_("^1%s^1 felt a little hot\n"), s1)); - else - print (sprintf(_("^1%s^1 burnt to death\n"), s1)); - } - } else { - HUD_KillNotify_Push(s1, "", 0, DEATH_GENERIC); - if(alsoprint) - { - if(gentle) - print (sprintf(_("^1%s^1 needs a restart\n"), s1)); - else - print (sprintf(_("^1%s^1 died\n"), s1)); - } - } - } else if(msg == MSG_KILL_ACTION_SPREE) { - if(gentle) - print (sprintf(_("^1%s^1 needs a restart after a %d scoring spree\n"), s1, stof(s2))); - else - print (sprintf(_("^1%s^1 died with a %d kill spree\n"), s1, stof(s2))); - } else if(msg == MSG_INFO) { - if(type == INFO_GOTFLAG) { // here, s2 is the flag name - HUD_KillNotify_Push(s1, s2, 0, INFO_GOTFLAG); - print(sprintf(_("%s^7 got the %s\n"), s1, s2)); - } else if(type == INFO_LOSTFLAG) { - HUD_KillNotify_Push(s1, s2, 0, INFO_LOSTFLAG); - print(sprintf(_("%s^7 lost the %s\n"), s1, s2)); - } else if(type == INFO_PICKUPFLAG) { - HUD_KillNotify_Push(s1, s2, 0, INFO_GOTFLAG); - print(sprintf(_("%s^7 picked up the %s\n"), s1, s2)); - } else if(type == INFO_RETURNFLAG) { - HUD_KillNotify_Push(s1, s2, 0, INFO_RETURNFLAG); - print(sprintf(_("%s^7 returned the %s\n"), s1, s2)); - } else if(type == INFO_CAPTUREFLAG) { - HUD_KillNotify_Push(s1, s2, 0, INFO_CAPTUREFLAG); - print(sprintf(_("%s^7 captured the %s%s\n"), s1, s2, s3)); - } - } else if(msg == MSG_RACE) { - if(type == RACE_SERVER_RECORD) { - HUD_KillNotify_Push(s1, s2, 1, RACE_SERVER_RECORD); - } - else if(type == RACE_NEW_RANK) { - HUD_KillNotify_Push(s1, s2, 1, RACE_NEW_RANK); - } - else if(type == RACE_NEW_TIME) { - HUD_KillNotify_Push(s1, s2, 1, RACE_NEW_TIME); - } - else if(type == RACE_FAIL) { - HUD_KillNotify_Push(s1, s2, 1, RACE_FAIL); - } - } else if(msg == MSG_KA) { - if(type == KA_PICKUPBALL) { - HUD_KillNotify_Push(s1, s2, 0, KA_PICKUPBALL); - if(alsoprint) - print (sprintf(_("%s^7 has picked up the ball!\n"), s1)); - } - else if(type == KA_DROPBALL) { - HUD_KillNotify_Push(s1, s2, 0, KA_DROPBALL); - if(alsoprint) - print(sprintf(_("%s^7 has dropped the ball!\n"), s1)); - } - } - } - - void HUD_KillCenterprint(string s1, string s2, float type, float msg) - { - float gentle; - gentle = (autocvar_cl_gentle || autocvar_cl_gentle_messages); - if(msg == MSG_SUICIDE) { - if (type == DEATH_TEAMCHANGE) { - centerprint_hud(sprintf(_("You are now on: %s"), s1)); - } else if (type == DEATH_AUTOTEAMCHANGE) { - centerprint_hud(sprintf(_("You have been moved into a different team to improve team balance\nYou are now on: %s"), s1)); - } else if (type == DEATH_CAMP) { - if(gentle) - centerprint_hud(_("^1Reconsider your tactics, camper!")); - else - centerprint_hud(_("^1Die camper!")); - } else if (type == DEATH_NOAMMO) { - if(gentle) - centerprint_hud(_("^1You are reinserted into the game for running out of ammo...")); - else - centerprint_hud(_("^1You were killed for running out of ammo...")); - } else if (type == DEATH_ROT) { - if(gentle) - centerprint_hud(_("^1You need to preserve your health")); - else - centerprint_hud(_("^1You grew too old without taking your medicine")); - } else if (type == KILL_TEAM_RED || type == KILL_TEAM_BLUE) { - if(gentle) - centerprint_hud(_("^1Don't go against team mates!")); - else - centerprint_hud(_("^1Don't shoot your team mates!")); - } else if (type == DEATH_QUIET) { - // do nothing - } else { // generic message - if(gentle) - centerprint_hud(_("^1You need to be more careful!")); - else - centerprint_hud(_("^1You killed your own dumb self!")); - } - } else if(msg == MSG_KILL) { - if (type == KILL_TEAM_RED || type == KILL_TEAM_BLUE) { - if(gentle) { - centerprint_hud(sprintf(_("^1Moron! You went against ^7%s^1, a team mate!"), s1)); - } else { - centerprint_hud(sprintf(_("^1Moron! You fragged ^7%s^1, a team mate!"), s1)); - } - } else if (type == KILL_FIRST_BLOOD) { - if(gentle) { - centerprint_hud(_("^1First score")); - } else { - centerprint_hud(_("^1First blood")); - } - } else if (type == KILL_FIRST_VICTIM) { - if(gentle) { - centerprint_hud(_("^1First casualty")); - } else { - centerprint_hud(_("^1First victim")); - } - } else if (type == KILL_TYPEFRAG) { // s2 contains "advanced kill messages" such as ping, handicap... - if(gentle) { - centerprint_hud(strcat(sprintf(_("^1You scored against ^7%s^1 who was typing!"), s1), s2)); - } else { - centerprint_hud(strcat(sprintf(_("^1You typefragged ^7%s"), s1), s2)); - } - } else if (type == KILL_TYPEFRAGGED) { - if(gentle) { - centerprint_hud(strcat(sprintf(_("^1You were scored against by ^7%s^1 while you were typing!"), s1), s2)); - } else { - centerprint_hud(strcat(sprintf(_("^1You were typefragged by ^7%s"), s1), s2)); - } - } else if (type == KILL_FRAG) { - if(gentle) { - centerprint_hud(strcat(sprintf(_("^4You scored against ^7%s"), s1), s2)); - } else { - centerprint_hud(strcat(sprintf(_("^4You fragged ^7%s"), s1), s2)); - } - } else { // generic message - if(gentle) { - centerprint_hud(strcat(sprintf(_("^1You were scored against by ^7%s"), s1), s2)); - } else { - centerprint_hud(strcat(sprintf(_("^1You were fragged by ^7%s"), s1), s2)); - } ++ } + } - } else if(msg == MSG_KILL_ACTION) { - // TODO: invent more centerprints here? - centerprint_hud(_("^1Watch your step!")); + // victim + if(notify_victims[kn_index]) { strunzone(notify_victims[kn_index]); } + notify_victims[kn_index] = strzone(victim); } } diff --cc qcsrc/common/constants.qh index b908bacec,c25fb059f..146d2905d --- a/qcsrc/common/constants.qh +++ b/qcsrc/common/constants.qh @@@ -372,108 -362,6 +370,31 @@@ float SPECIES_ROBOT_RUSTY = 4 float SPECIES_ROBOT_SHINY = 5; float SPECIES_RESERVED = 15; - // Deathtypes (weapon deathtypes are the IT_* constants below) - // NOTE: when adding death types, please add an explanation to Docs/spamlog.txt too. - float DEATH_SPECIAL_START = 10000; - float DEATH_FALL = 10000; - float DEATH_TELEFRAG = 10001; - float DEATH_DROWN = 10002; - float DEATH_HURTTRIGGER = 10003; - float DEATH_LAVA = 10004; - float DEATH_SLIME = 10005; - float DEATH_KILL = 10006; - float DEATH_NOAMMO = 10007; - float DEATH_SWAMP = 10008; - float DEATH_TEAMCHANGE = 10009; - float DEATH_AUTOTEAMCHANGE = 10010; - float DEATH_CAMP = 10011; - float DEATH_SHOOTING_STAR = 10012; - float DEATH_ROT = 10013; - float DEATH_MIRRORDAMAGE = 10014; - float DEATH_TOUCHEXPLODE = 10015; - float DEATH_CHEAT = 10016; - float DEATH_FIRE = 10017; - float DEATH_QUIET = 10021; - - float DEATH_VHFIRST = 10030; - float DEATH_VHCRUSH = 10030; - float DEATH_SBMINIGUN = 10031; - float DEATH_SBROCKET = 10032; - float DEATH_SBBLOWUP = 10033; - float DEATH_WAKIGUN = 10034; - float DEATH_WAKIROCKET = 10035; - float DEATH_WAKIBLOWUP = 10036; - float DEATH_RAPTOR_CANNON = 10037; - float DEATH_RAPTOR_BOMB = 10038; - float DEATH_RAPTOR_BOMB_SPLIT = 10039; - float DEATH_RAPTOR_DEATH = 10040; - float DEATH_BUMB_GUN = 10041; - float DEATH_BUMB_RAY = 10042; - float DEATH_BUMB_RAY_HEAL = 10043; - float DEATH_BUMB_DEATH = 10044; - float DEATH_VHLAST = 10044; - #define DEATH_ISVEHICLE(t) ((t) >= DEATH_VHFIRST && (t) <= DEATH_VHLAST) - - float DEATH_GENERIC = 10050; - - float DEATH_WEAPON = 10100; - - float DEATH_CUSTOM = 10300; - - float DEATH_TURRET = 10500; - float DEATH_TURRET_EWHEEL = 10501; - float DEATH_TURRET_FLAC = 10502; - float DEATH_TURRET_MACHINEGUN = 10503; - float DEATH_TURRET_WALKER_GUN = 10504; - float DEATH_TURRET_WALKER_MEELE = 10505; - float DEATH_TURRET_WALKER_ROCKET = 10506; - float DEATH_TURRET_HELLION = 10507; - float DEATH_TURRET_HK = 10508; - float DEATH_TURRET_MLRS = 10509; - float DEATH_TURRET_PLASMA = 10510; - float DEATH_TURRET_PHASER = 10511; - float DEATH_TURRET_TESLA = 10512; - float DEATH_TURRET_LAST = 10512; - +// Monster death types +float DEATH_MONSTER = 10513; +float DEATH_MONSTER_DEMON_MELEE = 10514; +float DEATH_MONSTER_DEMON_JUMP = 10515; +float DEATH_MONSTER_SHAMBLER_MELEE = 10516; +float DEATH_MONSTER_SHAMBLER_CLAW = 10517; +float DEATH_MONSTER_SHAMBLER_LIGHTNING = 10518; +float DEATH_MONSTER_SOLDIER_NAIL = 10519; +float DEATH_MONSTER_ENFORCER_NAIL = 10520; +float DEATH_MONSTER_DOG_BITE = 10521; +float DEATH_MONSTER_DOG_JUMP = 10522; +float DEATH_MONSTER_TARBABY_BLOWUP = 10523; +float DEATH_MONSTER_FISH_BITE = 10524; +float DEATH_MONSTER_HELLFISH_BITE = 10525; +float DEATH_MONSTER_SHALRATH_MELEE = 10526; +float DEATH_MONSTER_OGRE_CHAINSAW = 10527; +float DEATH_MONSTER_OGRE_NAIL = 10528; +float DEATH_MONSTER_MELEE = 10529; +float DEATH_MONSTER_ZOMBIE = 10530; +float DEATH_MONSTER_HELLKNIGHT_FIREBALL = 10531; +float DEATH_MONSTER_LAST = 10532; + - float DEATH_WEAPONMASK = 0xFF; - float DEATH_HITTYPEMASK = 0x1F00; // which is WAY below 10000 used for normal deaths - float HITTYPE_SECONDARY = 0x100; - float HITTYPE_SPLASH = 0x200; // automatically set by RadiusDamage - float HITTYPE_BOUNCE = 0x400; - float HITTYPE_RESERVED2 = 0x800; - float HITTYPE_RESERVED = 0x1000; // unused yet - - // macros to access these - #define DEATH_ISTURRET(t) ((t) >= DEATH_TURRET && (t) <= DEATH_TURRET_LAST) - #define DEATH_ISSPECIAL(t) ((t) >= DEATH_SPECIAL_START) - #define DEATH_WEAPONOFWEAPONDEATH(t) ((t) & DEATH_WEAPONMASK) - #define DEATH_ISWEAPON(t,w) (!DEATH_ISSPECIAL(t) && DEATH_WEAPONOFWEAPONDEATH(t) == (w)) - #define DEATH_WEAPONOF(t) (DEATH_ISSPECIAL(t) ? 0 : DEATH_WEAPONOFWEAPONDEATH(t)) - #define WEP_VALID(w) ((w) >= WEP_FIRST && (w) <= WEP_LAST) ++// macros to access this - will be fixed soon +#define DEATH_ISMONSTER(t) ((t) >= DEATH_MONSTER && (t) <= DEATH_MONSTER_LAST) + #define FRAGS_PLAYER 0 #define FRAGS_SPECTATOR -666 #define FRAGS_LMS_LOSER -616 diff --cc qcsrc/server/g_damage.qc index efa6c0ad5,e86b148bc..827518f44 --- a/qcsrc/server/g_damage.qc +++ b/qcsrc/server/g_damage.qc @@@ -394,191 -486,92 +486,153 @@@ void Obituary(entity attacker, entity i } else { - if (!checkrules_firstblood) - { - checkrules_firstblood = TRUE; - Send_KillNotification(a, "", "", KILL_FIRST_BLOOD, MSG_KILL); - // TODO: make these print a newline if they dont - Send_CSQC_KillCenterprint(attacker, "", "", KILL_FIRST_BLOOD, MSG_KILL); - Send_CSQC_KillCenterprint(targ, "", "", KILL_FIRST_VICTIM, MSG_KILL); - PlayerStats_Event(attacker, PLAYERSTATS_ACHIEVEMENT_FIRSTBLOOD, 1); - PlayerStats_Event(targ, PLAYERSTATS_ACHIEVEMENT_FIRSTVICTIM, 1); - } - - if(targ.istypefrag) { - Send_CSQC_KillCenterprint(attacker, s, Obituary_ExtraFragInfo(targ), KILL_TYPEFRAG, MSG_KILL); - Send_CSQC_KillCenterprint(targ, a, Obituary_ExtraFragInfo(attacker), KILL_TYPEFRAGGED, MSG_KILL); - } else { - Send_CSQC_KillCenterprint(attacker, s, Obituary_ExtraFragInfo(targ), KILL_FRAG, MSG_KILL); - Send_CSQC_KillCenterprint(targ, a, Obituary_ExtraFragInfo(attacker), KILL_FRAGGED, MSG_KILL); - } - - attacker.taunt_soundtime = time + 1; + kill_count_to_attacker = attacker.killcount; + kill_count_to_target = 0; + } - if (deathtype == DEATH_HURTTRIGGER && inflictor.message2 != "") - msg = inflictor.message2; - else if (deathtype == DEATH_CUSTOM) - msg = deathmessage; + float verbose_allowed = (autocvar_notification_server_allows_frag_verbose && ((autocvar_notification_server_allows_frag_verbose == 2) || inWarmupStage)); + if(targ.istypefrag) + { + if(attacker.FRAG_VERBOSE && verbose_allowed) + Send_Notification(NOTIF_ONE, attacker, MSG_CENTER, CENTER_DEATH_MURDER_TYPEFRAG_VERBOSE, targ.netname, kill_count_to_attacker, (IS_BOT_CLIENT(targ) ? NO_MSG : targ.ping)); else - msg = ""; - - if(strstrofs(msg, "%", 0) < 0) - msg = strcat("%s ", msg, " by %s"); + Send_Notification(NOTIF_ONE, attacker, MSG_CENTER, CENTER_DEATH_MURDER_TYPEFRAG, targ.netname, kill_count_to_attacker); - Send_KillNotification(a, s, msg, deathtype, MSG_KILL); + if(targ.FRAG_VERBOSE && verbose_allowed) + Send_Notification(NOTIF_ONE, targ, MSG_CENTER, CENTER_DEATH_MURDER_TYPEFRAGGED_VERBOSE, attacker.netname, kill_count_to_target, attacker.health, attacker.armorvalue, (IS_BOT_CLIENT(attacker) ? NO_MSG : attacker.ping)); + else + Send_Notification(NOTIF_ONE, targ, MSG_CENTER, CENTER_DEATH_MURDER_TYPEFRAGGED, attacker.netname, kill_count_to_target); + } + else + { + if(attacker.FRAG_VERBOSE && verbose_allowed) + Send_Notification(NOTIF_ONE, attacker, MSG_CENTER, CENTER_DEATH_MURDER_FRAG_VERBOSE, targ.netname, kill_count_to_attacker, (IS_BOT_CLIENT(targ) ? NO_MSG : targ.ping)); + else + Send_Notification(NOTIF_ONE, attacker, MSG_CENTER, CENTER_DEATH_MURDER_FRAG, targ.netname, kill_count_to_attacker); - GiveFrags(attacker, targ, 1, deathtype); + if(targ.FRAG_VERBOSE && verbose_allowed) + Send_Notification(NOTIF_ONE, targ, MSG_CENTER, CENTER_DEATH_MURDER_FRAGGED_VERBOSE, attacker.netname, kill_count_to_target, attacker.health, attacker.armorvalue, (IS_BOT_CLIENT(attacker) ? NO_MSG : attacker.ping)); + else + Send_Notification(NOTIF_ONE, targ, MSG_CENTER, CENTER_DEATH_MURDER_FRAGGED, attacker.netname, kill_count_to_target); + } - if (targ.killcount > 2) { - Send_KillNotification(s, ftos(targ.killcount), a, KILL_END_SPREE, MSG_SPREE); - } + if not(Obituary_WeaponDeath(targ, TRUE, deathtype, targ.netname, attacker.netname, deathlocation, targ.killcount, kill_count_to_attacker)) + Obituary_SpecialDeath(targ, TRUE, deathtype, targ.netname, attacker.netname, deathlocation, targ.killcount, kill_count_to_attacker, 0); + } + } - attacker.killcount = attacker.killcount + 1; + // ============= + // ACCIDENT/TRAP + // ============= + else + { + switch(deathtype) + { + // For now, we're just forcing HURTTRIGGER to behave as "DEATH_VOID" and giving it no special options... + // Later on you will only be able to make custom messages using DEATH_CUSTOM, + // and there will be a REAL DEATH_VOID implementation which mappers will use. + /*case DEATH_HURTTRIGGER: + { + s1 = targ.netname; + s2 = inflictor.message; + if(strstrofs(s2, "%", 0) < 0) { s2 = strcat("%s ", s2); } + break; + }*/ - if (attacker.killcount == 3) - { - Send_KillNotification(a, "", "", KILL_SPREE_3, MSG_SPREE); - AnnounceTo(attacker, "03kills"); - PlayerStats_Event(attacker, PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_3, 1); - } - else if (attacker.killcount == 5) - { - Send_KillNotification(a, "", "", KILL_SPREE_5, MSG_SPREE); - AnnounceTo(attacker, "05kills"); - PlayerStats_Event(attacker, PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_5, 1); - } - else if (attacker.killcount == 10) - { - Send_KillNotification(a, "", "", KILL_SPREE_10, MSG_SPREE); - AnnounceTo(attacker, "10kills"); - PlayerStats_Event(attacker, PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_10, 1); - } - else if (attacker.killcount == 15) - { - Send_KillNotification(a, "", "", KILL_SPREE_15, MSG_SPREE); - AnnounceTo(attacker, "15kills"); - PlayerStats_Event(attacker, PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_15, 1); - } - else if (attacker.killcount == 20) - { - Send_KillNotification(a, "", "", KILL_SPREE_20, MSG_SPREE); - AnnounceTo(attacker, "20kills"); - PlayerStats_Event(attacker, PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_20, 1); - } - else if (attacker.killcount == 25) - { - Send_KillNotification(a, "", "", KILL_SPREE_25, MSG_SPREE); - AnnounceTo(attacker, "25kills"); - PlayerStats_Event(attacker, PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_25, 1); - } - else if (attacker.killcount == 30) - { - Send_KillNotification(a, "", "", KILL_SPREE_30, MSG_SPREE); - AnnounceTo(attacker, "30kills"); - PlayerStats_Event(attacker, PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_30, 1); - } - else if (attacker.killcount > 2) { - Send_KillNotification(a, ftos(attacker.killcount), "", KILL_SPREE, MSG_SPREE); - } - LogDeath("frag", deathtype, attacker, targ); + case DEATH_CUSTOM: + { + Obituary_SpecialDeath(targ, FALSE, deathtype, + targ.netname, + ((strstrofs(deathmessage, "%", 0) < 0) ? strcat("%s ", deathmessage) : deathmessage), + deathlocation, + targ.killcount, + 0, + 0); + break; } - } - else - { - Send_CSQC_KillCenterprint(targ, "", "", deathtype, MSG_KILL_ACTION); - if (deathtype == DEATH_HURTTRIGGER && inflictor.message != "") - msg = inflictor.message; - else if (deathtype == DEATH_CUSTOM) - msg = deathmessage; - else - msg = ""; - if(strstrofs(msg, "%", 0) < 0) - msg = strcat("%s ", msg); - - GiveFrags(targ, targ, -1, deathtype); - if(PlayerScore_Add(targ, SP_SCORE, 0) == -5) { - AnnounceTo(targ, "botlike"); - PlayerStats_Event(attacker, PLAYERSTATS_ACHIEVEMENT_BOTLIKE, 1); + + default: + { + Obituary_SpecialDeath(targ, FALSE, deathtype, targ.netname, deathlocation, "", targ.killcount, 0, 0); + break; } - Send_KillNotification(s, msg, "", deathtype, MSG_KILL_ACTION); - - if (targ.killcount > 2) - Send_KillNotification(s, ftos(targ.killcount), "", 0, MSG_KILL_ACTION_SPREE); - - LogDeath("accident", deathtype, targ, targ); } - targ.death_origin = targ.origin; - if(targ != attacker) - targ.killer_origin = attacker.origin; + LogDeath("accident", deathtype, targ, targ); + GiveFrags(targ, targ, -1, deathtype); - // FIXME: this should go in PutClientInServer - if (targ.killcount) - targ.killcount = 0; + if(PlayerScore_Add(targ, SP_SCORE, 0) == -5) + { + AnnounceTo(targ, "botlike"); + PlayerStats_Event(attacker, PLAYERSTATS_ACHIEVEMENT_BOTLIKE, 1); + } } + + // reset target kill count + if(targ.killcount) { targ.killcount = 0; } } +void Ice_Think() +{ + if(self.owner.health < 1) + { + remove(self); + return; + } + setorigin(self, self.owner.origin - '0 0 16'); + self.nextthink = time; +} + +void Freeze (entity targ, float freeze_time) +{ + float monster = (targ.flags & FL_MONSTER); + float player = (targ.flags & FL_CLIENT); + + if(!player && !monster) // only specified entities can be freezed + return; + + if(targ.frozen || targ.freezetag_frozen) + return; + + targ.frozen = 1; + targ.revive_progress = 0; + targ.health = 1; + targ.revive_speed = freeze_time; + + entity ice; + ice = spawn(); + ice.owner = targ; + ice.classname = "ice"; + ice.scale = targ.scale; + ice.think = Ice_Think; + ice.nextthink = time; + ice.frame = floor(random() * 21); // ice model has 20 different looking frames + setmodel(ice, "models/ice/ice.md3"); + + entity oldself; + oldself = self; + self = ice; + Ice_Think(); + self = oldself; + + RemoveGrapplingHook(targ); +} + +void Unfreeze (entity targ) +{ + targ.frozen = 0; + targ.revive_progress = 0; + targ.health = ((targ.classname == STR_PLAYER) ? autocvar_g_balance_health_start : targ.max_health); + + // remove the ice block + entity ice; + for(ice = world; (ice = find(ice, classname, "ice")); ) if(ice.owner == targ) + { + remove(ice); + break; + } +} + // these are updated by each Damage call for use in button triggering and such entity damage_targ; entity damage_inflictor; diff --cc qcsrc/server/miscfunctions.qc index 20b383972,2b7384180..b3056e5b3 --- a/qcsrc/server/miscfunctions.qc +++ b/qcsrc/server/miscfunctions.qc @@@ -85,22 -83,23 +83,25 @@@ string STR_PLAYER = "player" string STR_SPECTATOR = "spectator"; string STR_OBSERVER = "observer"; - #if 0 - #define FOR_EACH_CLIENT(v) for(v = world; (v = findflags(v, flags, FL_CLIENT)) != world; ) - #define FOR_EACH_REALCLIENT(v) FOR_EACH_CLIENT(v) if(clienttype(v) == CLIENTTYPE_REAL) - #define FOR_EACH_PLAYER(v) for(v = world; (v = find(v, classname, STR_PLAYER)) != world; ) - #define FOR_EACH_REALPLAYER(v) FOR_EACH_PLAYER(v) if(clienttype(v) == CLIENTTYPE_REAL) - #else + #define IS_PLAYER(v) (v.classname == STR_PLAYER) + #define IS_SPEC(v) (v.classname == STR_SPECTATOR) + #define IS_OBSERVER(v) (v.classname == STR_OBSERVER) + #define IS_CLIENT(v) (v.flags & FL_CLIENT) + #define IS_BOT_CLIENT(v) (clienttype(v) == CLIENTTYPE_BOT) + #define IS_REAL_CLIENT(v) (clienttype(v) == CLIENTTYPE_REAL) + #define IS_NOT_A_CLIENT(v) (clienttype(v) == CLIENTTYPE_NOTACLIENT) + #define FOR_EACH_CLIENTSLOT(v) for(v = world; (v = nextent(v)) && (num_for_edict(v) <= maxclients); ) - #define FOR_EACH_CLIENT(v) FOR_EACH_CLIENTSLOT(v) if(v.flags & FL_CLIENT) - #define FOR_EACH_REALCLIENT(v) FOR_EACH_CLIENT(v) if(clienttype(v) == CLIENTTYPE_REAL) - #define FOR_EACH_PLAYER(v) FOR_EACH_CLIENT(v) if(v.classname == STR_PLAYER) - #define FOR_EACH_SPEC(v) FOR_EACH_CLIENT(v) if(v.classname != STR_PLAYER) - #define FOR_EACH_REALPLAYER(v) FOR_EACH_REALCLIENT(v) if(v.classname == STR_PLAYER) + #define FOR_EACH_CLIENT(v) FOR_EACH_CLIENTSLOT(v) if(IS_CLIENT(v)) + #define FOR_EACH_REALCLIENT(v) FOR_EACH_CLIENT(v) if(IS_REAL_CLIENT(v)) + + #define FOR_EACH_PLAYER(v) FOR_EACH_CLIENT(v) if(IS_PLAYER(v)) + #define FOR_EACH_SPEC(v) FOR_EACH_CLIENT(v) if not(IS_PLAYER(v)) // Samual: shouldn't this be IS_SPEC(v)? and rather create a separate macro to include observers too + #define FOR_EACH_REALPLAYER(v) FOR_EACH_REALCLIENT(v) if(IS_PLAYER(v)) + +#define FOR_EACH_MONSTER(v) for(v = world; (v = findflags(v, flags, FL_MONSTER)) != world; ) - #endif + - #define CENTER_OR_VIEWOFS(ent) (ent.origin + ((ent.classname == STR_PLAYER) ? ent.view_ofs : ((ent.mins + ent.maxs) * 0.5))) + #define CENTER_OR_VIEWOFS(ent) (ent.origin + (IS_PLAYER(ent) ? ent.view_ofs : ((ent.mins + ent.maxs) * 0.5))) // copies a string to a tempstring (so one can strunzone it) string strcat1(string s) = #115; // FRIK_FILE