set g_start_weapon_hook -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default"
set g_start_weapon_tuba -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default"
set g_start_weapon_fireball -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default"
+set g_start_weapon_incubator -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default"
set g_balance_health_start 100
set g_balance_armor_start 0
set g_start_ammo_shells 15
alias selectteam "qc_cmd_cmd selectteam ${* ?}" // Attempt to choose a team to join into
alias selfstuff "qc_cmd_cmd selfstuff ${* ?}" // Stuffcmd a command to your own client
alias sentcvar "qc_cmd_cmd sentcvar ${* ?}" // New system for sending a client cvar to the server
+alias spawnmob "qc_cmd_cmd mobspawn ${* ?}" // Spawn a monster infront of the player
alias spectate "qc_cmd_cmd spectate ${* ?}" // Become an observer
alias suggestmap "qc_cmd_cmd suggestmap ${* ?}" // Suggest a map to the mapvote at match end
//alias tell "qc_cmd_cmd tell ${* ?}" // Send a message directly to a player
// mutator aliases
alias sandbox "cmd g_sandbox ${* ?}"
+alias spawnturret "cmd turretspawn ${* ?}"
+alias debugmonsters "cmd debugmonsters ${* ?}"
+alias upgradeturret "cmd buffturret ${* ?}"
// ============================================================
alias anticheat "qc_cmd_sv anticheat ${* ?}" // Create an anticheat report for a client
alias bbox "qc_cmd_sv bbox ${* ?}" // Print detailed information about world size
alias bot_cmd "qc_cmd_sv bot_cmd ${* ?}" // Control and send commands to bots
+alias butcher "qc_cmd_sv butcher ${* ?}" // Remove all monsters on the map
alias cointoss "qc_cmd_sv cointoss ${* ?}" // Flip a virtual coin and give random result
alias database "qc_cmd_sv database ${* ?}" // Extra controls of the serverprogs database
alias defer_clear "qc_cmd_sv defer_clear ${* ?}" // Clear all queued defer commands for a specific client
set g_weaponreplace_hook ""
set g_weaponreplace_tuba ""
set g_weaponreplace_fireball ""
+set g_weaponreplace_incubator ""
set sv_q3acompat_machineshotgunswap 0 "shorthand for swapping uzi and shotgun (for Q3A map compatibility in mapinfo files)"
set g_movement_highspeed 1 "movement speed modification factor (only changes movement when above maxspeed)"
exec vehicles.cfg
exec crosshairs.cfg
exec gamemodes.cfg
+exec monsters.cfg
+exec za.cfg
// load console command aliases and settings
exec commands.cfg
alias cl_hook_gamestart_cts
alias cl_hook_gamestart_ka
alias cl_hook_gamestart_ft
+alias cl_hook_gamestart_td
alias cl_hook_gameend
alias cl_hook_activeweapon
alias sv_hook_gamestart_cts
alias sv_hook_gamestart_ka
alias sv_hook_gamestart_ft
+alias sv_hook_gamestart_td
alias sv_hook_gamerestart
alias sv_hook_gameend
set g_ft_respawn_waves 0
set g_ft_respawn_delay 0
set g_ft_weapon_stay 0
+set g_td_respawn_waves 0
+set g_td_respawn_delay 0
+set g_td_weapon_stay 0
// =======
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_miniboss_min_monsters 5 "monster count to start spawning minibosses at"
+set g_td_monster_count 10
+set g_td_monster_count_increment 5
+set g_td_hardcore 0 "if enabled, players can't respawn during combat phase"
+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 g_td_monsters_skill_increment 0.1
+set g_td_monster_spawn_protection_radius 300
+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
--- /dev/null
+1 12 10 1 // demon stand\r14 7 10 1 // demon walk\r22 5 10 1 // demon run\r28 11 10 0 // demon leap\r40 5 10 0 // demon pain\r46 8 10 0 // demon death\r55 14 10 1 // demon melee
\ No newline at end of file
--- /dev/null
+Fiendish Deamon Doll model
+
+Copyright (C) 2003 Ulrich Gablraith
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+History:
+
+7-5-04
+
+The model was given to Mapes so he could port it into OpenQuartz by permission.
+
+Greg Mapes
\ No newline at end of file
--- /dev/null
+/*
+Generated framegroups file for dog
+Used by DarkPlaces to simulate frame groups in DPM models.
+*/
+
+1 25 60 1 // dog idle
+26 37 60 1 // dog walk
+63 37 120 1 // dog run
+100 50 60 1 // dog attack
+150 42 60 0 // dog die
+192 25 60 1 // dog pain
--- /dev/null
+This cerberus model is GPL 2.0 compatible (http://opengameart.org/content/animated-cerberus).
\ No newline at end of file
--- /dev/null
+1 6 10 1 // enforcer stand\r8 15 10 1 // enforcer walk\r24 7 10 1 // enforcer run\r32 9 10 1 // enforcer attack\r42 13 10 0 // enforcer death1\r56 10 10 0 // enforcer death2\r67 3 10 0 // enforcer pain1\r71 4 10 0 // enforcer pain2\r76 7 10 0 // enforcer pain3\r84 18 10 0 // enforcer pain4
\ No newline at end of file
--- /dev/null
+Enforcer
+
+Copyright (C) 2004 Greg Mapes
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+7-7-04
+First Release:
+
+Greg Mapes
+
+7-11-04
+
+The gun was a bit long and stuck through a lot of walls and other surfaces when it died, so it got revised.
+
+Greg Mapes
--- /dev/null
+1 17 10 1 // fish attack\r19 19 10 0 // fish death\r41 16 10 1 // fish swim\r59 8 10 0 // fish pain
\ No newline at end of file
--- /dev/null
+All the models in this folder (except zombie.dpm) were copied from the GPL project OpenQuartz 2 (http://www.quakewiki.net/openquartz-2).
\ No newline at end of file
--- /dev/null
+1 8 10 1 // hellknight stand\r10 19 10 1 // hellknight walk\r30 7 10 1 // hellknight run\r38 4 10 0 // hellknight pain\r43 11 10 0 // hellknight death1\r55 8 10 0 // hellknight death2\r64 15 10 0 // hellknight charge1\r80 13 10 0 // hellknight magic1\r94 12 10 0 // hellknight magic2\r107 5 10 0 // hellknight charge2\r113 9 10 1 // hellknight slice\r123 9 10 1 // hellknight smash\r133 21 10 1 // hellknight weapon attack\r155 10 10 0 //hellknight magic3
\ No newline at end of file
--- /dev/null
+Hooded model
+
+Copyright (C) 2003 Ulrich Gablraith
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+History:
+
+7-5-04
+
+The model was given to Mapes so he could port it into OpenQuartz by permission.
+
+Greg Mapes
\ No newline at end of file
--- /dev/null
+1 8 10 1 // knight stand\r10 7 10 1 // knight run\r18 10 10 1 // knight run attack\r29 2 10 0 // knight pain1\r32 10 10 0 // knight pain2\r43 9 10 1 // knight attack\r53 13 10 1 // knight walk\r67 4 10 0 // knight kneel\r72 4 10 1 // knight standing\r77 9 10 0 // knight death1\r88 10 10 0 // knight death2
\ No newline at end of file
--- /dev/null
+Knight model
+
+Copyright (C) 2004 Ulrich Gablraith
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+History:
+
+7-5-04
+
+The model was given to Mapes so he could port it into OpenQuartz by permission.
+
+Greg Mapes
\ No newline at end of file
--- /dev/null
+Monsters -Phantom Knight, Magical Knight, Master Knight, Knight, Jack-o-Lantern,
+ -Doll Fiend.
+
+Copyright (C) 2004 Ulrich Galbraith
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+Ulrich Galbraith
+ugalbrai@krl.org
+
+
+7-22-04
+
+First release
+
+I had to give some of them proper animation and proper connecting models so they would work.
+
+-Mapes
\ No newline at end of file
--- /dev/null
+1 8 10 1 // ogre stand\r10 15 10 1 // ogre walk\r26 7 10 1 // ogre run\r34 13 10 1 // ogre swing\r48 13 10 1 // ogre smash\r62 5 10 1 // ogre shoot\r68 4 10 0 // ogre pain1\r73 2 10 0 // ogre pain2\r76 5 10 0 // ogre pain3\r82 15 10 0 // ogre pain4\r98 14 10 0 // ogre pain5\r113 13 10 0 // ogre death1\r127 9 10 0 // ogre death2\r137 10 10 0 // ogre pull
\ No newline at end of file
--- /dev/null
+1 10 10 1 // shalrath attack\r12 4 10 0 // shalrath pain\r18 5 10 0 // shalrath death\r26 12 10 1 // shalrath walk
\ No newline at end of file
--- /dev/null
+1 16 10 1 // shambler stand\r18 11 10 1 // shambler walk\r31 5 10 1 // shambler run\r37 11 10 1 // shambler smash\r49 8 10 1 // shambler swing right\r58 8 10 1 // shambler swing left\r67 11 10 1 // shambler magic\r79 5 10 0 // shambler pain\r85 10 10 0 // shambler death
\ No newline at end of file
--- /dev/null
+1 8 10 1 // ogre stand\r10 15 10 1 // ogre walk\r26 7 10 1 // ogre run\r34 13 10 1 // ogre swing\r48 13 10 1 // ogre smash\r62 5 10 1 // ogre shoot\r68 4 10 0 // ogre pain1\r73 2 10 0 // ogre pain2\r76 5 10 0 // ogre pain3\r82 15 10 0 // ogre pain4\r98 14 10 0 // ogre pain5\r113 13 10 0 // ogre death1\r127 9 10 0 // ogre death2\r137 10 10 0 // ogre pull
\ No newline at end of file
--- /dev/null
+/*
+Generated framegroups file for spider
+Used by DarkPlaces to simulate frame groups in DPM models.
+*/
+
+1 60 60 1 // spider idle
+61 41 120 1 // spider walk
+102 24 60 1 // spider attack
+125 10 60 1 // spider attack2
\ No newline at end of file
--- /dev/null
+This spider model is GPL 2.0 compatible (http://opengameart.org/content/low-poly-spider-glest).
\ No newline at end of file
--- /dev/null
+1 24 10 1 // tarbaby walk\r26 24 10 1 // tarbaby run\r51 5 10 0 // tarbaby jump\r57 3 10 1 // tarbaby fly\r61 1 10 0 // tarbaby explode
\ No newline at end of file
--- /dev/null
+1 14 10 1 // wizard hover\r16 13 10 1 // wizard fly\r30 12 10 1 // wizard magic attack\r43 3 10 0 // wizard pain\r47 7 10 0 // wizard death
\ No newline at end of file
--- /dev/null
+pterascragg model
+
+Copyright (C) 2000 Dylan "lithiumbat" Sartain
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+History:
+
+7-11-00
+
+First release
+build time: about 2 hrs spread over three days
+model was made as a replacement for the scragg or wizard.
+
+7-13-00
+
+Seth Galbraith (sgalbrai@krl.org):
+Lowered death frame to lie on the ground
+Created head gib model
--- /dev/null
+bloodyskull,bloodyskull
+meat,meat
\ No newline at end of file
--- /dev/null
+bloodyskull,bloodyskull_alien
+meat,meat_alien
\ No newline at end of file
--- /dev/null
+bloodyskull,bloodyskull_robot
+meat,meat_robot
\ No newline at end of file
--- /dev/null
+// Misc
+set g_monsters 1 "Enable monsters (master switch)"
+set g_monsters_skill 1 "Monster skill (affecting some of their attributes). 1 - easy, 2 - medium, 3 - hard, 4 - insane, 5 - nightmare"
+set g_monsters_miniboss_chance 5
+set g_monsters_miniboss_healthboost 100
+set g_monsters_forcedrop "" "Force all monsters to drop this item on death. Possible values are: health, armor, ammo"
+set g_monsters_drop_size medium "Size of the item monsters drop. Possible health/amor values are: small, medium, large. Possible ammo values are: shells, bullets, cells, rockets"
+set g_monsters_owners 1 "Monsters will not attack their owners if set to 1"
+set g_monsters_teams 1
+set g_monster_spawnshieldtime 2 "Monsters will not take damage for this amount of seconds"
+set g_monsters_typefrag 1
+set g_monsters_healthbars 1 "Show health bars above monsters"
+set g_monsters_giants_only 0
+set g_monsters_nogiants 1
+set g_monsters_respawn 1 "Enable monster respawning"
+set g_monsters_respawn_delay 20 "Monsters respawn in this amount of seconds"
+set g_monsters_score_kill 1 "Get this many points for killing a naturally spawned monster"
+set g_monsters_max 20 "Global maximum player-spawned monsters"
+set g_monsters_max_perplayer 3 "Maximum monsters per-player"
+set g_monsters_skill_easy 2 "Monster easy skill level (used for skill based functions)"
+set g_monsters_skill_normal 4 "Monster normal skill level (used for skill based functions)"
+set g_monsters_skill_hard 5 "Monster hard skill level (used for skill based functions)"
+set g_monsters_skill_insane 7 "Monster insane skill level (used for skill based functions)"
+set g_monsters_skill_nightmare 10 "Monster nightmare skill level (used for skill based functions)"
+
+// Enforcer
+set g_monster_enforcer 1 "Enable Enforcers"
+set g_monster_enforcer_health 80 "Enforcer health"
+set g_monster_enforcer_drop armor "Enforcer drops this item on death"
+set g_monster_enforcer_drop_size large "Size of the item Enforcers drop. Possible values are: small, medium, large"
+set g_monster_enforcer_speed_walk 75 "Enforcer walk speed"
+set g_monster_enforcer_speed_run 100 "Enforcer run speed"
+set g_monster_enforcer_attack_uzi_bullets 3 "Number of machine gun bullets Enforcer fires"
+
+// Ogre
+set g_monster_ogre 1 "Enable Ogres"
+set g_monster_ogre_health 200 "Ogre health"
+set g_monster_ogre_chainsaw_damage 15 "Ogre chainsaw damage (hits multiple times)"
+set g_monster_ogre_drop ammo "Ogre drops this item on death"
+set g_monster_ogre_drop_size bullets "Size of the item Ogres drop. Possible values are: small, medium, large"
+set g_monster_ogre_speed_walk 100 "Ogre walk speed"
+set g_monster_ogre_speed_run 150 "Ogre run speed"
+set g_monster_ogre_attack_uzi_bullets 3 "Number of machine gun bullets Ogre fires"
+
+// Fiend
+set g_monster_demon 1 "Enable Fiends"
+set g_monster_demon_health 300 "Fiend health"
+set g_monster_demon_attack_jump_damage 40 "Fiend jump attack damage"
+set g_monster_demon_damage 20 "Fiend melee attack damage"
+set g_monster_demon_drop health "Fiend drops this item on death"
+set g_monster_demon_drop_size medium "Size of the item Fiends drop. Possible values are: small, medium, large"
+set g_monster_demon_speed_walk 150 "Fiend walk speed"
+set g_monster_demon_speed_run 300 "Fiend run speed"
+
+// Shambler
+set g_monster_shambler 1 "Enable Shamblers"
+set g_monster_shambler_health 600 "Shambler health"
+set g_monster_shambler_damage 50 "Shambler melee attack damage"
+set g_monster_shambler_attack_lightning_damage 20 "Shambler lightning attack damage per frame"
+set g_monster_shambler_attack_claw_damage 30 "Shambler claw attack damage"
+set g_monster_shambler_drop health "Shambler drops this item on death"
+set g_monster_shambler_drop_size large "Size of the item Shamblers drop. Possible values are: small, medium, large"
+set g_monster_shambler_speed_walk 100 "Shambler walk speed"
+set g_monster_shambler_speed_run 150 "Shambler run speed"
+
+// Knight
+set g_monster_knight 1 "Enable Knights"
+set g_monster_knight_health 75 "Knight Health"
+set g_monster_knight_drop armor "Knight drops this item on death"
+set g_monster_knight_drop_size medium "Size of the item Knights drop. Possible values are: small, medium, large"
+set g_monster_knight_melee_damage 20 "Knight melee attack damage"
+set g_monster_knight_melee_side_damage 10 "Knight melee attack side damage"
+set g_monster_knight_speed_walk 40 "Knight walk speed"
+set g_monster_knight_speed_run 70 "Knight run speed"
+
+// Grunt
+set g_monster_soldier 1 "Enable Grunts"
+set g_monster_soldier_health 100 "Grunt Health"
+set g_monster_soldier_drop ammo "Grunt drops this item on death"
+set g_monster_soldier_drop_size shells "Size of the item Grunts drop. Possible values are: small, medium, large"
+set g_monster_soldier_melee_damage 20 "Grunt melee attack damage"
+set g_monster_soldier_speed_walk 30 "Grunt walk speed"
+set g_monster_soldier_speed_run 50 "Grunt run speed"
+set g_monster_soldier_ammo 5 "Grunt weapon ammo"
+set g_monster_soldier_weapon_laser_chance 6 "Chance of Grunt weapon being laser"
+set g_monster_soldier_weapon_shotgun_chance 8 "Chance of Grunt weapon being shotgun"
+set g_monster_soldier_weapon_machinegun_chance 4 "Chance of Grunt weapon being machine gun"
+set g_monster_soldier_weapon_rocketlauncher_chance 2 "Chance of Grunt weapon being rocket launcher"
+set g_monster_soldier_attack_uzi_bullets 3 "Number of machine gun bullets Grunt fires"
+
+// Scrag
+set g_monster_wizard 1 "Enable Scrags"
+set g_monster_wizard_health 80 "Scrag health"
+set g_monster_wizard_drop ammo "Scrag drops this item on death"
+set g_monster_wizard_drop_size cells "Size of the item Scrags drop. Possible values are: small, medium, large"
+set g_monster_wizard_speed_walk 40 "Scrag walk speed"
+set g_monster_wizard_speed_run 70 "Scrag run speed"
+set g_monster_wizard_spike_damage 15 "Scrag spike damage"
+set g_monster_wizard_spike_damage 7 "Scrag spike edge damage"
+set g_monster_wizard_spike_radius 20 "Scrag spike damage radius"
+set g_monster_wizard_spike_speed 400 "Scrag spike speed"
+
+// Rottweiler
+set g_monster_dog 1 "Enable Rottweilers"
+set g_monster_dog_health 25 "Rottweiler health"
+set g_monster_dog_bite_damage 15 "Rottweiler bite attack damage"
+set g_monster_dog_attack_jump_damage 30 "Rottweiler jump attack damage"
+set g_monster_dog_drop health "Rottweiler drops this item on death"
+set g_monster_dog_drop_size small "Size of the item Rottweilers drop. Possible values are: small, medium, large"
+set g_monster_dog_speed_walk 60 "Rottweiler walk speed"
+set g_monster_dog_speed_run 120 "Rottweiler run speed"
+
+// Spawn
+set g_monster_tarbaby 1 "Enable Spawns"
+set g_monster_tarbaby_health 80 "Spawn health"
+set g_monster_tarbaby_drop ammo "Spawn drops this item when it explodes"
+set g_monster_tarbaby_drop_size rockets "Size of the item Spawns drop. Possible values are: small, medium, large"
+set g_monster_tarbaby_speed_walk 20 "Spawn walk speed"
+set g_monster_tarbaby_speed_run 30 "Spawn run speed"
+
+// Hell-Knight
+set g_monster_hellknight 1 "Enable Hell-Knights"
+set g_monster_hellknight_health 250 "Hell-Knight health"
+set g_monster_hellknight_drop armor "Hell-Knight drops this item on death"
+set g_monster_hellknight_drop_size medium "Size of the item Hell-Knights drop. Possible values are: small, medium, large"
+set g_monster_hellknight_inferno_damage 40 "Hell-Knight inferno damage"
+set g_monster_hellknight_inferno_chance 0.4 "Hell-Knight inferno attack chance"
+set g_monster_hellknight_inferno_damagetime 3 "How long the inferno should burn the player"
+set g_monster_hellknight_fireball_damage 30 "Hell-Knight fireball projectile damage"
+set g_monster_hellknight_fireball_edgedamage 10 "Hell-Knight fireball indirect hit damage"
+set g_monster_hellknight_fireball_force 50 "Hell-Knight fireball projectile push force"
+set g_monster_hellknight_fireball_radius 70 "Hell-Knight fireball projectile damage radius"
+set g_monster_hellknight_fireball_speed 600 "Hell-Knight fireball projectile speed"
+set g_monster_hellknight_fireball_spread 0 "Hell-Knight fireball projectile spread"
+set g_monster_hellknight_fireball_chance 0.3 "Chance for Hell-Knight to throw a fireball"
+set g_monster_hellknight_jump_chance 0.2 "Chance for Hell-Knight to jump at the player (always 1 if enemy is further than _dist)"
+set g_monster_hellknight_jump_damage 25 "Hell-Knight jump attack damage"
+set g_monster_hellknight_jump_dist 500 "Hell-Knight will prioritise jumping if the enemy is this far away"
+set g_monster_hellknight_melee_damage 20 "Hell-Knight melee attack damage"
+set g_monster_hellknight_spike_damage 5 "Hell-Knight spike projectile damage"
+set g_monster_hellknight_spike_edgedamage 5 "Hell-Knight spike projectile indirect hit damage"
+set g_monster_hellknight_spike_radius 20 "Hell-Knight spike projectile damage radius"
+set g_monster_hellknight_spike_force 5 "Hell-Knight spike projectile force"
+set g_monster_hellknight_spike_chance 0.5 "Hell-Knight spike attack chance"
+set g_monster_hellknight_speed_walk 75 "Hell-Knight walk speed"
+set g_monster_hellknight_speed_run 150 "Hell-Knight run speed"
+
+// Rotfish
+set g_monster_fish 1 "Enable Rotfish"
+set g_monster_fish_health 25 "Rotfish health"
+set g_monster_fish_damage 10 "Rotfish bite attack damage"
+set g_monster_fish_drop health "Rotfish drops this item on death"
+set g_monster_fish_drop_size small "Size of the item Rotfish drop. Possible values are: small, medium, large"
+set g_monster_fish_speed_walk 40 "Rotfish walk speed"
+set g_monster_fish_speed_run 70 "Rotfish run speed"
+
+// Vore
+set g_monster_shalrath 1 "Enable Vores"
+set g_monster_shalrath_health 400 "Vore health"
+set g_monster_shalrath_damage 30 "Vore magic attack damage"
+set g_monster_shalrath_drop health "Vore drops this item on death"
+set g_monster_shalrath_drop_size medium "Size of the item Vores drop. Possible values are: small, medium, large"
+set g_monster_shalrath_speed 50 "Vore move speed"
+
+// Spawner
+set g_monster_spawner 1 "Enable Monster Spawner"
+set g_monster_spawner_health 100 "Spawner health"
+set g_monster_spawner_target_recheck_delay 1 "Spawner enemy check delay"
+set g_monster_spawner_target_range 600 "Spawner maximum enemy distance"
+set g_monster_spawner_spawn_range 600 "Spawn monsters while enemy is within this range"
+set g_monster_spawner_maxmobs 4 "Maximum number of spawned monsters"
+set g_monster_spawner_forcespawn 0 "Force spawner to spawn this type of monster"
+
+// Zombie
+set g_monster_zombie 1 "Enable Zombies"
+set g_monster_zombie_attack_leap_damage 45 "Damage when zombie performs an attack leap"
+set g_monster_zombie_attack_leap_delay 1.5 "Delay after zombie attack leap"
+set g_monster_zombie_attack_leap_force 55 "Force of zombie attack leap"
+set g_monster_zombie_attack_leap_range 96 "Range of zombie attack leap"
+set g_monster_zombie_attack_leap_speed 500 "The speed of a zombie attack leap"
+set g_monster_zombie_attack_stand_damage 35 "Damage when zombie hits from a standing position"
+set g_monster_zombie_attack_stand_delay 1.2 "Delay after a zombie hits from a standing position"
+set g_monster_zombie_attack_stand_range 48 "Range of a zombie standing position attack"
+set g_monster_zombie_health 200 "Zombie health"
+set g_monster_zombie_idle_timer 1 "Minimum time a zombie can stay idle"
+set g_monster_zombie_speed_walk 150 "Zombie walk speed"
+set g_monster_zombie_speed_run 400 "Zombie run speed"
+set g_monster_zombie_stopspeed 100 "Speed at which zombie stops"
+set g_monster_zombie_target_recheck_delay 5 How much time should a zombie run afer an enemy before checking if it's still in range"
+set g_monster_zombie_target_range 1200 How far the zombie can see an enemy"
+set g_monster_zombie_drop health "Zombie drops this item on death"
+set g_monster_zombie_drop_size large "Size of the item zombies drop. Possible values are: small, medium, large"
+
+// Spider
+set g_monster_spider 1 "Enable Spiders"
+set g_monster_spider_attack_type 0 "Spider attack type (0 = ice, 1 = fire, ...)"
+set g_monster_spider_attack_leap_delay 1.5 "Delay after spider attack leap"
+set g_monster_spider_attack_leap_range 96 "Range of spider attack leap"
+set g_monster_spider_attack_stand_damage 35 "Damage when spider hits from a standing position"
+set g_monster_spider_attack_stand_delay 1.2 "Delay after a spider hits from a standing position"
+set g_monster_spider_attack_stand_range 48 "Range of a spider standing position attack"
+set g_monster_spider_health 200 "Spider health"
+set g_monster_spider_idle_timer_min 1 "Minimum time a spider can stay idle"
+set g_monster_spider_speed_walk 150 "Spider walk speed"
+set g_monster_spider_speed_run 400 "Spider run speed"
+set g_monster_spider_stopspeed 100 Speed at which spider stops"
+set g_monster_spider_target_recheck_delay 5 How much time should a spider run afer an enemy before checking if it's still in range"
+set g_monster_spider_target_range 1200 How far the spider can see an enemy"
+set g_monster_spider_drop health "Spider drops this item on death"
+set g_monster_spider_drop_size large "Size of the item spiders drop. Possible values are: small, medium, large"
\ No newline at end of file
}
}
}
- } else if (type == DEATH_CUSTOM) {
+ } else 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");
vector HUD_DrawMapStats(vector pos, vector rgb, vector bg_size) {
float stat_secrets_found, stat_secrets_total;
- float rows;
+ float stat_current_wave, stat_totalwaves;
+ float stat_monsters_killed, stat_monsters_total;
+ float rows = 0;
string val;
+
+ // get tower defense stats
+ stat_current_wave = getstatf(STAT_CURRENT_WAVE);
+ stat_totalwaves = getstatf(STAT_TOTALWAVES);
+
+ // get monster stats
+ stat_monsters_killed = getstatf(STAT_MONSTERS_KILLED);
+ stat_monsters_total = getstatf(STAT_MONSTERS_TOTAL);
// get secrets stats
stat_secrets_found = getstatf(STAT_SECRETS_FOUND);
stat_secrets_total = getstatf(STAT_SECRETS_TOTAL);
// get number of rows
- rows = (stat_secrets_total ? 1 : 0);
+ if(stat_secrets_total)
+ rows += 1;
+ if(stat_totalwaves)
+ rows += 1;
+ if(stat_monsters_total)
+ rows += 1;
// if no rows, return
if not(rows)
else
drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
drawborderlines(autocvar_scoreboard_border_thickness, pos, tmp, '0 0 0', scoreboard_alpha_bg * 0.75, DRAWFLAG_NORMAL);
+
+ // draw waves
+ if(stat_totalwaves)
+ {
+ val = sprintf("%d/%d", stat_current_wave, stat_totalwaves);
+ pos = HUD_DrawKeyValue(pos, _("Current wave:"), val);
+ }
+
+ // draw monsters
+ if(stat_monsters_total)
+ {
+ val = sprintf("%d/%d", stat_monsters_killed, stat_monsters_total);
+ pos = HUD_DrawKeyValue(pos, _("Monsters killed:"), val);
+ }
// draw secrets
- val = sprintf("%d/%d", stat_secrets_found, stat_secrets_total);
- pos = HUD_DrawKeyValue(pos, _("Secrets found:"), val);
+ if(stat_secrets_total)
+ {
+ val = sprintf("%d/%d", stat_secrets_found, stat_secrets_total);
+ pos = HUD_DrawKeyValue(pos, _("Secrets found:"), val);
+ }
// update position
pos_y += 1.25 * hud_fontsize_y;
const float STAT_RESPAWN_TIME = 72;
+const float STAT_CURRENT_WAVE = 73;
+const float STAT_TOTALWAVES = 74;
+
+const float STAT_MONSTERS_TOTAL = 75;
+const float STAT_MONSTERS_KILLED = 76;
+
// mod stats (1xx)
const float STAT_REDALIVE = 100;
const float STAT_BLUEALIVE = 101;
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;
#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)
+#define DEATH_ISMONSTER(t) ((t) >= DEATH_MONSTER && (t) <= DEATH_MONSTER_LAST)
#define FRAGS_PLAYER 0
#define FRAGS_SPECTATOR -666
MapInfo_Map_supportedGametypes |= MAPINFO_TYPE_CTF;
else if(v == "runematch_spawn_point")
MapInfo_Map_supportedGametypes |= MAPINFO_TYPE_RUNEMATCH;
+ else if(v == "td_generator")
+ MapInfo_Map_supportedGametypes |= MAPINFO_TYPE_TD;
else if(v == "target_assault_roundend")
MapInfo_Map_supportedGametypes |= MAPINFO_TYPE_ASSAULT;
else if(v == "onslaught_generator")
REGISTER_GAMETYPE(_("Last Man Standing"),lms,g_lms,LMS,"timelimit=20 lives=9 leadlimit=0")
#define g_lms IS_GAMETYPE(LMS)
+REGISTER_GAMETYPE(_("Tower Defense"),td,g_td,TD,"timelimit=20 pointlimit=10 leadlimit=0")
+#define g_td IS_GAMETYPE(TD)
+
REGISTER_GAMETYPE(_("Arena"),arena,g_arena,ARENA,"timelimit=20 pointlimit=10 leadlimit=0")
#define g_arena IS_GAMETYPE(ARENA)
{
if(!inWarmupStage)
if(targ.flags & FL_CLIENT)
+ if(!(attacker.flags & FL_MONSTER)) // no accuracy for monsters
if(targ.deadflag == DEAD_NO)
if(IsDifferentTeam(attacker, targ))
return TRUE;
float autocvar_g_sandbox_object_material_velocity_factor;
float autocvar_g_max_info_autoscreenshot;
float autocvar_physics_ode;
+float autocvar_g_td_start_wave;
+float autocvar_g_td_hardcore;
+float autocvar_g_td_generator_health;
+float autocvar_g_td_current_monsters;
+float autocvar_g_td_generator_damaged_points;
+float autocvar_g_td_monster_count;
+float autocvar_g_td_monster_count_increment;
+float autocvar_g_td_buildphase_time;
+float autocvar_g_td_pvp;
+float autocvar_g_td_max_waves;
+float autocvar_g_td_kill_points;
+float autocvar_g_td_turretkill_points;
+float autocvar_g_td_generator_dontend;
+float autocvar_g_td_force_settings;
+float autocvar_g_td_turret_max;
+float autocvar_g_td_turret_plasma_cost;
+float autocvar_g_td_turret_mlrs_cost;
+float autocvar_g_td_turret_walker_cost;
+float autocvar_g_td_tower_buff_cost;
+float autocvar_g_td_monsters_skill_start;
+float autocvar_g_td_monsters_skill_increment;
+float autocvar_g_td_monster_spawn_protection_radius;
+float autocvar_g_za_monster_count;
+float autocvar_g_monsters;
+float autocvar_g_monsters_max;
+float autocvar_g_monsters_max_perplayer;
+float autocvar_g_monsters_giants_only;
+float autocvar_g_monsters_typefrag;
+float autocvar_g_monsters_owners;
+float autocvar_g_monsters_miniboss_chance;
+float autocvar_g_monsters_miniboss_healthboost;
+string autocvar_g_monsters_forcedrop;
+string autocvar_g_monsters_drop_type;
+string autocvar_g_monsters_drop_size;
+float autocvar_g_monsters_teams;
+float autocvar_g_monsters_healthbars;
+float autocvar_g_monsters_respawn_delay;
+float autocvar_g_monsters_respawn;
+float autocvar_g_monsters_nogiants;
+float autocvar_g_monsters_skill_easy;
+float autocvar_g_monsters_skill_normal;
+float autocvar_g_monsters_skill_hard;
+float autocvar_g_monsters_skill_insane;
+float autocvar_g_monsters_skill_nightmare;
self.event_damage = PlayerDamage;
self.bot_attack = TRUE;
+ self.monster_attack = TRUE;
self.statdraintime = time + 5;
self.BUTTON_ATCK = self.BUTTON_JUMP = self.BUTTON_ATCK2 = 0;
self.target = s;
activator = world;
self = oldself;
+
+ Unfreeze(self);
spawn_spot = spot;
MUTATOR_CALLHOOK(PlayerSpawn);
if(autocvar_g_forced_team_otherwise == "spectator")
return 0;
}
+
+ if(MUTATOR_CALLHOOK(PlayerCanJoin))
+ return 0;
if(self.team_forced < 0)
return 0; // forced spectators can never join
return;
#endif
+ if(self.frozen)
+ {
+ self.revive_progress = bound(0, self.revive_progress + frametime * self.revive_speed, 1);
+ self.health = max(1, self.revive_progress * autocvar_g_balance_health_start);
+
+ if(self.revive_progress >= 1)
+ Unfreeze(self);
+ }
+
MUTATOR_CALLHOOK(PlayerPreThink);
if(!self.cvar_cl_newusekeysupported) // FIXME remove this - it was a stupid idea to begin with, we can JUST use the button
self.prevorigin = self.origin;
if (!self.vehicle)
- if (((self.BUTTON_CROUCH && !self.hook.state) || self.health <= g_bloodloss) && self.animstate_startframe != self.anim_melee_x && !self.freezetag_frozen) // prevent crouching if using melee attack
+ if (((self.BUTTON_CROUCH && !self.hook.state) || self.health <= g_bloodloss) && self.animstate_startframe != self.anim_melee_x && !self.freezetag_frozen && !self.frozen) // prevent crouching if using melee attack
{
if (!self.crouch)
{
// secret status
secrets_setstatus();
+ // monsters status
+ monsters_setstatus();
+
self.dmg_team = max(0, self.dmg_team - autocvar_g_teamdamage_resetspeed * frametime);
//self.angles_y=self.v_angle_y + 90; // temp
*/
void PlayerJump (void)
{
- if(self.freezetag_frozen)
+ if(self.freezetag_frozen || self.frozen)
return; // no jumping in freezetag when frozen
float mjumpheight;
self.disableclientprediction = 0;
if(time < self.ladder_time)
self.disableclientprediction = 1;
+
+ if(self.frozen)
+ {
+ self.movement = '0 0 0';
+ self.disableclientprediction = 1;
+ }
MUTATOR_CALLHOOK(PlayerPhysics);
PM_Accelerate(wishdir, wishspeed, wishspeed, autocvar_sv_accelerate*maxspd_mod, 1, 0, 0, 0);
}
}
- else if ((self.items & IT_JETPACK) && self.BUTTON_HOOK && (!autocvar_g_jetpack_fuel || self.ammo_fuel >= 0.01 || self.items & IT_UNLIMITED_WEAPON_AMMO) && !self.freezetag_frozen)
+ else if ((self.items & IT_JETPACK) && self.BUTTON_HOOK && (!autocvar_g_jetpack_fuel || self.ammo_fuel >= 0.01 || self.items & IT_UNLIMITED_WEAPON_AMMO) && !self.freezetag_frozen && !self.frozen)
{
//makevectors(self.v_angle_y * '0 1 0');
makevectors(self.v_angle);
if (!self.animstate_override)
{
- if (self.freezetag_frozen)
+ if (self.freezetag_frozen || self.frozen)
setanim(self, self.anim_idle, TRUE, FALSE, FALSE);
else if (!(self.flags & FL_ONGROUND) || self.BUTTON_JUMP)
{
w = self.weapon;
if (w == 0)
return; // just in case
+ if(self.frozen)
+ return;
if(MUTATOR_CALLHOOK(ForbidThrowCurrentWeapon))
return;
if(!autocvar_g_weapon_throwable)
if(((arena_roundbased || g_ca || g_freezetag) && time < warmup) || ((time < game_starttime) && !autocvar_sv_ready_restart_after_countdown))
return;
- if(self.freezetag_frozen == 1)
+ if(self.freezetag_frozen == 1 || self.frozen == 1)
return;
if (!self.weaponentity || self.health < 1)
vector org;
float lag;
- if(player.hitplotfh >= 0)
+ if(player.hitplotfh >= 0 && !(player.flags & FL_MONSTER))
{
lag = ANTILAG_LATENCY(player);
if(lag < 0.001)
void W_AttachToShotorg(entity flash, vector offset)
{
+ if(self.flags & FL_MONSTER)
+ return; // no flash for monsters
entity xflash;
flash.owner = self;
flash.angles_z = random() * 360;
void W_DecreaseAmmo(.float ammo_type, float ammo_use, float ammo_reload)
{
+ if(self.flags & FL_MONSTER) // no ammo for monsters... yet
+ return;
+
if((self.items & IT_UNLIMITED_WEAPON_AMMO) && !ammo_reload)
return;
}
}
+void ClientCommand_mobspawn(float request, float argc)
+{
+ switch(request)
+ {
+ case CMD_REQUEST_COMMAND:
+ {
+ entity e;
+ string tospawn, mname, s;
+ float spawncount = 0, moveflag, max_global, max_perplayer, i;
+
+ max_global = autocvar_g_monsters_max;
+ max_perplayer = autocvar_g_monsters_max_perplayer;
+ moveflag = (argv(3) ? stof(argv(3)) : 1); // follow owner if not defined
+ spawncount = ((argv(2)) ? stof(argv(2)) : 1);
+ tospawn = argv(1);
+ mname = argv(4);
+ s = ((spawncount == 1) ? "" : "s");
+
+ if(tospawn == "list")
+ {
+ sprint(self, "Available monsters:\n");
+ sprint(self, strcat(monsterlist(), "\n"));
+ return;
+ }
+
+ if(self.classname != STR_PLAYER) { sprint(self, "You can't spawn monsters while spectating.\n"); return; }
+ else if(self.deadflag) { sprint(self, "You can't spawn monsters while dead.\n"); return; }
+ else if(self.monstercount > max_perplayer) { sprint(self, "You have spawned too many monsters, kill some before trying to spawn any more.\n"); return; }
+ else if(totalspawned > max_global) { sprint(self, "The global maximum monster count has been reached, kill some before trying to spawn any more.\n"); return; }
+ else if(spawncount == 0) { sprint(self, "No monsters to spawn.\n"); return; }
+
+ makevectors(self.v_angle);
+ WarpZone_TraceLine(self.origin + self.view_ofs, self.origin + self.view_ofs + v_forward * 100, MOVE_NORMAL, self);
+
+ for(i = 0; i < spawncount; i++)
+ {
+ self.monstercount++;
+ if(self.monstercount > max_perplayer) break; // FIXME: check for these properly
+ e = spawnmonster(tospawn, self, self, trace_endpos, FALSE, moveflag);
+ if(e == world) { self.monstercount -= 1; break; } // take back the 1 that was lost
+ if(mname != "") e.netname = mname;
+ totalspawned++;
+ }
+
+ sprint(self, sprintf("Spawned %d %s%s\n", spawncount, tospawn, s));
+
+ return;
+ }
+
+ default:
+ sprint(self, "Incorrect parameters for ^2mobspawn^7\n");
+ case CMD_REQUEST_USAGE:
+ {
+ sprint(self, "\nUsage:^3 cmd mobspawn monster\n");
+ sprint(self, " See 'cmd mobspawn list' for available arguments.\n");
+ return;
+ }
+ }
+}
+
void ClientCommand_ready(float request) // todo: anti-spam for toggling readyness
{
switch(request)
CLIENT_COMMAND("clientversion", ClientCommand_clientversion(request, arguments), "Release version of the game") \
CLIENT_COMMAND("mv_getpicture", ClientCommand_mv_getpicture(request, arguments), "Retrieve mapshot picture from the server") \
CLIENT_COMMAND("join", ClientCommand_join(request), "Become a player in the game") \
+ CLIENT_COMMAND("mobspawn", ClientCommand_mobspawn(request, arguments), "Spawn monsters infront of yourself") \
CLIENT_COMMAND("ready", ClientCommand_ready(request), "Qualify as ready to end warmup stage (or restart server if allowed)") \
CLIENT_COMMAND("say", ClientCommand_say(request, arguments, command), "Print a message to chat to all players") \
CLIENT_COMMAND("say_team", ClientCommand_say_team(request, arguments, command), "Print a message to chat to all team mates") \
.float lms_spectate_warning;
.float checkfail;
+// number of monsters spawned with mobspawn command
+float totalspawned;
+
string MapVote_Suggest(string m);
// used by common/command/generic.qc:GenericCommand_dumpcommands to list all commands into a .txt file
-void ClientCommand_macro_write_aliases(float fh);
\ No newline at end of file
+void ClientCommand_macro_write_aliases(float fh);
}
}
+void GameCommand_butcher(float request)
+{
+ switch(request)
+ {
+ case CMD_REQUEST_COMMAND:
+ {
+ float removed_count = 0;
+ totalspawned = 0;
+ entity montokill = world;
+ FOR_EACH_MONSTER(montokill)
+ {
+ if(montokill.sprite)
+ WaypointSprite_Kill(montokill.sprite);
+
+ if(montokill.realowner.flags & FL_CLIENT)
+ montokill.realowner.monstercount -= 1;
+
+ remove(montokill);
+ removed_count += 1;
+ }
+ if(removed_count <= 0)
+ print("No monsters to kill\n");
+ else
+ print(strcat("Killed ", ftos(removed_count), " monster", ((removed_count == 1) ? "\n" : "s\n")));
+ return; // never fall through to usage
+ }
+
+ default:
+ case CMD_REQUEST_USAGE:
+ {
+ print("\nUsage:^3 sv_cmd butcher\n");
+ print(" No arguments required.\n");
+ return;
+ }
+ }
+}
+
void GameCommand_allready(float request)
{
switch(request)
// Common commands have double indentation to separate them a bit.
#define SERVER_COMMANDS(request,arguments,command) \
SERVER_COMMAND("adminmsg", GameCommand_adminmsg(request, arguments), "Send an admin message to a client directly") \
+ SERVER_COMMAND("butcher", GameCommand_butcher(request), "Instantly removes all monsters on the map") \
SERVER_COMMAND("allready", GameCommand_allready(request), "Restart the server and reset the players") \
SERVER_COMMAND("allspec", GameCommand_allspec(request, arguments), "Force all players to spectate") \
SERVER_COMMAND("anticheat", GameCommand_anticheat(request, arguments), "Create an anticheat report for a client") \
#endif
..float current_ammo;
+.float currentegg;
.float weapon_load[WEP_MAXCOUNT];
.float ammo_none; // used by the reloading system, must always be 0
.float freezetag_frozen;
.float freezetag_revive_progress;
+.float frozen; // for freeze attacks
+.float revive_progress;
+.float revive_speed; // NOTE: multiplier (anything above 1 is instaheal)
+
.entity muzzle_flash;
.float misc_bulletcounter; // replaces uzi & hlac bullet counter.
#define MISSILE_IS_CONFUSABLE(m) ((m.missile_flags & MIF_GUIDED_CONFUSABLE) ? TRUE : FALSE)
#define MISSILE_IS_GUIDED(m) ((m.missile_flags & MIF_GUIDED_ALL) ? TRUE : FALSE)
#define MISSILE_IS_TRACKING(m) ((m.missile_flags & MIF_GUIDED_TRACKING) ? TRUE : FALSE)
+
+.string spawnmob;
+.float monster_attack;
+
+float monster_skill;
+float spawncode_first_load; // used to tell the player the monster database is loading (TODO: fix this?)
+
+.entity monster_owner; // new monster owner entity, fixes non-solid monsters
+.float monstercount; // per player monster count
+
+.float stat_monsters_killed; // stats
+.float stat_monsters_total;
+float monsters_total;
+float monsters_killed;
+void monsters_setstatus(); // monsters.qc
+string monsterlist();
}
}
+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;
mirrorforce *= g_weaponforcefactor;
}
+ if(targ.frozen && attacker.classname != "monster_spider")
+ {
+ damage = 0;
+ force *= 0.2;
+ }
+
// should this be changed at all? If so, in what way?
frag_attacker = attacker;
frag_target = targ;
else
victim = targ;
- if(victim.classname == "player" || victim.turrcaps_flags & TFL_TURRCAPS_ISTURRET)
+ if(victim.classname == "player" || victim.turrcaps_flags & TFL_TURRCAPS_ISTURRET || victim.flags & FL_MONSTER)
{
if(IsDifferentTeam(victim, attacker))
{
e.fire_endtime = 0;
// ice stops fire
- if(e.freezetag_frozen)
+ if(e.freezetag_frozen || e.frozen)
e.fire_endtime = 0;
t = min(frametime, e.fire_endtime - time);
if((arena_roundbased && time < warmup) || (time < game_starttime))
return;
- if(self.freezetag_frozen)
+ if(self.freezetag_frozen || self.frozen)
return;
if(self.vehicle)
BADCVAR("g_freezetag");
BADCVAR("g_keepaway");
BADCVAR("g_keyhunt");
+ BADCVAR("g_td");
BADCVAR("g_keyhunt_teams");
BADCVAR("g_keyhunt_teams");
BADCVAR("g_lms");
addstat(STAT_FROZEN, AS_INT, freezetag_frozen);
addstat(STAT_REVIVE_PROGRESS, AS_FLOAT, freezetag_revive_progress);
}
+
+ if(g_td)
+ {
+ addstat(STAT_CURRENT_WAVE, AS_FLOAT, stat_current_wave);
+ addstat(STAT_TOTALWAVES, AS_FLOAT, stat_totalwaves);
+ }
+
+ // freeze attacks
+ addstat(STAT_FROZEN, AS_INT, frozen);
+ addstat(STAT_REVIVE_PROGRESS, AS_FLOAT, revive_progress);
// g_movementspeed hack
addstat(STAT_MOVEVARS_AIRSPEEDLIMIT_NONQW, AS_FLOAT, stat_sv_airspeedlimit_nonqw);
// secrets
addstat(STAT_SECRETS_TOTAL, AS_FLOAT, stat_secrets_total);
addstat(STAT_SECRETS_FOUND, AS_FLOAT, stat_secrets_found);
+
+ // monsters
+ addstat(STAT_MONSTERS_TOTAL, AS_FLOAT, stat_monsters_total);
+ addstat(STAT_MONSTERS_KILLED, AS_FLOAT, stat_monsters_killed);
// misc
addstat(STAT_RESPAWN_TIME, AS_FLOAT, stat_respawn_time);
// weird mutators that deserve to count as mod
if(autocvar_g_minstagib)
modname = "MinstaGib";
+ if(autocvar_g_monsters)
+ modname = "Monsters";
// extra mutators that deserve to count as mod
MUTATOR_CALLHOOK(SetModname);
// weird game types that deserve to count as mod
return WINNING_NO;
}
+// TD winning condition:
+// game terminates if there are no generators (or 1 dies if td_dontend is TRUE)
+float gensurvived;
+float WinningCondition_TowerDefense()
+{
+ WinningConditionHelper(); // set worldstatus
+
+ if(inWarmupStage)
+ return WINNING_NO;
+
+ // first check if the game has ended
+ if(gendestroyed == TRUE) // FALSE means either generator hasen't spawned yet, or mapper didn't add one
+ if(td_gencount < 1 || !td_dont_end)
+ {
+ ClearWinners();
+ dprint("Everyone lost, ending game.\n");
+ return WINNING_YES;
+ }
+
+ if(gensurvived)
+ {
+ ClearWinners();
+ SetWinners(winning, 4);
+ return WINNING_YES;
+ }
+
+ // Two or more teams remain
+ return WINNING_NO;
+}
+
/*
============
CheckRules_World
{
checkrules_status = WinningCondition_Onslaught(); // TODO remove this?
}
+ else if(g_td)
+ {
+ checkrules_status = WinningCondition_TowerDefense(); // TODO make these mutator hooks?
+ }
else
{
checkrules_status = WinningCondition_Scores(fraglimit, leadlimit);
#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)
+#define FOR_EACH_MONSTER(v) for(v = world; (v = findflags(v, flags, FL_MONSTER)) != world; )
#else
#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_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_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)))
void readlevelcvars(void)
{
g_minstagib = cvar("g_minstagib");
+
+ monster_skill = cvar("g_monsters_skill");
// load ALL the mutators
if(cvar("g_dodging"))
// is this a mutator? is this a mode?
if(cvar("g_sandbox"))
MUTATOR_ADD(sandbox);
+
+ if(cvar("g_za"))
+ MUTATOR_ADD(mutator_zombie_apocalypse);
if(cvar("sv_allow_fullbright"))
serverflags |= SERVERFLAG_ALLOW_FULLBRIGHT;
self.velocity = normalize(self.velocity) * (mspeed - 50);//* max_velocity;
}
+void movelib_move_simple_gravity(vector newdir,float velo,float blendrate)
+{
+ float z_speed = self.velocity_z;
+ self.movelib_lastupdate = time;
+ self.velocity = self.velocity * (1 - blendrate) + (newdir * blendrate) * velo;
+ self.velocity_z = z_speed;
+}
+
+void movelib_jump_simple(float power){
+ self.velocity_z=power;
+ self.movelib_lastupdate = time;
+}
+
/*
.float mass;
.float side_friction;
MUTATOR_HOOKABLE(ClientDisconnect);
// called when a player disconnects
+
+MUTATOR_HOOKABLE(PlayerCanJoin);
+ // called when a player tries to join
+ // if this returns TRUE, the player cannot join
MUTATOR_HOOKABLE(PlayerDies);
// called when a player dies to e.g. remove stuff he was carrying.
// return error to request removal
// INPUT: self - turret
+MUTATOR_HOOKABLE(TurretValidateTarget);
+ // return target score
+ // INPUT:
+ entity turret_target;
+ entity turret;
+
MUTATOR_HOOKABLE(OnEntityPreSpawn);
// return error to prevent entity spawn, or modify the entity
// INPUT:
entity self;
entity other;
+
+MUTATOR_HOOKABLE(MonsterSpawn);
+ // called when a monster spawns
+
+MUTATOR_HOOKABLE(MonsterDies);
+ // called when a monster dies
+ // INPUT:
+ entity frag_attacker;
+
+MUTATOR_HOOKABLE(MonsterDropItem);
+ // called when a monster is dropping loot
+ // INPUT, OUTPUT:
+ string monster_dropitem;
+ string monster_dropsize;
+
+MUTATOR_HOOKABLE(MonsterMove);
+ // called when a monster moves
+ // INPUT:
+ float monster_speed_run;
+ float monster_speed_walk;
+ entity monster_target;
+
+MUTATOR_HOOKABLE(MonsterFindTarget);
+ // called when a monster looks for another target
+
+MUTATOR_HOOKABLE(MonsterCheckBossFlag);
+ // called to change a random monster to a miniboss
MUTATOR_HOOKABLE(PlayerDamage_SplitHealthArmor);
// called when a player gets damaged to e.g. remove stuff he was carrying.
MUTATOR_DECLARATION(gamemode_ctf);
MUTATOR_DECLARATION(gamemode_nexball);
MUTATOR_DECLARATION(gamemode_onslaught);
+MUTATOR_DECLARATION(gamemode_td);
MUTATOR_DECLARATION(mutator_dodging);
MUTATOR_DECLARATION(mutator_invincibleprojectiles);
MUTATOR_DECLARATION(mutator_spawn_near_teammate);
MUTATOR_DECLARATION(mutator_vampire);
MUTATOR_DECLARATION(mutator_superspec);
+MUTATOR_DECLARATION(mutator_zombie_apocalypse);
MUTATOR_DECLARATION(sandbox);
mutators/gamemode_keepaway.qh
mutators/gamemode_nexball.qh
mutators/mutator_dodging.qh
+mutators/gamemode_td.qh
//// tZork Turrets ////
tturrets/include/turrets_early.qh
../common/explosion_equation.qc
+monsters/monsters.qh
+
mutators/base.qc
mutators/gamemode_ctf.qc
mutators/gamemode_freezetag.qc
mutators/gamemode_keepaway.qc
mutators/gamemode_nexball.qc
mutators/gamemode_onslaught.qc
+mutators/gamemode_td.qc
mutators/mutator_invincibleproj.qc
mutators/mutator_new_toys.qc
mutators/mutator_nix.qc
mutators/mutator_spawn_near_teammate.qc
mutators/sandbox.qc
mutators/mutator_superspec.qc
+mutators/mutator_zombie_apocalypse.qc
../warpzonelib/anglestransform.qc
../warpzonelib/mathlib.qc
float vehic = (self.vehicle_flags & VHF_ISVEHICLE);
float projectile = (self.flags & FL_PROJECTILE);
+ float monster = (self.flags & FL_MONSTER);
if (self.watertype <= CONTENT_WATER && self.waterlevel > 0) // workaround a retarded bug made by id software :P (yes, it's that old of a bug)
{
self.dmgtime = 0;
}
- if(!vehic && !projectile) // vehicles and projectiles don't drown
+ if(!vehic && !projectile && !monster) // vehicles, monsters and projectiles don't drown
{
if (self.waterlevel != WATERLEVEL_SUBMERGED)
{
MUTATOR_ADD(gamemode_ctf);
have_team_spawns = -1; // request team spawns
}
+
+ if(g_td)
+ {
+ fraglimit_override = 0; // no limits in TD - it's a survival mode
+ leadlimit_override = 0;
+ MUTATOR_ADD(gamemode_td);
+ }
if(g_runematch)
{
self.tur_head.avelocity = self.avelocity;
self.tur_head.angles = self.idle_aim;
self.health = self.tur_health;
+ self.max_health = self.tur_health;
self.enemy = world;
self.volly_counter = self.shot_volly;
self.takedamage = DAMAGE_NO;
self.nextthink = time;
self.think = turret_stdproc_die;
+
+ if(self.realowner)
+ self.realowner.turret_cnt -= 1;
}
self.SendFlags |= TNSF_STATUS;
float turret_validate_target(entity e_turret, entity e_target, float validate_flags)
{
vector v_tmp;
+
+ turret_target = e_target;
+ turret = e_turret;
+ if(MUTATOR_CALLHOOK(TurretValidateTarget))
+ return 1;
+ e_target = turret_target;
+ e_turret = turret;
//if(!validate_flags & TFL_TARGETSELECT_NOBUILTIN)
// return -0.5;
if not (self.health)
self.health = 1000;
self.tur_health = max(1, self.health);
+ self.max_health = self.tur_health;
+ self.bot_attack = TRUE;
+ self.monster_attack = TRUE;
if not (self.turrcaps_flags)
self.turrcaps_flags = TFL_TURRCAPS_RADIUSDMG | TFL_TURRCAPS_MEDPROJ | TFL_TURRCAPS_PLAYERKILL;
self.turret_score_target = turret_stdproc_targetscore_generic;
self.use = turret_stdproc_use;
- self.bot_attack = TRUE;
++turret_count;
self.nextthink = time + 1;
if ((_turret.target_select_missilebias > 0) && (_target.flags & FL_PROJECTILE))
m_score = 1;
- if ((_turret.target_select_playerbias > 0) && (_target.flags & FL_CLIENT))
+ if ((_turret.target_select_playerbias > 0) && (_target.flags & FL_CLIENT) && !g_td)
+ p_score = 1;
+
+ if(g_td && _target.flags & FL_MONSTER)
p_score = 1;
d_score = max(d_score, 0);
vector fl_org;
self.enemy.ammo = min(self.enemy.ammo + self.shot_dmg,self.enemy.ammo_max);
+ if(g_td) // auto repair?
+ {
+ self.enemy.health = min(self.enemy.health + self.shot_dmg,self.enemy.max_health);
+ self.enemy.tur_health = min(self.enemy.tur_health + self.shot_dmg,self.enemy.max_health);
+ }
fl_org = 0.5 * (self.enemy.absmin + self.enemy.absmax);
te_smallflash(fl_org);
}
return 0;
if (self.ammo < self.shot_dmg)
- return 0;
+ return 0;
+
+ if (vlen(self.enemy.origin - self.origin) > self.target_range)
+ return 0;
+ if(g_td)
+ {
+ if(self.realowner != self.enemy.realowner)
+ return 0;
+
+ if(self.enemy.turrcaps_flags & TFL_TURRCAPS_AMMOSOURCE)
+ return 0;
+
+ if(self.enemy.health >= self.enemy.max_health)
+ return 0;
+ }
+
if (self.enemy.ammo >= self.enemy.ammo_max)
return 0;
- if (vlen(self.enemy.origin - self.origin) > self.target_range)
- return 0;
-
- if(self.team != self.enemy.team)
+ if(teamplay && self.team != self.enemy.team)
return 0;
if not (self.enemy.ammo_flags & TFL_AMMO_ENERGY)
m_speed = vlen(self.velocity);
// Enemy dead? just keep on the current heading then.
- if (self.enemy == world || self.enemy.deadflag != DEAD_NO)
+ if (self.enemy == world || self.enemy.deadflag != DEAD_NO || (g_td && !(self.enemy.flags & FL_MONSTER || self.enemy.classname == "td_generator")) || self.enemy.classname == "td_generator")
self.enemy = world;
if (self.enemy)
#include "w_rifle.qc"
#include "w_fireball.qc"
#include "w_seeker.qc"
+#include "w_incubator.qc"
return;
}
- if (owner_player.weaponentity.state != WS_INUSE || !lgbeam_checkammo() || owner_player.deadflag != DEAD_NO || !owner_player.BUTTON_ATCK || owner_player.freezetag_frozen)
+ if (owner_player.weaponentity.state != WS_INUSE || !lgbeam_checkammo() || owner_player.deadflag != DEAD_NO || !owner_player.BUTTON_ATCK || owner_player.freezetag_frozen || owner_player.frozen)
{
if(self == owner_player.lgbeam)
owner_player.lgbeam = world;
--- /dev/null
+set g_za 0 "Enable zombie apocalypse mutator"
+set g_za_monster_count 20
\ No newline at end of file