]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Merge branch 'master' into TimePath/deathtypes 234/head
authorTimePath <andrew.hardaker1995@gmail.com>
Sun, 11 Oct 2015 22:38:36 +0000 (09:38 +1100)
committerTimePath <andrew.hardaker1995@gmail.com>
Sun, 11 Oct 2015 22:39:59 +0000 (09:39 +1100)
# Conflicts:
# qcsrc/client/damage.qc
# qcsrc/client/hud.qc
# qcsrc/client/main.qc
# qcsrc/client/progs.inc
# qcsrc/common/vehicles/vehicle/raptor_weapons.qc
# qcsrc/common/weapons/all.qc
# qcsrc/server/cheats.qc
# qcsrc/server/g_world.qc
# qcsrc/server/teamplay.qc

386 files changed:
defaultXonotic.cfg
physics.cfg
physicsCPMA.cfg
physicsFruit.cfg
physicsHavoc.cfg
physicsLeeStricklin-ModdedFruit.cfg
physicsLeeStricklin.cfg
physicsLeeStricklinOld.cfg
physicsLzd.cfg
physicsNexuiz10.cfg
physicsNexuiz11.cfg
physicsNexuiz151.cfg
physicsNexuiz151b.cfg
physicsNexuiz16rc1.cfg
physicsNexuiz20.cfg
physicsNexuiz25.cfg
physicsNexuiz26.cfg
physicsNoQWBunny-nexbased.cfg
physicsQ.cfg
physicsQ2.cfg
physicsQ2a.cfg
physicsQ3.cfg
physicsQBF.cfg
physicsQBFplus.cfg
physicsSamual.cfg
physicsWarsow.cfg
physicsWarsowClassicBunny.cfg
physicsWarsowDev.cfg
qcsrc/.gitignore [new file with mode: 0644]
qcsrc/Doxyfile [new file with mode: 0644]
qcsrc/Makefile
qcsrc/client/_all.qh
qcsrc/client/announcer.qc
qcsrc/client/announcer.qh
qcsrc/client/bgmscript.qc
qcsrc/client/bgmscript.qh
qcsrc/client/command/all.qc [deleted file]
qcsrc/client/command/all.qh [deleted file]
qcsrc/client/command/cl_cmd.qc [deleted file]
qcsrc/client/command/cl_cmd.qh [deleted file]
qcsrc/client/commands/all.qc [new file with mode: 0644]
qcsrc/client/commands/all.qh [new file with mode: 0644]
qcsrc/client/commands/cl_cmd.qc [new file with mode: 0644]
qcsrc/client/commands/cl_cmd.qh [new file with mode: 0644]
qcsrc/client/controlpoint.qc
qcsrc/client/controlpoint.qh
qcsrc/client/csqc_constants.qh
qcsrc/client/csqcmodel_hooks.qc
qcsrc/client/damage.qc
qcsrc/client/damage.qh
qcsrc/client/effects.qc
qcsrc/client/effects.qh
qcsrc/client/generator.qc
qcsrc/client/generator.qh
qcsrc/client/gibs.qc
qcsrc/client/gibs.qh
qcsrc/client/hook.qc
qcsrc/client/hook.qh
qcsrc/client/hud.qc
qcsrc/client/hud.qh
qcsrc/client/hud_config.qc
qcsrc/client/hud_config.qh
qcsrc/client/laser.qc
qcsrc/client/laser.qh
qcsrc/client/main.qc
qcsrc/client/main.qh
qcsrc/client/mapvoting.qc
qcsrc/client/mapvoting.qh
qcsrc/client/miscfunctions.qc
qcsrc/client/miscfunctions.qh
qcsrc/client/modeleffects.qc
qcsrc/client/modeleffects.qh
qcsrc/client/particles.qc
qcsrc/client/particles.qh
qcsrc/client/player_skeleton.qc
qcsrc/client/player_skeleton.qh
qcsrc/client/progs.inc
qcsrc/client/quickmenu.qc
qcsrc/client/quickmenu.qh [new file with mode: 0644]
qcsrc/client/rubble.qh
qcsrc/client/scoreboard.qc
qcsrc/client/scoreboard.qh
qcsrc/client/shownames.qc
qcsrc/client/shownames.qh
qcsrc/client/t_items.qc
qcsrc/client/teamradar.qc
qcsrc/client/teamradar.qh
qcsrc/client/tuba.qc
qcsrc/client/tuba.qh
qcsrc/client/view.qc
qcsrc/client/wall.qc
qcsrc/client/wall.qh
qcsrc/client/weapons/projectile.qc
qcsrc/client/weapons/projectile.qh
qcsrc/common/animdecide.qc
qcsrc/common/buffs/all.qc
qcsrc/common/campaign_file.qc
qcsrc/common/campaign_setup.qc
qcsrc/common/command/all.qh
qcsrc/common/command/command.qh
qcsrc/common/command/generic.qc
qcsrc/common/effects/all.inc [new file with mode: 0644]
qcsrc/common/effects/all.qc [new file with mode: 0644]
qcsrc/common/effects/all.qh [new file with mode: 0644]
qcsrc/common/effects/effect.qh [new file with mode: 0644]
qcsrc/common/effects/effectinfo.qc
qcsrc/common/effects/effects.inc [deleted file]
qcsrc/common/effects/effects.qc [deleted file]
qcsrc/common/effects/effects.qh [deleted file]
qcsrc/common/gamemodes/all.inc [new file with mode: 0644]
qcsrc/common/gamemodes/all.qc [new file with mode: 0644]
qcsrc/common/gamemodes/all.qh [new file with mode: 0644]
qcsrc/common/gamemodes/gamemode/nexball/nexball.qc [new file with mode: 0644]
qcsrc/common/gamemodes/gamemode/nexball/nexball.qh [new file with mode: 0644]
qcsrc/common/gamemodes/gamemode/nexball/weapon.qc [new file with mode: 0644]
qcsrc/common/items/all.inc
qcsrc/common/items/all.qh
qcsrc/common/items/item.qh
qcsrc/common/items/item/powerup.qc
qcsrc/common/mapinfo.qc
qcsrc/common/minigames/cl_minigames.qh
qcsrc/common/minigames/cl_minigames_hud.qc
qcsrc/common/minigames/cl_minigames_hud.qh [new file with mode: 0644]
qcsrc/common/minigames/minigame/c4.qc
qcsrc/common/minigames/minigame/pp.qc
qcsrc/common/minigames/minigame/snake.qc
qcsrc/common/minigames/sv_minigames.qc
qcsrc/common/models/all.qh
qcsrc/common/models/model.qh [new file with mode: 0644]
qcsrc/common/monsters/monster.qh
qcsrc/common/monsters/monster/mage.qc
qcsrc/common/monsters/monster/shambler.qc
qcsrc/common/monsters/monster/spider.qc
qcsrc/common/monsters/monster/wyvern.qc
qcsrc/common/monsters/monster/zombie.qc
qcsrc/common/monsters/spawn.qc
qcsrc/common/monsters/sv_monsters.qc
qcsrc/common/monsters/sv_monsters.qh
qcsrc/common/movetypes/movetypes.qc
qcsrc/common/mutators/all.inc
qcsrc/common/mutators/all.qc
qcsrc/common/mutators/all.qh [new file with mode: 0644]
qcsrc/common/mutators/base.qh
qcsrc/common/mutators/mutator/casings.qc
qcsrc/common/mutators/mutator/damagetext.qc
qcsrc/common/mutators/mutator/instagib/instagib.qc [new file with mode: 0644]
qcsrc/common/mutators/mutator/instagib/items.qc [new file with mode: 0644]
qcsrc/common/mutators/mutator/itemstime.qc
qcsrc/common/mutators/mutator/waypoints/waypointsprites.qc
qcsrc/common/nades/all.qc
qcsrc/common/notifications.qc
qcsrc/common/notifications.qh
qcsrc/common/physics.qc
qcsrc/common/physics.qh
qcsrc/common/playerstats.qc
qcsrc/common/sounds/all.inc
qcsrc/common/sounds/all.qh
qcsrc/common/sounds/sound.qh [new file with mode: 0644]
qcsrc/common/stats.qh
qcsrc/common/triggers/func/breakable.qc
qcsrc/common/triggers/misc/laser.qc
qcsrc/common/triggers/subs.qh
qcsrc/common/triggers/target/music.qc
qcsrc/common/triggers/target/spawn.qc
qcsrc/common/triggers/teleporters.qc
qcsrc/common/triggers/trigger/jumppads.qc
qcsrc/common/triggers/trigger/secret.qc
qcsrc/common/triggers/trigger/swamp.qc
qcsrc/common/triggers/trigger/viewloc.qc
qcsrc/common/turrets/all.qh
qcsrc/common/util-post.qh [deleted file]
qcsrc/common/util-pre.qh [deleted file]
qcsrc/common/util.qc
qcsrc/common/util.qh
qcsrc/common/vehicles/sv_vehicles.qc
qcsrc/common/vehicles/vehicle/racer.qc
qcsrc/common/vehicles/vehicle/raptor_weapons.qc
qcsrc/common/viewloc.qc
qcsrc/common/weapons/all.inc
qcsrc/common/weapons/all.qc
qcsrc/common/weapons/all.qh
qcsrc/common/weapons/config.qc
qcsrc/common/weapons/config.qh
qcsrc/csqcmodellib/cl_model.qc [deleted file]
qcsrc/csqcmodellib/cl_model.qh [deleted file]
qcsrc/csqcmodellib/cl_player.qc [deleted file]
qcsrc/csqcmodellib/cl_player.qh [deleted file]
qcsrc/csqcmodellib/common.qh [deleted file]
qcsrc/csqcmodellib/interpolate.qc [deleted file]
qcsrc/csqcmodellib/interpolate.qh [deleted file]
qcsrc/csqcmodellib/settings.qh [deleted file]
qcsrc/csqcmodellib/sv_model.qc [deleted file]
qcsrc/csqcmodellib/sv_model.qh [deleted file]
qcsrc/lib/_all.inc
qcsrc/lib/bool.qh
qcsrc/lib/color.qh [new file with mode: 0644]
qcsrc/lib/compiler.qh [new file with mode: 0644]
qcsrc/lib/csqcmodel/cl_model.qc [new file with mode: 0644]
qcsrc/lib/csqcmodel/cl_model.qh [new file with mode: 0644]
qcsrc/lib/csqcmodel/cl_player.qc [new file with mode: 0644]
qcsrc/lib/csqcmodel/cl_player.qh [new file with mode: 0644]
qcsrc/lib/csqcmodel/common.qh [new file with mode: 0644]
qcsrc/lib/csqcmodel/interpolate.qc [new file with mode: 0644]
qcsrc/lib/csqcmodel/interpolate.qh [new file with mode: 0644]
qcsrc/lib/csqcmodel/settings.qh [new file with mode: 0644]
qcsrc/lib/csqcmodel/sv_model.qc [new file with mode: 0644]
qcsrc/lib/csqcmodel/sv_model.qh [new file with mode: 0644]
qcsrc/lib/defer.qh
qcsrc/lib/functional.qh [new file with mode: 0644]
qcsrc/lib/int.qh [new file with mode: 0644]
qcsrc/lib/iter.qh [new file with mode: 0644]
qcsrc/lib/misc.qh [new file with mode: 0644]
qcsrc/lib/nil.qh
qcsrc/lib/oo.qh
qcsrc/lib/registry.qh
qcsrc/lib/self.qh [new file with mode: 0644]
qcsrc/lib/test.qh
qcsrc/lib/urllib.qh
qcsrc/lib/warpzone/COPYING [new file with mode: 0644]
qcsrc/lib/warpzone/TODO [new file with mode: 0644]
qcsrc/lib/warpzone/anglestransform.qc [new file with mode: 0644]
qcsrc/lib/warpzone/anglestransform.qh [new file with mode: 0644]
qcsrc/lib/warpzone/client.qc [new file with mode: 0644]
qcsrc/lib/warpzone/client.qh [new file with mode: 0644]
qcsrc/lib/warpzone/common.qc [new file with mode: 0644]
qcsrc/lib/warpzone/common.qh [new file with mode: 0644]
qcsrc/lib/warpzone/mathlib.qc [new file with mode: 0644]
qcsrc/lib/warpzone/mathlib.qh [new file with mode: 0644]
qcsrc/lib/warpzone/server.qc [new file with mode: 0644]
qcsrc/lib/warpzone/server.qh [new file with mode: 0644]
qcsrc/lib/warpzone/util_server.qc [new file with mode: 0644]
qcsrc/lib/warpzone/util_server.qh [new file with mode: 0644]
qcsrc/menu/_all.qh
qcsrc/menu/anim/animation.qc
qcsrc/menu/anim/animhost.qc
qcsrc/menu/command/menu_cmd.qc
qcsrc/menu/gamesettings.qh
qcsrc/menu/item.qc
qcsrc/menu/item/modalcontroller.qc
qcsrc/menu/item/slider.qc
qcsrc/menu/menu.qc
qcsrc/menu/menu.qh
qcsrc/menu/oo/base.qh [deleted file]
qcsrc/menu/oo/classes.qc
qcsrc/menu/progs.inc
qcsrc/menu/xonotic/cvarlist.qc
qcsrc/menu/xonotic/dialog_multiplayer_media_screenshot_viewer.qc
qcsrc/menu/xonotic/mainwindow.qc
qcsrc/menu/xonotic/screenshotlist.qc
qcsrc/menu/xonotic/serverlist.qc
qcsrc/menu/xonotic/soundlist.qc
qcsrc/menu/xonotic/util.qc
qcsrc/server/_all.qh
qcsrc/server/anticheat.qc
qcsrc/server/antilag.qc
qcsrc/server/bot/_all.inc [new file with mode: 0644]
qcsrc/server/bot/aim.qc
qcsrc/server/bot/bot.qc
qcsrc/server/bot/havocbot/_all.inc [new file with mode: 0644]
qcsrc/server/bot/havocbot/havocbot.qc
qcsrc/server/bot/havocbot/role_keyhunt.qc
qcsrc/server/bot/havocbot/roles.qc
qcsrc/server/bot/navigation.qc
qcsrc/server/bot/scripting.qc
qcsrc/server/bot/waypoints.qc
qcsrc/server/cheats.qc
qcsrc/server/cl_client.qc
qcsrc/server/cl_impulse.qc
qcsrc/server/cl_player.qc
qcsrc/server/command/banning.qc
qcsrc/server/command/cmd.qc
qcsrc/server/command/cmd.qh
qcsrc/server/command/common.qc
qcsrc/server/command/getreplies.qc
qcsrc/server/command/radarmap.qc
qcsrc/server/command/sv_cmd.qc
qcsrc/server/command/vote.qc
qcsrc/server/controlpoint.qc
qcsrc/server/csqceffects.qc
qcsrc/server/ent_cs.qc
qcsrc/server/g_damage.qc
qcsrc/server/g_damage.qh
qcsrc/server/g_hook.qc
qcsrc/server/g_lights.qc
qcsrc/server/g_models.qc
qcsrc/server/g_subs.qc
qcsrc/server/g_violence.qc
qcsrc/server/g_world.qc
qcsrc/server/ipban.qc
qcsrc/server/item_key.qc
qcsrc/server/mapvoting.qc
qcsrc/server/miscfunctions.qc
qcsrc/server/mutators/gamemode.qh
qcsrc/server/mutators/gamemode_assault.qc
qcsrc/server/mutators/gamemode_ca.qc
qcsrc/server/mutators/gamemode_ctf.qc
qcsrc/server/mutators/gamemode_cts.qc
qcsrc/server/mutators/gamemode_deathmatch.qc
qcsrc/server/mutators/gamemode_domination.qc
qcsrc/server/mutators/gamemode_freezetag.qc
qcsrc/server/mutators/gamemode_invasion.qc
qcsrc/server/mutators/gamemode_keepaway.qc
qcsrc/server/mutators/gamemode_keyhunt.qc
qcsrc/server/mutators/gamemode_lms.qc
qcsrc/server/mutators/gamemode_nexball.qc [deleted file]
qcsrc/server/mutators/gamemode_nexball.qh [deleted file]
qcsrc/server/mutators/gamemode_nexball_weapon.qc [deleted file]
qcsrc/server/mutators/gamemode_onslaught.qc
qcsrc/server/mutators/gamemode_race.qc
qcsrc/server/mutators/gamemode_tdm.qc
qcsrc/server/mutators/mutator.qh
qcsrc/server/mutators/mutator_bloodloss.qc
qcsrc/server/mutators/mutator_breakablehook.qc
qcsrc/server/mutators/mutator_buffs.qc
qcsrc/server/mutators/mutator_campcheck.qc
qcsrc/server/mutators/mutator_dodging.qc
qcsrc/server/mutators/mutator_instagib.qc [deleted file]
qcsrc/server/mutators/mutator_instagib_items.qc [deleted file]
qcsrc/server/mutators/mutator_invincibleproj.qc
qcsrc/server/mutators/mutator_melee_only.qc
qcsrc/server/mutators/mutator_midair.qc
qcsrc/server/mutators/mutator_multijump.qc
qcsrc/server/mutators/mutator_nades.qc
qcsrc/server/mutators/mutator_new_toys.qc
qcsrc/server/mutators/mutator_nix.qc
qcsrc/server/mutators/mutator_overkill.qc
qcsrc/server/mutators/mutator_physical_items.qc
qcsrc/server/mutators/mutator_pinata.qc
qcsrc/server/mutators/mutator_random_gravity.qc
qcsrc/server/mutators/mutator_rocketflying.qc
qcsrc/server/mutators/mutator_rocketminsta.qc
qcsrc/server/mutators/mutator_spawn_near_teammate.qc
qcsrc/server/mutators/mutator_superspec.qc
qcsrc/server/mutators/mutator_touchexplode.qc
qcsrc/server/mutators/mutator_vampire.qc
qcsrc/server/mutators/mutators.qc
qcsrc/server/mutators/mutators.qh
qcsrc/server/mutators/mutators_include.qc
qcsrc/server/mutators/mutators_include.qh
qcsrc/server/mutators/sandbox.qc
qcsrc/server/pathlib/_all.inc [new file with mode: 0644]
qcsrc/server/pathlib/debug.qc
qcsrc/server/pathlib/main.qc
qcsrc/server/pathlib/movenode.qc
qcsrc/server/pathlib/pathlib.qh
qcsrc/server/playerdemo.qc
qcsrc/server/portals.qc
qcsrc/server/progs.inc
qcsrc/server/race.qc
qcsrc/server/round_handler.qc
qcsrc/server/scores.qc
qcsrc/server/scores_rules.qc
qcsrc/server/spawnpoints.qc
qcsrc/server/steerlib.qc
qcsrc/server/sv_main.qc
qcsrc/server/t_items.qc
qcsrc/server/t_items.qh
qcsrc/server/t_quake.qc
qcsrc/server/t_quake3.qc
qcsrc/server/teamplay.qc
qcsrc/server/teamplay.qh
qcsrc/server/weapons/accuracy.qc
qcsrc/server/weapons/common.qc
qcsrc/server/weapons/csqcprojectile.qc
qcsrc/server/weapons/hitplot.qc
qcsrc/server/weapons/selection.qc
qcsrc/server/weapons/spawning.qc
qcsrc/server/weapons/throwing.qc
qcsrc/server/weapons/tracing.qc
qcsrc/server/weapons/weaponstats.qc
qcsrc/server/weapons/weaponsystem.qc
qcsrc/test/compilationunit.sh
qcsrc/warpzonelib/COPYING [deleted file]
qcsrc/warpzonelib/TODO [deleted file]
qcsrc/warpzonelib/anglestransform.qc [deleted file]
qcsrc/warpzonelib/anglestransform.qh [deleted file]
qcsrc/warpzonelib/client.qc [deleted file]
qcsrc/warpzonelib/client.qh [deleted file]
qcsrc/warpzonelib/common.qc [deleted file]
qcsrc/warpzonelib/common.qh [deleted file]
qcsrc/warpzonelib/mathlib.qc [deleted file]
qcsrc/warpzonelib/mathlib.qh [deleted file]
qcsrc/warpzonelib/server.qc [deleted file]
qcsrc/warpzonelib/server.qh [deleted file]
qcsrc/warpzonelib/util_server.qc [deleted file]
qcsrc/warpzonelib/util_server.qh [deleted file]

index 0afdb7af70254056edf38c1153d4bc057fa55993..3735e55349da0713a11e59317ead64ebe0d13610 100644 (file)
@@ -305,6 +305,7 @@ set sv_doublejump 0 "allow Quake 2-style double jumps"
 set sv_jumpspeedcap_min "" "lower bound on the baseline velocity of a jump; final velocity will be >= (jumpheight * min + jumpheight)"
 set sv_jumpspeedcap_max "" "upper bound on the baseline velocity of a jump; final velocity will be <= (jumpheight * max + jumpheight)"
 set sv_jumpspeedcap_max_disable_on_ramps 0 "disable upper baseline velocity bound on ramps to preserve the old rampjump style"
+set sv_track_canjump 0 "track if the player released the jump key between 2 jumps to decide if they are able to jump or not"
 
 seta sv_precacheplayermodels 1
 seta sv_precacheweapons 0
index 58d1b1f81d058263aa59c1ddd779f758c72b7e21..e9fe5628940d9597fd5843533b54bced13066ae0 100644 (file)
@@ -38,6 +38,7 @@ set g_physics_xonotic_accelerate 15
 set g_physics_xonotic_stopspeed 100
 set g_physics_xonotic_airaccelerate 2
 set g_physics_xonotic_airstopaccelerate 3
+set g_physics_xonotic_track_canjump 0
 
 // ========
 //  Nexuiz
@@ -65,6 +66,7 @@ set g_physics_nexuiz_accelerate 8
 set g_physics_nexuiz_stopspeed 100
 set g_physics_nexuiz_airaccelerate 5.5
 set g_physics_nexuiz_airstopaccelerate 0
+set g_physics_nexuiz_track_canjump 0
 
 // =======
 //  Quake
@@ -92,6 +94,7 @@ set g_physics_quake_accelerate 10
 set g_physics_quake_stopspeed 100
 set g_physics_quake_airaccelerate 106.66666666666666666666
 set g_physics_quake_airstopaccelerate 0
+set g_physics_quake_track_canjump 1
 
 // ========
 //  Warsow
@@ -119,6 +122,7 @@ set g_physics_warsow_accelerate 15
 set g_physics_warsow_stopspeed 100
 set g_physics_warsow_airaccelerate 1
 set g_physics_warsow_airstopaccelerate 2.5
+set g_physics_warsow_track_canjump 0
 
 // ========
 //  DeFrag
@@ -146,6 +150,7 @@ set g_physics_defrag_accelerate 15
 set g_physics_defrag_stopspeed 100
 set g_physics_defrag_airaccelerate 1
 set g_physics_defrag_airstopaccelerate 2.5
+set g_physics_defrag_track_canjump 0
 
 // =========
 //  Quake 3
@@ -173,6 +178,7 @@ set g_physics_quake3_accelerate 10
 set g_physics_quake3_stopspeed 100
 set g_physics_quake3_airaccelerate 1
 set g_physics_quake3_airstopaccelerate 0
+set g_physics_quake3_track_canjump 1
 
 // ========
 //  Vecxis
@@ -200,6 +206,7 @@ set g_physics_vecxis_accelerate 5.5
 set g_physics_vecxis_stopspeed 100
 set g_physics_vecxis_airaccelerate 5.5
 set g_physics_vecxis_airstopaccelerate 0
+set g_physics_vecxis_track_canjump 0
 
 // =========
 //  Quake 2
@@ -227,6 +234,7 @@ set g_physics_quake2_accelerate 10
 set g_physics_quake2_stopspeed 100
 set g_physics_quake2_airaccelerate 1
 set g_physics_quake2_airstopaccelerate 0
+set g_physics_quake2_track_canjump 1
 
 // =======
 //  Bones
@@ -254,3 +262,4 @@ set g_physics_bones_accelerate 15
 set g_physics_bones_stopspeed 100
 set g_physics_bones_airaccelerate 1
 set g_physics_bones_airstopaccelerate 2.5
+set g_physics_bones_track_canjump 0
index 9734cfc6f6ccc1180a9925105814321f1d5ed69f..e4bbad3d48630aa95c9f3463fdd1d327c7323a12 100644 (file)
@@ -34,3 +34,4 @@ sv_jumpspeedcap_min ""
 sv_jumpspeedcap_max ""
 sv_jumpspeedcap_max_disable_on_ramps 0
 g_teleport_maxspeed 400
+sv_track_canjump 0
index 5f65d66d8ab36e6b6e2349174c15431ea20e6e3f..ee44b5547a052717cde7f28fb0f52063e638c65f 100644 (file)
@@ -33,3 +33,4 @@ sv_jumpspeedcap_min 0 // need predicting? (it should already be in CSQC predicti
 sv_jumpspeedcap_max 0.35
 sv_jumpspeedcap_max_disable_on_ramps 1
 g_teleport_maxspeed 0
+sv_track_canjump 0
index f107158720dc50d26d0dcc014a5a4eb23ae8ddbe..6aac341780e7573cbe580b714e62b747d61e6612 100644 (file)
@@ -34,3 +34,4 @@ sv_jumpspeedcap_min ""
 sv_jumpspeedcap_max ""
 sv_jumpspeedcap_max_disable_on_ramps 0
 g_teleport_maxspeed 0
+sv_track_canjump 0
index 3553a94a7e587a415a24613aaf735392622e6a53..90eaa49c1223cd4bacf7aa7e228dc4670f88240b 100644 (file)
@@ -42,3 +42,4 @@ sv_jumpspeedcap_min 0 // need predicting? (it should already be in CSQC predicti
 sv_jumpspeedcap_max ""
 sv_jumpspeedcap_max_disable_on_ramps 1
 g_teleport_maxspeed 0
+sv_track_canjump 0
index e4aef4440d6b5b173e141962d3e429077216ab31..03081fdab7554b9c5118b795ac8b86987ff966a6 100644 (file)
@@ -42,3 +42,4 @@ sv_jumpspeedcap_min ""
 sv_jumpspeedcap_max ""
 sv_jumpspeedcap_max_disable_on_ramps 1
 g_teleport_maxspeed 0
+sv_track_canjump 0
index eda92ac6930431893efd7865b83f26d45efecffc..ef213a70f9d356226b401c0779752d85d69c7157 100644 (file)
@@ -37,3 +37,4 @@ sv_jumpspeedcap_min ""
 sv_jumpspeedcap_max 0.38
 sv_jumpspeedcap_max_disable_on_ramps 0
 g_teleport_maxspeed 0
+sv_track_canjump 0
index cd76c2fe39f557fd6bb50133fddc8dad880dc1e6..51c49d7832dbf0197ca6a2ab5d456389ce675ebf 100644 (file)
@@ -35,3 +35,4 @@ sv_jumpspeedcap_min ""
 sv_jumpspeedcap_max ""
 sv_jumpspeedcap_max_disable_on_ramps 0
 g_teleport_maxspeed 0
+sv_track_canjump 0
index 6c99b307f00f74d41e90e6d95b5db96dcacb2e20..0ce33aa95132362f57bb28eeec904c6549bed91e 100644 (file)
@@ -35,3 +35,4 @@ sv_jumpspeedcap_min ""
 sv_jumpspeedcap_max ""
 sv_jumpspeedcap_max_disable_on_ramps 0
 g_teleport_maxspeed 0
+sv_track_canjump 0
index 65a6a4b6fc40b9a67fc91d4936cee4095e32ebd2..08711fd5b0f6905b33ff2688261f0e0543611922 100644 (file)
@@ -34,3 +34,4 @@ sv_jumpspeedcap_min ""
 sv_jumpspeedcap_max ""
 sv_jumpspeedcap_max_disable_on_ramps 0
 g_teleport_maxspeed 0
+sv_track_canjump 0
index 833a67dce383f608a8051938cdffa905d55f3d4d..092985cae51a00a87a76cf26a78519c9f5d3f127 100644 (file)
@@ -34,3 +34,4 @@ sv_jumpspeedcap_min ""
 sv_jumpspeedcap_max ""
 sv_jumpspeedcap_max_disable_on_ramps 0
 g_teleport_maxspeed 0
+sv_track_canjump 0
index 31380c973828580dc2fe523cac5715e59e8ab020..c6d9bef4b912d82e5200691d82a3fb55627b4d88 100644 (file)
@@ -34,3 +34,4 @@ sv_jumpspeedcap_min ""
 sv_jumpspeedcap_max ""
 sv_jumpspeedcap_max_disable_on_ramps 0
 g_teleport_maxspeed 0
+sv_track_canjump 0
index f3a85e50b7cf4d03556fd315f7b731b5d4125ec6..5e0ee6ae0c6f265690c3783be05c3d10f35a1d19 100644 (file)
@@ -34,3 +34,4 @@ sv_jumpspeedcap_min ""
 sv_jumpspeedcap_max ""
 sv_jumpspeedcap_max_disable_on_ramps 0
 g_teleport_maxspeed 0
+sv_track_canjump 0
index 60071e1844026fb1bb9fb04e695d19247295f33b..d129a2db05ebada4a9698aeafcfedbb9456ac2d9 100644 (file)
@@ -34,3 +34,4 @@ sv_jumpspeedcap_min ""
 sv_jumpspeedcap_max ""
 sv_jumpspeedcap_max_disable_on_ramps 0
 g_teleport_maxspeed 0
+sv_track_canjump 0
index dd984bb310c1a8c2299df157edc8b751e20d05d5..8a52299763d537423fb2012f6a9ed304c969ef0e 100644 (file)
@@ -34,3 +34,4 @@ sv_jumpspeedcap_min ""
 sv_jumpspeedcap_max ""
 sv_jumpspeedcap_max_disable_on_ramps 0
 g_teleport_maxspeed 0
+sv_track_canjump 0
index 827bbc55c16501e6ee64e509b4313f8612a0d3c4..4df3f211ebe490134394e21d60a35a0b739fae6b 100644 (file)
@@ -34,3 +34,4 @@ sv_jumpspeedcap_min ""
 sv_jumpspeedcap_max ""
 sv_jumpspeedcap_max_disable_on_ramps 0
 g_teleport_maxspeed 0
+sv_track_canjump 0
index f8d43c4f2ece249c7fe52776ce6bae5c7577a535..3e905428f76d52f1183cde4fc116ccabc0268afa 100644 (file)
@@ -43,3 +43,4 @@ sv_jumpspeedcap_min ""
 sv_jumpspeedcap_max ""
 sv_jumpspeedcap_max_disable_on_ramps 1
 g_teleport_maxspeed 0
+sv_track_canjump 0
index c26745629677cf209b65c223eb60d5abfd6a9436..448e087f46f20c1d0287dfd29c9a605a93266fcc 100644 (file)
@@ -35,3 +35,4 @@ sv_jumpspeedcap_min ""
 sv_jumpspeedcap_max ""
 sv_jumpspeedcap_max_disable_on_ramps 0
 g_teleport_maxspeed 0
+sv_track_canjump 0
index 05e2f1456cdd5152935fe084e730f717069dc4cd..124c50660a1046ca8bf9ce7245a4d9579a0ff71c 100644 (file)
@@ -34,3 +34,4 @@ sv_jumpspeedcap_min ""
 sv_jumpspeedcap_max ""
 sv_jumpspeedcap_max_disable_on_ramps 0
 g_teleport_maxspeed 0
+sv_track_canjump 0
index 9b953e32e8b78b8852f663ed4e55668da55a1b1a..580f6257fa65f2bde52c74983f72492e45456f2f 100644 (file)
@@ -35,3 +35,4 @@ sv_jumpspeedcap_min ""
 sv_jumpspeedcap_max ""
 sv_jumpspeedcap_max_disable_on_ramps 0
 g_teleport_maxspeed 0
+sv_track_canjump 0
index eed1c7409008447be660d6b84b73e57da536d11f..6f00896b671b4b542115d6270c96b4bac7d08c20 100644 (file)
@@ -34,3 +34,4 @@ sv_jumpspeedcap_min ""
 sv_jumpspeedcap_max ""
 sv_jumpspeedcap_max_disable_on_ramps 0
 g_teleport_maxspeed 320
+sv_track_canjump 0
index 8dff0edd9df5d208440a721a04fce1e236a5722a..31963e9feee4dc1dc6691514a081bde9d3765c7f 100644 (file)
@@ -34,3 +34,4 @@ sv_jumpspeedcap_min ""
 sv_jumpspeedcap_max ""
 sv_jumpspeedcap_max_disable_on_ramps 0
 g_teleport_maxspeed 0
+sv_track_canjump 0
index 634b6083ee6c910a69442de8430c8251e2781bb7..82463859835480526e90bbae65db204238344fd7 100644 (file)
@@ -34,3 +34,4 @@ sv_jumpspeedcap_min ""
 sv_jumpspeedcap_max ""
 sv_jumpspeedcap_max_disable_on_ramps 0
 g_teleport_maxspeed 0
+sv_track_canjump 0
index 8019089bf216f7eb5749c8d12064a494ca0f7edd..6858892e3b3ad27b1c8a8e8d4257c7a650e269c6 100644 (file)
@@ -34,3 +34,4 @@ sv_jumpspeedcap_min ""
 sv_jumpspeedcap_max ""
 sv_jumpspeedcap_max_disable_on_ramps 0
 g_teleport_maxspeed 0
+sv_track_canjump 0
index 7d66b3716d987f96d48687973d7c09cfc7f1011d..50101d73d43165843ecf32f08b55fb33aff8fb2d 100644 (file)
@@ -34,3 +34,4 @@ sv_jumpspeedcap_min ""
 sv_jumpspeedcap_max ""
 sv_jumpspeedcap_max_disable_on_ramps 0
 g_teleport_maxspeed 0
+sv_track_canjump 0
index 1dbb14a90fb4f87d31359ee48ee84ea32ae11231..c4c3535a7f9ac1c74d3daa7a7c7645f4daaa9e27 100644 (file)
@@ -34,3 +34,4 @@ sv_jumpspeedcap_min ""
 sv_jumpspeedcap_max ""
 sv_jumpspeedcap_max_disable_on_ramps 0
 g_teleport_maxspeed 0
+sv_track_canjump 0
index f2f989d7580295a9ea237701d240ab7084dc7bb0..331723ec9317539cbc2b2e4bdc139a99b52abb94 100644 (file)
@@ -34,3 +34,4 @@ sv_jumpspeedcap_min ""
 sv_jumpspeedcap_max ""
 sv_jumpspeedcap_max_disable_on_ramps 0
 g_teleport_maxspeed 0
+sv_track_canjump 0
diff --git a/qcsrc/.gitignore b/qcsrc/.gitignore
new file mode 100644 (file)
index 0000000..5ccff1a
--- /dev/null
@@ -0,0 +1 @@
+html/
diff --git a/qcsrc/Doxyfile b/qcsrc/Doxyfile
new file mode 100644 (file)
index 0000000..f177a27
--- /dev/null
@@ -0,0 +1,2384 @@
+# Doxyfile 1.8.10
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project.
+#
+# All text after a double hash (##) is considered a comment and is placed in
+# front of the TAG it is preceding.
+#
+# All text after a single hash (#) is considered a comment and will be ignored.
+# The format is:
+# TAG = value [value, ...]
+# For lists, items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (\" \").
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all text
+# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv
+# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv
+# for the list of possible encodings.
+# The default value is: UTF-8.
+
+DOXYFILE_ENCODING      = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by
+# double-quotes, unless you are using Doxywizard) that should identify the
+# project for which the documentation is generated. This name is used in the
+# title of most generated pages and in a few other places.
+# The default value is: My Project.
+
+PROJECT_NAME           = "Xonotic"
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
+# could be handy for archiving the generated documentation or if some version
+# control system is used.
+
+PROJECT_NUMBER         =
+
+# Using the PROJECT_BRIEF tag one can provide an optional one line description
+# for a project that appears at the top of each page and should give viewer a
+# quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF          =
+
+# With the PROJECT_LOGO tag one can specify a logo or an icon that is included
+# in the documentation. The maximum height of the logo should not exceed 55
+# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy
+# the logo to the output directory.
+
+PROJECT_LOGO           =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
+# into which the generated documentation will be written. If a relative path is
+# entered, it will be relative to the location where doxygen was started. If
+# left blank the current directory will be used.
+
+OUTPUT_DIRECTORY       =
+
+# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub-
+# directories (in 2 levels) under the output directory of each output format and
+# will distribute the generated files over these directories. Enabling this
+# option can be useful when feeding doxygen a huge amount of source files, where
+# putting all generated files in the same directory would otherwise causes
+# performance problems for the file system.
+# The default value is: NO.
+
+CREATE_SUBDIRS         = NO
+
+# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII
+# characters to appear in the names of generated files. If set to NO, non-ASCII
+# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode
+# U+3044.
+# The default value is: NO.
+
+ALLOW_UNICODE_NAMES    = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,
+# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),
+# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,
+# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),
+# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,
+# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,
+# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,
+# Ukrainian and Vietnamese.
+# The default value is: English.
+
+OUTPUT_LANGUAGE        = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member
+# descriptions after the members that are listed in the file and class
+# documentation (similar to Javadoc). Set to NO to disable this.
+# The default value is: YES.
+
+BRIEF_MEMBER_DESC      = YES
+
+# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief
+# description of a member or function before the detailed description
+#
+# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+# The default value is: YES.
+
+REPEAT_BRIEF           = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator that is
+# used to form the text in various listings. Each string in this list, if found
+# as the leading text of the brief description, will be stripped from the text
+# and the result, after processing the whole list, is used as the annotated
+# text. Otherwise, the brief description is used as-is. If left blank, the
+# following values are used ($name is automatically replaced with the name of
+# the entity):The $name class, The $name widget, The $name file, is, provides,
+# specifies, contains, represents, a, an and the.
+
+ABBREVIATE_BRIEF       =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# doxygen will generate a detailed section even if there is only a brief
+# description.
+# The default value is: NO.
+
+ALWAYS_DETAILED_SEC    = YES
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+# The default value is: NO.
+
+INLINE_INHERITED_MEMB  = YES
+
+# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path
+# before files name in the file list and in the header files. If set to NO the
+# shortest path that makes the file name unique will be used
+# The default value is: YES.
+
+FULL_PATH_NAMES        = YES
+
+# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
+# Stripping is only done if one of the specified strings matches the left-hand
+# part of the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the path to
+# strip.
+#
+# Note that you can specify absolute paths here, but also relative paths, which
+# will be relative from the directory where doxygen is started.
+# This tag requires that the tag FULL_PATH_NAMES is set to YES.
+
+STRIP_FROM_PATH        =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
+# path mentioned in the documentation of a class, which tells the reader which
+# header file to include in order to use a class. If left blank only the name of
+# the header file containing the class definition is used. Otherwise one should
+# specify the list of include paths that are normally passed to the compiler
+# using the -I flag.
+
+STRIP_FROM_INC_PATH    =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
+# less readable) file names. This can be useful is your file systems doesn't
+# support long names like on DOS, Mac, or CD-ROM.
+# The default value is: NO.
+
+SHORT_NAMES            = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the
+# first line (until the first dot) of a Javadoc-style comment as the brief
+# description. If set to NO, the Javadoc-style will behave just like regular Qt-
+# style comments (thus requiring an explicit @brief command for a brief
+# description.)
+# The default value is: NO.
+
+JAVADOC_AUTOBRIEF      = YES
+
+# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
+# line (until the first dot) of a Qt-style comment as the brief description. If
+# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
+# requiring an explicit \brief command for a brief description.)
+# The default value is: NO.
+
+QT_AUTOBRIEF           = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a
+# multi-line C++ special comment block (i.e. a block of //! or /// comments) as
+# a brief description. This used to be the default behavior. The new default is
+# to treat a multi-line C++ comment block as a detailed description. Set this
+# tag to YES if you prefer the old behavior instead.
+#
+# Note that setting this tag to YES also means that rational rose comments are
+# not recognized any more.
+# The default value is: NO.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
+# documentation from any documented member that it re-implements.
+# The default value is: YES.
+
+INHERIT_DOCS           = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new
+# page for each member. If set to NO, the documentation of a member will be part
+# of the file/class/namespace that contains it.
+# The default value is: NO.
+
+SEPARATE_MEMBER_PAGES  = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen
+# uses this value to replace tabs by spaces in code fragments.
+# Minimum value: 1, maximum value: 16, default value: 4.
+
+TAB_SIZE               = 4
+
+# This tag can be used to specify a number of aliases that act as commands in
+# the documentation. An alias has the form:
+# name=value
+# For example adding
+# "sideeffect=@par Side Effects:\n"
+# will allow you to put the command \sideeffect (or @sideeffect) in the
+# documentation, which will result in a user-defined paragraph with heading
+# "Side Effects:". You can put \n's in the value part of an alias to insert
+# newlines.
+
+ALIASES                =
+
+# This tag can be used to specify a number of word-keyword mappings (TCL only).
+# A mapping has the form "name=value". For example adding "class=itcl::class"
+# will allow you to use the command class in the itcl::class meaning.
+
+TCL_SUBST              =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
+# only. Doxygen will then generate output that is more tailored for C. For
+# instance, some of the names that are used will be different. The list of all
+# members will be omitted, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_FOR_C  = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or
+# Python sources only. Doxygen will then generate output that is more tailored
+# for that language. For instance, namespaces will be presented as packages,
+# qualified scopes will look different, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_JAVA   = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources. Doxygen will then generate output that is tailored for Fortran.
+# The default value is: NO.
+
+OPTIMIZE_FOR_FORTRAN   = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for VHDL.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_VHDL   = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it
+# parses. With this tag you can assign which parser to use for a given
+# extension. Doxygen has a built-in mapping, but you can override or extend it
+# using this tag. The format is ext=language, where ext is a file extension, and
+# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
+# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran:
+# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran:
+# Fortran. In the later case the parser tries to guess whether the code is fixed
+# or free formatted code, this is the default for Fortran type files), VHDL. For
+# instance to make doxygen treat .inc files as Fortran files (default is PHP),
+# and .f files as C (default is Fortran), use: inc=Fortran f=C.
+#
+# Note: For files without extension you can use no_extension as a placeholder.
+#
+# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
+# the files are not read by doxygen.
+
+EXTENSION_MAPPING      = qc=C qh=C inc=C
+
+# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
+# according to the Markdown format, which allows for more readable
+# documentation. See http://daringfireball.net/projects/markdown/ for details.
+# The output of markdown processing is further processed by doxygen, so you can
+# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
+# case of backward compatibilities issues.
+# The default value is: YES.
+
+MARKDOWN_SUPPORT       = YES
+
+# When enabled doxygen tries to link words that correspond to documented
+# classes, or namespaces to their corresponding documentation. Such a link can
+# be prevented in individual cases by putting a % sign in front of the word or
+# globally by setting AUTOLINK_SUPPORT to NO.
+# The default value is: YES.
+
+AUTOLINK_SUPPORT       = YES
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should set this
+# tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string);
+# versus func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+# The default value is: NO.
+
+BUILTIN_STL_SUPPORT    = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+# The default value is: NO.
+
+CPP_CLI_SUPPORT        = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
+# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen
+# will parse them like normal C++ but will assume all classes use public instead
+# of private inheritance when no explicit protection keyword is present.
+# The default value is: NO.
+
+SIP_SUPPORT            = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate
+# getter and setter methods for a property. Setting this option to YES will make
+# doxygen to replace the get and set methods by a property in the documentation.
+# This will only work if the methods are indeed getting or setting a simple
+# type. If this is not the case, or you want to show the methods anyway, you
+# should set this option to NO.
+# The default value is: YES.
+
+IDL_PROPERTY_SUPPORT   = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+# The default value is: NO.
+
+DISTRIBUTE_GROUP_DOC   = NO
+
+# If one adds a struct or class to a group and this option is enabled, then also
+# any nested class or struct is added to the same group. By default this option
+# is disabled and one has to add nested compounds explicitly via \ingroup.
+# The default value is: NO.
+
+GROUP_NESTED_COMPOUNDS = NO
+
+# Set the SUBGROUPING tag to YES to allow class member groups of the same type
+# (for instance a group of public functions) to be put as a subgroup of that
+# type (e.g. under the Public Functions section). Set it to NO to prevent
+# subgrouping. Alternatively, this can be done per class using the
+# \nosubgrouping command.
+# The default value is: YES.
+
+SUBGROUPING            = YES
+
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions
+# are shown inside the group in which they are included (e.g. using \ingroup)
+# instead of on a separate page (for HTML and Man pages) or section (for LaTeX
+# and RTF).
+#
+# Note that this feature does not work in combination with
+# SEPARATE_MEMBER_PAGES.
+# The default value is: NO.
+
+INLINE_GROUPED_CLASSES = NO
+
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions
+# with only public data fields or simple typedef fields will be shown inline in
+# the documentation of the scope in which they are defined (i.e. file,
+# namespace, or group documentation), provided this scope is documented. If set
+# to NO, structs, classes, and unions are shown on a separate page (for HTML and
+# Man pages) or section (for LaTeX and RTF).
+# The default value is: NO.
+
+INLINE_SIMPLE_STRUCTS  = NO
+
+# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or
+# enum is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically be
+# useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+# The default value is: NO.
+
+TYPEDEF_HIDES_STRUCT   = YES
+
+# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
+# cache is used to resolve symbols given their name and scope. Since this can be
+# an expensive process and often the same symbol appears multiple times in the
+# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small
+# doxygen will become slower. If the cache is too large, memory is wasted. The
+# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range
+# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536
+# symbols. At the end of a run doxygen will report the cache usage and suggest
+# the optimal cache size from a speed point of view.
+# Minimum value: 0, maximum value: 9, default value: 0.
+
+LOOKUP_CACHE_SIZE      = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in
+# documentation are documented, even if no documentation was available. Private
+# class members and static file members will be hidden unless the
+# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
+# Note: This will also disable the warnings about undocumented members that are
+# normally produced when WARNINGS is set to YES.
+# The default value is: NO.
+
+EXTRACT_ALL            = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will
+# be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PRIVATE        = YES
+
+# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal
+# scope will be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PACKAGE        = YES
+
+# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be
+# included in the documentation.
+# The default value is: NO.
+
+EXTRACT_STATIC         = YES
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined
+# locally in source files will be included in the documentation. If set to NO,
+# only classes defined in header files are included. Does not have any effect
+# for Java sources.
+# The default value is: YES.
+
+EXTRACT_LOCAL_CLASSES  = YES
+
+# This flag is only useful for Objective-C code. If set to YES, local methods,
+# which are defined in the implementation section but not in the interface are
+# included in the documentation. If set to NO, only methods in the interface are
+# included.
+# The default value is: NO.
+
+EXTRACT_LOCAL_METHODS  = YES
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base name of
+# the file that contains the anonymous namespace. By default anonymous namespace
+# are hidden.
+# The default value is: NO.
+
+EXTRACT_ANON_NSPACES   = YES
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
+# undocumented members inside documented classes or files. If set to NO these
+# members will be included in the various overviews, but no documentation
+# section is generated. This option has no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_MEMBERS     = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy. If set
+# to NO, these classes will be included in the various overviews. This option
+# has no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_CLASSES     = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
+# (class|struct|union) declarations. If set to NO, these declarations will be
+# included in the documentation.
+# The default value is: NO.
+
+HIDE_FRIEND_COMPOUNDS  = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
+# documentation blocks found inside the body of a function. If set to NO, these
+# blocks will be appended to the function's detailed documentation block.
+# The default value is: NO.
+
+HIDE_IN_BODY_DOCS      = NO
+
+# The INTERNAL_DOCS tag determines if documentation that is typed after a
+# \internal command is included. If the tag is set to NO then the documentation
+# will be excluded. Set it to YES to include the internal documentation.
+# The default value is: NO.
+
+INTERNAL_DOCS          = YES
+
+# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
+# names in lower-case letters. If set to YES, upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+# The default value is: system dependent.
+
+CASE_SENSE_NAMES       = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
+# their full class and namespace scopes in the documentation. If set to YES, the
+# scope will be hidden.
+# The default value is: NO.
+
+HIDE_SCOPE_NAMES       = NO
+
+# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will
+# append additional text to a page's title, such as Class Reference. If set to
+# YES the compound reference will be hidden.
+# The default value is: NO.
+
+HIDE_COMPOUND_REFERENCE= NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
+# the files that are included by a file in the documentation of that file.
+# The default value is: YES.
+
+SHOW_INCLUDE_FILES     = YES
+
+# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each
+# grouped member an include statement to the documentation, telling the reader
+# which file to include in order to use the member.
+# The default value is: NO.
+
+SHOW_GROUPED_MEMB_INC  = YES
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include
+# files with double quotes in the documentation rather than with sharp brackets.
+# The default value is: NO.
+
+FORCE_LOCAL_INCLUDES   = NO
+
+# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the
+# documentation for inline members.
+# The default value is: YES.
+
+INLINE_INFO            = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
+# (detailed) documentation of file and class members alphabetically by member
+# name. If set to NO, the members will appear in declaration order.
+# The default value is: YES.
+
+SORT_MEMBER_DOCS       = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
+# descriptions of file, namespace and class members alphabetically by member
+# name. If set to NO, the members will appear in declaration order. Note that
+# this will also influence the order of the classes in the class list.
+# The default value is: NO.
+
+SORT_BRIEF_DOCS        = NO
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the
+# (brief and detailed) documentation of class members so that constructors and
+# destructors are listed first. If set to NO the constructors will appear in the
+# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.
+# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief
+# member documentation.
+# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting
+# detailed member documentation.
+# The default value is: NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy
+# of group names into alphabetical order. If set to NO the group names will
+# appear in their defined order.
+# The default value is: NO.
+
+SORT_GROUP_NAMES       = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by
+# fully-qualified names, including namespaces. If set to NO, the class list will
+# be sorted only by class name, not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the alphabetical
+# list.
+# The default value is: NO.
+
+SORT_BY_SCOPE_NAME     = NO
+
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper
+# type resolution of all parameters of a function it will reject a match between
+# the prototype and the implementation of a member function even if there is
+# only one candidate or it is obvious which candidate to choose by doing a
+# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still
+# accept a match between prototype and implementation in such cases.
+# The default value is: NO.
+
+STRICT_PROTO_MATCHING  = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo
+# list. This list is created by putting \todo commands in the documentation.
+# The default value is: YES.
+
+GENERATE_TODOLIST      = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test
+# list. This list is created by putting \test commands in the documentation.
+# The default value is: YES.
+
+GENERATE_TESTLIST      = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug
+# list. This list is created by putting \bug commands in the documentation.
+# The default value is: YES.
+
+GENERATE_BUGLIST       = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO)
+# the deprecated list. This list is created by putting \deprecated commands in
+# the documentation.
+# The default value is: YES.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional documentation
+# sections, marked by \if <section_label> ... \endif and \cond <section_label>
+# ... \endcond blocks.
+
+ENABLED_SECTIONS       =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
+# initial value of a variable or macro / define can have for it to appear in the
+# documentation. If the initializer consists of more lines than specified here
+# it will be hidden. Use a value of 0 to hide initializers completely. The
+# appearance of the value of individual variables and macros / defines can be
+# controlled using \showinitializer or \hideinitializer command in the
+# documentation regardless of this setting.
+# Minimum value: 0, maximum value: 10000, default value: 30.
+
+MAX_INITIALIZER_LINES  = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
+# the bottom of the documentation of classes and structs. If set to YES, the
+# list will mention the files that were used to generate the documentation.
+# The default value is: YES.
+
+SHOW_USED_FILES        = YES
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This
+# will remove the Files entry from the Quick Index and from the Folder Tree View
+# (if specified).
+# The default value is: YES.
+
+SHOW_FILES             = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces
+# page. This will remove the Namespaces entry from the Quick Index and from the
+# Folder Tree View (if specified).
+# The default value is: YES.
+
+SHOW_NAMESPACES        = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command command input-file, where command is the value of the
+# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided
+# by doxygen. Whatever the program writes to standard output is used as the file
+# version. For an example see the documentation.
+
+FILE_VERSION_FILTER    =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
+# by doxygen. The layout file controls the global structure of the generated
+# output files in an output format independent way. To create the layout file
+# that represents doxygen's defaults, run doxygen with the -l option. You can
+# optionally specify a file name after the option, if omitted DoxygenLayout.xml
+# will be used as the name of the layout file.
+#
+# Note that if you run doxygen from a directory containing a file called
+# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
+# tag is left empty.
+
+LAYOUT_FILE            =
+
+# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
+# the reference definitions. This must be a list of .bib files. The .bib
+# extension is automatically appended if omitted. This requires the bibtex tool
+# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info.
+# For LaTeX the style of the bibliography can be controlled using
+# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
+# search path. See also \cite for info how to create references.
+
+CITE_BIB_FILES         =
+
+#---------------------------------------------------------------------------
+# Configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated to
+# standard output by doxygen. If QUIET is set to YES this implies that the
+# messages are off.
+# The default value is: NO.
+
+QUIET                  = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES
+# this implies that the warnings are on.
+#
+# Tip: Turn warnings on while writing the documentation.
+# The default value is: YES.
+
+WARNINGS               = YES
+
+# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate
+# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
+# will automatically be disabled.
+# The default value is: YES.
+
+WARN_IF_UNDOCUMENTED   = YES
+
+# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some parameters
+# in a documented function, or documenting parameters that don't exist or using
+# markup commands wrongly.
+# The default value is: YES.
+
+WARN_IF_DOC_ERROR      = YES
+
+# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
+# are documented, but have no documentation for their parameters or return
+# value. If set to NO, doxygen will only warn about wrong or incomplete
+# parameter documentation, but not about the absence of documentation.
+# The default value is: NO.
+
+WARN_NO_PARAMDOC       = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that doxygen
+# can produce. The string should contain the $file, $line, and $text tags, which
+# will be replaced by the file and line number from which the warning originated
+# and the warning text. Optionally the format may contain $version, which will
+# be replaced by the version of the file (if it could be obtained via
+# FILE_VERSION_FILTER)
+# The default value is: $file:$line: $text.
+
+WARN_FORMAT            = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning and error
+# messages should be written. If left blank the output is written to standard
+# error (stderr).
+
+WARN_LOGFILE           =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag is used to specify the files and/or directories that contain
+# documented source files. You may enter file names like myfile.cpp or
+# directories like /usr/src/myproject. Separate the files or directories with
+# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
+# Note: If this tag is empty the current directory is searched.
+
+INPUT                  =
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
+# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
+# documentation (see: http://www.gnu.org/software/libiconv) for the list of
+# possible encodings.
+# The default value is: UTF-8.
+
+INPUT_ENCODING         = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
+# *.h) to filter out the source-files in the directories.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# read by doxygen.
+#
+# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,
+# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,
+# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc,
+# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd,
+# *.vhdl, *.ucf, *.qsf, *.as and *.js.
+
+FILE_PATTERNS          = *.qc *.qh *.inc
+
+# The RECURSIVE tag can be used to specify whether or not subdirectories should
+# be searched for input files as well.
+# The default value is: NO.
+
+RECURSIVE              = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should be
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+#
+# Note that relative paths are relative to the directory from which doxygen is
+# run.
+
+EXCLUDE                =
+
+# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
+# directories that are symbolic links (a Unix file system feature) are excluded
+# from the input.
+# The default value is: NO.
+
+EXCLUDE_SYMLINKS       = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories.
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories for example use the pattern */test/*
+
+EXCLUDE_PATTERNS       =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories use the pattern */test/*
+
+EXCLUDE_SYMBOLS        = _
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or directories
+# that contain example code fragments that are included (see the \include
+# command).
+
+EXAMPLE_PATH           =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank all
+# files are included.
+
+EXAMPLE_PATTERNS       =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude commands
+# irrespective of the value of the RECURSIVE tag.
+# The default value is: NO.
+
+EXAMPLE_RECURSIVE      = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or directories
+# that contain images that are to be included in the documentation (see the
+# \image command).
+
+IMAGE_PATH             =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command:
+#
+# <filter> <input-file>
+#
+# where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the
+# name of an input file. Doxygen will then use the output that the filter
+# program writes to standard output. If FILTER_PATTERNS is specified, this tag
+# will be ignored.
+#
+# Note that the filter must not add or remove lines; it is applied before the
+# code is scanned, but not when the output code is generated. If lines are added
+# or removed, the anchors will not be placed correctly.
+
+INPUT_FILTER           =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form: pattern=filter
+# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
+# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
+# patterns match the file name, INPUT_FILTER is applied.
+
+FILTER_PATTERNS        =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will also be used to filter the input files that are used for
+# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
+# The default value is: NO.
+
+FILTER_SOURCE_FILES    = NO
+
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and
+# it is also possible to disable source filtering for a specific pattern using
+# *.ext= (so without naming a filter).
+# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.
+
+FILTER_SOURCE_PATTERNS =
+
+# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
+# is part of the input, its contents will be placed on the main page
+# (index.html). This can be useful if you have a project on for instance GitHub
+# and want to reuse the introduction page also for the doxygen output.
+
+USE_MDFILE_AS_MAINPAGE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will be
+# generated. Documented entities will be cross-referenced with these sources.
+#
+# Note: To get rid of all source code in the generated output, make sure that
+# also VERBATIM_HEADERS is set to NO.
+# The default value is: NO.
+
+SOURCE_BROWSER         = YES
+
+# Setting the INLINE_SOURCES tag to YES will include the body of functions,
+# classes and enums directly into the documentation.
+# The default value is: NO.
+
+INLINE_SOURCES         = YES
+
+# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any
+# special comment blocks from generated source code fragments. Normal C, C++ and
+# Fortran comments will always remain visible.
+# The default value is: YES.
+
+STRIP_CODE_COMMENTS    = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES then for each documented
+# function all documented functions referencing it will be listed.
+# The default value is: NO.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES then for each documented function
+# all documented entities called/used by that function will be listed.
+# The default value is: NO.
+
+REFERENCES_RELATION    = YES
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
+# to YES then the hyperlinks from functions in REFERENCES_RELATION and
+# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
+# link to the documentation.
+# The default value is: YES.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the
+# source code will show a tooltip with additional information such as prototype,
+# brief description and links to the definition and documentation. Since this
+# will make the HTML file larger and loading of large files a bit slower, you
+# can opt to disable this feature.
+# The default value is: YES.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+SOURCE_TOOLTIPS        = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code will
+# point to the HTML generated by the htags(1) tool instead of doxygen built-in
+# source browser. The htags tool is part of GNU's global source tagging system
+# (see http://www.gnu.org/software/global/global.html). You will need version
+# 4.8.6 or higher.
+#
+# To use it do the following:
+# - Install the latest version of global
+# - Enable SOURCE_BROWSER and USE_HTAGS in the config file
+# - Make sure the INPUT points to the root of the source tree
+# - Run doxygen as normal
+#
+# Doxygen will invoke htags (and that will in turn invoke gtags), so these
+# tools must be available from the command line (i.e. in the search path).
+#
+# The result: instead of the source browser generated by doxygen, the links to
+# source code will now point to the output of htags.
+# The default value is: NO.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+USE_HTAGS              = NO
+
+# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a
+# verbatim copy of the header file for each class for which an include is
+# specified. Set to NO to disable this.
+# See also: Section \class.
+# The default value is: YES.
+
+VERBATIM_HEADERS       = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all
+# compounds will be generated. Enable this if the project contains a lot of
+# classes, structs, unions or interfaces.
+# The default value is: YES.
+
+ALPHABETICAL_INDEX     = YES
+
+# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
+# which the alphabetical index list will be split.
+# Minimum value: 1, maximum value: 20, default value: 5.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+COLS_IN_ALPHA_INDEX    = 5
+
+# In case all classes in a project start with a common prefix, all classes will
+# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
+# can be used to specify a prefix (or a list of prefixes) that should be ignored
+# while generating the index headers.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+IGNORE_PREFIX          =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output
+# The default value is: YES.
+
+GENERATE_HTML          = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_OUTPUT            = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
+# generated HTML page (for example: .htm, .php, .asp).
+# The default value is: .html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FILE_EXTENSION    = .html
+
+# The HTML_HEADER tag can be used to specify a user-defined HTML header file for
+# each generated HTML page. If the tag is left blank doxygen will generate a
+# standard header.
+#
+# To get valid HTML the header file that includes any scripts and style sheets
+# that doxygen needs, which is dependent on the configuration options used (e.g.
+# the setting GENERATE_TREEVIEW). It is highly recommended to start with a
+# default header using
+# doxygen -w html new_header.html new_footer.html new_stylesheet.css
+# YourConfigFile
+# and then modify the file new_header.html. See also section "Doxygen usage"
+# for information on how to generate the default header that doxygen normally
+# uses.
+# Note: The header is subject to change so you typically have to regenerate the
+# default header when upgrading to a newer version of doxygen. For a description
+# of the possible markers and block names see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_HEADER            =
+
+# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
+# generated HTML page. If the tag is left blank doxygen will generate a standard
+# footer. See HTML_HEADER for more information on how to generate a default
+# footer and what special commands can be used inside the footer. See also
+# section "Doxygen usage" for information on how to generate the default footer
+# that doxygen normally uses.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FOOTER            =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
+# sheet that is used by each HTML page. It can be used to fine-tune the look of
+# the HTML output. If left blank doxygen will generate a default style sheet.
+# See also section "Doxygen usage" for information on how to generate the style
+# sheet that doxygen normally uses.
+# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as
+# it is more robust and this tag (HTML_STYLESHEET) will in the future become
+# obsolete.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_STYLESHEET        =
+
+# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined
+# cascading style sheets that are included after the standard style sheets
+# created by doxygen. Using this option one can overrule certain style aspects.
+# This is preferred over using HTML_STYLESHEET since it does not replace the
+# standard style sheet and is therefore more robust against future updates.
+# Doxygen will copy the style sheet files to the output directory.
+# Note: The order of the extra style sheet files is of importance (e.g. the last
+# style sheet in the list overrules the setting of the previous ones in the
+# list). For an example see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_STYLESHEET  =
+
+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the HTML output directory. Note
+# that these files will be copied to the base HTML output directory. Use the
+# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that the
+# files will be copied as-is; there are no commands or markers available.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_FILES       =
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
+# will adjust the colors in the style sheet and background images according to
+# this color. Hue is specified as an angle on a colorwheel, see
+# http://en.wikipedia.org/wiki/Hue for more information. For instance the value
+# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
+# purple, and 360 is red again.
+# Minimum value: 0, maximum value: 359, default value: 220.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_HUE    = 220
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
+# in the HTML output. For a value of 0 the output will use grayscales only. A
+# value of 255 will produce the most vivid colors.
+# Minimum value: 0, maximum value: 255, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_SAT    = 100
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the
+# luminance component of the colors in the HTML output. Values below 100
+# gradually make the output lighter, whereas values above 100 make the output
+# darker. The value divided by 100 is the actual gamma applied, so 80 represents
+# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not
+# change the gamma.
+# Minimum value: 40, maximum value: 240, default value: 80.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_GAMMA  = 80
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
+# page will contain the date and time when the page was generated. Setting this
+# to YES can help to show when doxygen was last run and thus if the
+# documentation is up to date.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_TIMESTAMP         = YES
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_DYNAMIC_SECTIONS  = YES
+
+# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries
+# shown in the various tree structured indices initially; the user can expand
+# and collapse entries dynamically later on. Doxygen will expand the tree to
+# such a level that at most the specified number of entries are visible (unless
+# a fully collapsed tree already exceeds this amount). So setting the number of
+# entries 1 will produce a full collapsed tree by default. 0 is a special value
+# representing an infinite number of entries and will result in a full expanded
+# tree by default.
+# Minimum value: 0, maximum value: 9999, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_INDEX_NUM_ENTRIES = 100
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files will be
+# generated that can be used as input for Apple's Xcode 3 integrated development
+# environment (see: http://developer.apple.com/tools/xcode/), introduced with
+# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a
+# Makefile in the HTML output directory. Running make will produce the docset in
+# that directory and running make install will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
+# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
+# for more information.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_DOCSET        = NO
+
+# This tag determines the name of the docset feed. A documentation feed provides
+# an umbrella under which multiple documentation sets from a single provider
+# (such as a company or product suite) can be grouped.
+# The default value is: Doxygen generated docs.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_FEEDNAME        = "Doxygen generated docs"
+
+# This tag specifies a string that should uniquely identify the documentation
+# set bundle. This should be a reverse domain-name style string, e.g.
+# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_BUNDLE_ID       = org.doxygen.Project
+
+# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify
+# the documentation publisher. This should be a reverse domain-name style
+# string, e.g. com.mycompany.MyDocSet.documentation.
+# The default value is: org.doxygen.Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_ID    = org.doxygen.Publisher
+
+# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
+# The default value is: Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_NAME  = Publisher
+
+# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
+# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
+# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
+# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on
+# Windows.
+#
+# The HTML Help Workshop contains a compiler that can convert all HTML output
+# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
+# files are now used as the Windows 98 help format, and will replace the old
+# Windows help format (.hlp) on all Windows platforms in the future. Compressed
+# HTML files also contain an index, a table of contents, and you can search for
+# words in the documentation. The HTML workshop also contains a viewer for
+# compressed HTML files.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_HTMLHELP      = NO
+
+# The CHM_FILE tag can be used to specify the file name of the resulting .chm
+# file. You can add a path in front of the file if the result should not be
+# written to the html output directory.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_FILE               =
+
+# The HHC_LOCATION tag can be used to specify the location (absolute path
+# including file name) of the HTML help compiler (hhc.exe). If non-empty,
+# doxygen will try to run the HTML help compiler on the generated index.hhp.
+# The file has to be specified with full path.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+HHC_LOCATION           =
+
+# The GENERATE_CHI flag controls if a separate .chi index file is generated
+# (YES) or that it should be included in the master .chm file (NO).
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+GENERATE_CHI           = NO
+
+# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc)
+# and project file content.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_INDEX_ENCODING     =
+
+# The BINARY_TOC flag controls whether a binary table of contents is generated
+# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it
+# enables the Previous and Next buttons.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+BINARY_TOC             = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members to
+# the table of contents of the HTML help documentation and to the tree view.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+TOC_EXPAND             = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that
+# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help
+# (.qch) of the generated HTML documentation.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_QHP           = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify
+# the file name of the resulting .qch file. The path specified is relative to
+# the HTML output folder.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QCH_FILE               =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
+# Project output. For more information please see Qt Help Project / Namespace
+# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace).
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_NAMESPACE          = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
+# Help Project output. For more information please see Qt Help Project / Virtual
+# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual-
+# folders).
+# The default value is: doc.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_VIRTUAL_FOLDER     = doc
+
+# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
+# filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_NAME   =
+
+# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_ATTRS  =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
+# project's filter section matches. Qt Help Project / Filter Attributes (see:
+# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_SECT_FILTER_ATTRS  =
+
+# The QHG_LOCATION tag can be used to specify the location of Qt's
+# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
+# generated .qhp file.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHG_LOCATION           =
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
+# generated, together with the HTML files, they form an Eclipse help plugin. To
+# install this plugin and make it available under the help contents menu in
+# Eclipse, the contents of the directory containing the HTML and XML files needs
+# to be copied into the plugins directory of eclipse. The name of the directory
+# within the plugins directory should be the same as the ECLIPSE_DOC_ID value.
+# After copying Eclipse needs to be restarted before the help appears.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_ECLIPSEHELP   = NO
+
+# A unique identifier for the Eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have this
+# name. Each documentation set should have its own identifier.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.
+
+ECLIPSE_DOC_ID         = org.doxygen.Project
+
+# If you want full control over the layout of the generated HTML pages it might
+# be necessary to disable the index and replace it with your own. The
+# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top
+# of each HTML page. A value of NO enables the index and the value YES disables
+# it. Since the tabs in the index contain the same information as the navigation
+# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+DISABLE_INDEX          = NO
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information. If the tag
+# value is set to YES, a side panel will be generated containing a tree-like
+# index structure (just like the one that is generated for HTML Help). For this
+# to work a browser that supports JavaScript, DHTML, CSS and frames is required
+# (i.e. any modern browser). Windows users are probably better off using the
+# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can
+# further fine-tune the look of the index. As an example, the default style
+# sheet generated by doxygen has an example that shows how to put an image at
+# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
+# the same information as the tab index, you could consider setting
+# DISABLE_INDEX to YES when enabling this option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_TREEVIEW      = YES
+
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
+# doxygen will group on one line in the generated HTML documentation.
+#
+# Note that a value of 0 will completely suppress the enum values from appearing
+# in the overview section.
+# Minimum value: 0, maximum value: 20, default value: 4.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+ENUM_VALUES_PER_LINE   = 4
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used
+# to set the initial width (in pixels) of the frame in which the tree is shown.
+# Minimum value: 0, maximum value: 1500, default value: 250.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+TREEVIEW_WIDTH         = 250
+
+# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to
+# external symbols imported via tag files in a separate window.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+EXT_LINKS_IN_WINDOW    = NO
+
+# Use this tag to change the font size of LaTeX formulas included as images in
+# the HTML documentation. When you change the font size after a successful
+# doxygen run you need to manually remove any form_*.png images from the HTML
+# output directory to force them to be regenerated.
+# Minimum value: 8, maximum value: 50, default value: 10.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_FONTSIZE       = 10
+
+# Use the FORMULA_TRANPARENT tag to determine whether or not the images
+# generated for formulas are transparent PNGs. Transparent PNGs are not
+# supported properly for IE 6.0, but are supported on all modern browsers.
+#
+# Note that when changing this option you need to delete any form_*.png files in
+# the HTML output directory before the changes have effect.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_TRANSPARENT    = YES
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
+# http://www.mathjax.org) which uses client side Javascript for the rendering
+# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX
+# installed or if you want to formulas look prettier in the HTML output. When
+# enabled you may also need to install MathJax separately and configure the path
+# to it using the MATHJAX_RELPATH option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+USE_MATHJAX            = NO
+
+# When MathJax is enabled you can set the default output format to be used for
+# the MathJax output. See the MathJax site (see:
+# http://docs.mathjax.org/en/latest/output.html) for more details.
+# Possible values are: HTML-CSS (which is slower, but has the best
+# compatibility), NativeMML (i.e. MathML) and SVG.
+# The default value is: HTML-CSS.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_FORMAT         = HTML-CSS
+
+# When MathJax is enabled you need to specify the location relative to the HTML
+# output directory using the MATHJAX_RELPATH option. The destination directory
+# should contain the MathJax.js script. For instance, if the mathjax directory
+# is located at the same level as the HTML output directory, then
+# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
+# Content Delivery Network so you can quickly see the result without installing
+# MathJax. However, it is strongly recommended to install a local copy of
+# MathJax from http://www.mathjax.org before deployment.
+# The default value is: http://cdn.mathjax.org/mathjax/latest.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_RELPATH        = http://cdn.mathjax.org/mathjax/latest
+
+# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
+# extension names that should be enabled during MathJax rendering. For example
+# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_EXTENSIONS     =
+
+# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
+# of code that will be used on startup of the MathJax code. See the MathJax site
+# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an
+# example see the documentation.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_CODEFILE       =
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box for
+# the HTML output. The underlying search engine uses javascript and DHTML and
+# should work on any modern browser. Note that when using HTML help
+# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)
+# there is already a search function so this one should typically be disabled.
+# For large projects the javascript based search engine can be slow, then
+# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to
+# search using the keyboard; to jump to the search box use <access key> + S
+# (what the <access key> is depends on the OS and browser, but it is typically
+# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down
+# key> to jump into the search results window, the results can be navigated
+# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel
+# the search. The filter options can be selected when the cursor is inside the
+# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys>
+# to select a filter and <Enter> or <escape> to activate or cancel the filter
+# option.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+SEARCHENGINE           = YES
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a web server instead of a web client using Javascript. There
+# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
+# setting. When disabled, doxygen will generate a PHP script for searching and
+# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
+# and searching needs to be provided by external tools. See the section
+# "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SERVER_BASED_SEARCH    = NO
+
+# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP
+# script for searching. Instead the search results are written to an XML file
+# which needs to be processed by an external indexer. Doxygen will invoke an
+# external search engine pointed to by the SEARCHENGINE_URL option to obtain the
+# search results.
+#
+# Doxygen ships with an example indexer (doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: http://xapian.org/).
+#
+# See the section "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH        = NO
+
+# The SEARCHENGINE_URL should point to a search engine hosted by a web server
+# which will return the search results when EXTERNAL_SEARCH is enabled.
+#
+# Doxygen ships with an example indexer (doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: http://xapian.org/). See the section "External Indexing and
+# Searching" for details.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHENGINE_URL       =
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
+# search data is written to a file for indexing by an external tool. With the
+# SEARCHDATA_FILE tag the name of this file can be specified.
+# The default file is: searchdata.xml.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHDATA_FILE        = searchdata.xml
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the
+# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
+# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
+# projects and redirect the results back to the right project.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH_ID     =
+
+# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
+# projects other than the one defined by this configuration file, but that are
+# all added to the same external search index. Each project needs to have a
+# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of
+# to a relative location where the documentation can be found. The format is:
+# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTRA_SEARCH_MAPPINGS  =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output.
+# The default value is: YES.
+
+GENERATE_LATEX         = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_OUTPUT           = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked.
+#
+# Note that when enabling USE_PDFLATEX this option is only used for generating
+# bitmaps for formulas in the HTML output, but not in the Makefile that is
+# written to the output directory.
+# The default file is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_CMD_NAME         = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
+# index for LaTeX.
+# The default file is: makeindex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+MAKEINDEX_CMD_NAME     = makeindex
+
+# If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+COMPACT_LATEX          = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used by the
+# printer.
+# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x
+# 14 inches) and executive (7.25 x 10.5 inches).
+# The default value is: a4.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PAPER_TYPE             = a4
+
+# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
+# that should be included in the LaTeX output. The package can be specified just
+# by its name or with the correct syntax as to be used with the LaTeX
+# \usepackage command. To get the times font for instance you can specify :
+# EXTRA_PACKAGES=times or EXTRA_PACKAGES={times}
+# To use the option intlimits with the amsmath package you can specify:
+# EXTRA_PACKAGES=[intlimits]{amsmath}
+# If left blank no extra packages will be included.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+EXTRA_PACKAGES         =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
+# generated LaTeX document. The header should contain everything until the first
+# chapter. If it is left blank doxygen will generate a standard header. See
+# section "Doxygen usage" for information on how to let doxygen write the
+# default header to a separate file.
+#
+# Note: Only use a user-defined header if you know what you are doing! The
+# following commands have a special meaning inside the header: $title,
+# $datetime, $date, $doxygenversion, $projectname, $projectnumber,
+# $projectbrief, $projectlogo. Doxygen will replace $title with the empty
+# string, for the replacement values of the other commands the user is referred
+# to HTML_HEADER.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HEADER           =
+
+# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
+# generated LaTeX document. The footer should contain everything after the last
+# chapter. If it is left blank doxygen will generate a standard footer. See
+# LATEX_HEADER for more information on how to generate a default footer and what
+# special commands can be used inside the footer.
+#
+# Note: Only use a user-defined footer if you know what you are doing!
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_FOOTER           =
+
+# The LATEX_EXTRA_STYLESHEET tag can be used to specify additional user-defined
+# LaTeX style sheets that are included after the standard style sheets created
+# by doxygen. Using this option one can overrule certain style aspects. Doxygen
+# will copy the style sheet files to the output directory.
+# Note: The order of the extra style sheet files is of importance (e.g. the last
+# style sheet in the list overrules the setting of the previous ones in the
+# list).
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_STYLESHEET =
+
+# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the LATEX_OUTPUT output
+# directory. Note that the files will be copied as-is; there are no commands or
+# markers available.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_FILES      =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
+# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
+# contain links (just like the HTML output) instead of page references. This
+# makes the output suitable for online browsing using a PDF viewer.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PDF_HYPERLINKS         = YES
+
+# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
+# the PDF file directly from the LaTeX files. Set this option to YES, to get a
+# higher quality PDF documentation.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+USE_PDFLATEX           = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
+# command to the generated LaTeX files. This will instruct LaTeX to keep running
+# if errors occur, instead of asking the user for help. This option is also used
+# when generating formulas in HTML.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BATCHMODE        = NO
+
+# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the
+# index chapters (such as File Index, Compound Index, etc.) in the output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HIDE_INDICES     = NO
+
+# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source
+# code with syntax highlighting in the LaTeX output.
+#
+# Note that which sources are shown also depends on other settings such as
+# SOURCE_BROWSER.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_SOURCE_CODE      = NO
+
+# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
+# bibliography, e.g. plainnat, or ieeetr. See
+# http://en.wikipedia.org/wiki/BibTeX and \cite for more info.
+# The default value is: plain.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BIB_STYLE        = plain
+
+#---------------------------------------------------------------------------
+# Configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES, doxygen will generate RTF output. The
+# RTF output is optimized for Word 97 and may not look too pretty with other RTF
+# readers/editors.
+# The default value is: NO.
+
+GENERATE_RTF           = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: rtf.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_OUTPUT             = rtf
+
+# If the COMPACT_RTF tag is set to YES, doxygen generates more compact RTF
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+COMPACT_RTF            = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will
+# contain hyperlink fields. The RTF file will contain links (just like the HTML
+# output) instead of page references. This makes the output suitable for online
+# browsing using Word or some other Word compatible readers that support those
+# fields.
+#
+# Note: WordPad (write) and others do not support links.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_HYPERLINKS         = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's config
+# file, i.e. a series of assignments. You only have to provide replacements,
+# missing definitions are set to their default value.
+#
+# See also section "Doxygen usage" for information on how to generate the
+# default style sheet that doxygen normally uses.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_STYLESHEET_FILE    =
+
+# Set optional variables used in the generation of an RTF document. Syntax is
+# similar to doxygen's config file. A template extensions file can be generated
+# using doxygen -e rtf extensionFile.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_EXTENSIONS_FILE    =
+
+# If the RTF_SOURCE_CODE tag is set to YES then doxygen will include source code
+# with syntax highlighting in the RTF output.
+#
+# Note that which sources are shown also depends on other settings such as
+# SOURCE_BROWSER.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_SOURCE_CODE        = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES, doxygen will generate man pages for
+# classes and files.
+# The default value is: NO.
+
+GENERATE_MAN           = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it. A directory man3 will be created inside the directory specified by
+# MAN_OUTPUT.
+# The default directory is: man.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_OUTPUT             = man
+
+# The MAN_EXTENSION tag determines the extension that is added to the generated
+# man pages. In case the manual section does not start with a number, the number
+# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is
+# optional.
+# The default value is: .3.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_EXTENSION          = .3
+
+# The MAN_SUBDIR tag determines the name of the directory created within
+# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by
+# MAN_EXTENSION with the initial . removed.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_SUBDIR             =
+
+# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
+# will generate one additional man file for each entity documented in the real
+# man page(s). These additional files only source the real man page, but without
+# them the man command would be unable to find the correct page.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_LINKS              = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES, doxygen will generate an XML file that
+# captures the structure of the code including all documentation.
+# The default value is: NO.
+
+GENERATE_XML           = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: xml.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_OUTPUT             = xml
+
+# If the XML_PROGRAMLISTING tag is set to YES, doxygen will dump the program
+# listings (including syntax highlighting and cross-referencing information) to
+# the XML output. Note that enabling this will significantly increase the size
+# of the XML output.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_PROGRAMLISTING     = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to the DOCBOOK output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_DOCBOOK tag is set to YES, doxygen will generate Docbook files
+# that can be used to generate PDF.
+# The default value is: NO.
+
+GENERATE_DOCBOOK       = NO
+
+# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in
+# front of it.
+# The default directory is: docbook.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_OUTPUT         = docbook
+
+# If the DOCBOOK_PROGRAMLISTING tag is set to YES, doxygen will include the
+# program listings (including syntax highlighting and cross-referencing
+# information) to the DOCBOOK output. Note that enabling this will significantly
+# increase the size of the DOCBOOK output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_PROGRAMLISTING = NO
+
+#---------------------------------------------------------------------------
+# Configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an
+# AutoGen Definitions (see http://autogen.sf.net) file that captures the
+# structure of the code including all documentation. Note that this feature is
+# still experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_AUTOGEN_DEF   = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES, doxygen will generate a Perl module
+# file that captures the structure of the code including all documentation.
+#
+# Note that this feature is still experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_PERLMOD       = NO
+
+# If the PERLMOD_LATEX tag is set to YES, doxygen will generate the necessary
+# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
+# output from the Perl module output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_LATEX          = NO
+
+# If the PERLMOD_PRETTY tag is set to YES, the Perl module output will be nicely
+# formatted so it can be parsed by a human reader. This is useful if you want to
+# understand what is going on. On the other hand, if this tag is set to NO, the
+# size of the Perl module output will be much smaller and Perl will parse it
+# just the same.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_PRETTY         = YES
+
+# The names of the make variables in the generated doxyrules.make file are
+# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful
+# so different doxyrules.make files included by the same Makefile don't
+# overwrite each other's variables.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES, doxygen will evaluate all
+# C-preprocessor directives found in the sources and include files.
+# The default value is: YES.
+
+ENABLE_PREPROCESSING   = YES
+
+# If the MACRO_EXPANSION tag is set to YES, doxygen will expand all macro names
+# in the source code. If set to NO, only conditional compilation will be
+# performed. Macro expansion can be done in a controlled way by setting
+# EXPAND_ONLY_PREDEF to YES.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+MACRO_EXPANSION        = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
+# the macro expansion is limited to the macros specified with the PREDEFINED and
+# EXPAND_AS_DEFINED tags.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_ONLY_PREDEF     = NO
+
+# If the SEARCH_INCLUDES tag is set to YES, the include files in the
+# INCLUDE_PATH will be searched if a #include is found.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SEARCH_INCLUDES        = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by the
+# preprocessor.
+# This tag requires that the tag SEARCH_INCLUDES is set to YES.
+
+INCLUDE_PATH           =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will be
+# used.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+INCLUDE_FILE_PATTERNS  =
+
+# The PREDEFINED tag can be used to specify one or more macro names that are
+# defined before the preprocessor is started (similar to the -D option of e.g.
+# gcc). The argument of the tag is a list of macros of the form: name or
+# name=definition (no spaces). If the definition and the "=" are omitted, "=1"
+# is assumed. To prevent a macro definition from being undefined via #undef or
+# recursively expanded use the := operator instead of the = operator.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+PREDEFINED             =
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
+# tag can be used to specify a list of macro names that should be expanded. The
+# macro definition that is found in the sources will be used. Use the PREDEFINED
+# tag if you want to use a different macro definition that overrules the
+# definition found in the source code.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_AS_DEFINED      =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
+# remove all references to function-like macros that are alone on a line, have
+# an all uppercase name, and do not end with a semicolon. Such function macros
+# are typically used for boiler-plate code, and will confuse the parser if not
+# removed.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SKIP_FUNCTION_MACROS   = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES tag can be used to specify one or more tag files. For each tag
+# file the location of the external documentation should be added. The format of
+# a tag file without this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where loc1 and loc2 can be relative or absolute paths or URLs. See the
+# section "Linking to external documentation" for more information about the use
+# of tag files.
+# Note: Each tag file must have a unique name (where the name does NOT include
+# the path). If a tag file is not located in the directory in which doxygen is
+# run, you must also specify the path to the tagfile here.
+
+TAGFILES               =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
+# tag file that is based on the input files it reads. See section "Linking to
+# external documentation" for more information about the usage of tag files.
+
+GENERATE_TAGFILE       =
+
+# If the ALLEXTERNALS tag is set to YES, all external class will be listed in
+# the class index. If set to NO, only the inherited external classes will be
+# listed.
+# The default value is: NO.
+
+ALLEXTERNALS           = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will be
+# listed.
+# The default value is: YES.
+
+EXTERNAL_GROUPS        = YES
+
+# If the EXTERNAL_PAGES tag is set to YES, all external pages will be listed in
+# the related pages index. If set to NO, only the current project's pages will
+# be listed.
+# The default value is: YES.
+
+EXTERNAL_PAGES         = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of 'which perl').
+# The default file (with absolute path) is: /usr/bin/perl.
+
+PERL_PATH              = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES, doxygen will generate a class diagram
+# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
+# NO turns the diagrams off. Note that this option also works with HAVE_DOT
+# disabled, but it is recommended to install and use dot, since it yields more
+# powerful graphs.
+# The default value is: YES.
+
+CLASS_DIAGRAMS         = YES
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see:
+# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH            =
+
+# You can include diagrams made with dia in doxygen documentation. Doxygen will
+# then run dia to produce the diagram and insert it in the documentation. The
+# DIA_PATH tag allows you to specify the directory where the dia binary resides.
+# If left empty dia is assumed to be found in the default search path.
+
+DIA_PATH               =
+
+# If set to YES the inheritance and collaboration graphs will hide inheritance
+# and usage relations if the target is undocumented or is not a class.
+# The default value is: YES.
+
+HIDE_UNDOC_RELATIONS   = NO
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz (see:
+# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
+# Bell Labs. The other options in this section have no effect if this option is
+# set to NO
+# The default value is: NO.
+
+HAVE_DOT               = YES
+
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed
+# to run in parallel. When set to 0 doxygen will base this on the number of
+# processors available in the system. You can set it explicitly to a value
+# larger than 0 to get control over the balance between CPU load and processing
+# speed.
+# Minimum value: 0, maximum value: 32, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_NUM_THREADS        = 2
+
+# When you want a differently looking font in the dot files that doxygen
+# generates you can specify the font name using DOT_FONTNAME. You need to make
+# sure dot is able to find the font, which can be done by putting it in a
+# standard location or by setting the DOTFONTPATH environment variable or by
+# setting DOT_FONTPATH to the directory containing the font.
+# The default value is: Helvetica.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTNAME           = Helvetica
+
+# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of
+# dot graphs.
+# Minimum value: 4, maximum value: 24, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTSIZE           = 10
+
+# By default doxygen will tell dot to use the default font as specified with
+# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set
+# the path where dot can find it using this tag.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTPATH           =
+
+# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for
+# each documented class showing the direct and indirect inheritance relations.
+# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CLASS_GRAPH            = YES
+
+# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a
+# graph for each documented class showing the direct and indirect implementation
+# dependencies (inheritance, containment, and class references variables) of the
+# class with other documented classes.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+COLLABORATION_GRAPH    = YES
+
+# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for
+# groups, showing the direct groups dependencies.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GROUP_GRAPHS           = YES
+
+# If the UML_LOOK tag is set to YES, doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LOOK               = NO
+
+# If the UML_LOOK tag is enabled, the fields and methods are shown inside the
+# class node. If there are many fields or methods and many nodes the graph may
+# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the
+# number of items for each type to make the size more manageable. Set this to 0
+# for no limit. Note that the threshold may be exceeded by 50% before the limit
+# is enforced. So when you set the threshold to 10, up to 15 fields may appear,
+# but if the number exceeds 15, the total amount of fields shown is limited to
+# 10.
+# Minimum value: 0, maximum value: 100, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LIMIT_NUM_FIELDS   = 10
+
+# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
+# collaboration graphs will show the relations between templates and their
+# instances.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+TEMPLATE_RELATIONS     = NO
+
+# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to
+# YES then doxygen will generate a graph for each documented file showing the
+# direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDE_GRAPH          = YES
+
+# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are
+# set to YES then doxygen will generate a graph for each documented file showing
+# the direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDED_BY_GRAPH      = YES
+
+# If the CALL_GRAPH tag is set to YES then doxygen will generate a call
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command. Disabling a call graph can be
+# accomplished by means of the command \hidecallgraph.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALL_GRAPH             = YES
+
+# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable caller graphs for selected
+# functions only using the \callergraph command. Disabling a caller graph can be
+# accomplished by means of the command \hidecallergraph.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALLER_GRAPH           = YES
+
+# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical
+# hierarchy of all classes instead of a textual one.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GRAPHICAL_HIERARCHY    = YES
+
+# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the
+# dependencies a directory has on other directories in a graphical way. The
+# dependency relations are determined by the #include relations between the
+# files in the directories.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DIRECTORY_GRAPH        = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. For an explanation of the image formats see the section
+# output formats in the documentation of the dot tool (Graphviz (see:
+# http://www.graphviz.org/)).
+# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
+# to make the SVG files visible in IE 9+ (other browsers do not have this
+# requirement).
+# Possible values are: png, jpg, gif, svg, png:gd, png:gd:gd, png:cairo,
+# png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus and
+# png:gdiplus:gdiplus.
+# The default value is: png.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_IMAGE_FORMAT       = svg
+
+# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
+# enable generation of interactive SVG images that allow zooming and panning.
+#
+# Note that this requires a modern browser other than Internet Explorer. Tested
+# and working are Firefox, Chrome, Safari, and Opera.
+# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make
+# the SVG files visible. Older versions of IE do not have SVG support.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INTERACTIVE_SVG        = YES
+
+# The DOT_PATH tag can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_PATH               =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the \dotfile
+# command).
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOTFILE_DIRS           =
+
+# The MSCFILE_DIRS tag can be used to specify one or more directories that
+# contain msc files that are included in the documentation (see the \mscfile
+# command).
+
+MSCFILE_DIRS           =
+
+# The DIAFILE_DIRS tag can be used to specify one or more directories that
+# contain dia files that are included in the documentation (see the \diafile
+# command).
+
+DIAFILE_DIRS           =
+
+# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
+# path where java can find the plantuml.jar file. If left blank, it is assumed
+# PlantUML is not used or called during a preprocessing step. Doxygen will
+# generate a warning when it encounters a \startuml command in this case and
+# will not generate output for the diagram.
+
+PLANTUML_JAR_PATH      =
+
+# When using plantuml, the specified paths are searched for files specified by
+# the !include statement in a plantuml block.
+
+PLANTUML_INCLUDE_PATH  =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
+# that will be shown in the graph. If the number of nodes in a graph becomes
+# larger than this value, doxygen will truncate the graph, which is visualized
+# by representing a node as a red box. Note that doxygen if the number of direct
+# children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that
+# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+# Minimum value: 0, maximum value: 10000, default value: 50.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_GRAPH_MAX_NODES    = 500
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs
+# generated by dot. A depth value of 3 means that only nodes reachable from the
+# root by following a path via at most 3 edges will be shown. Nodes that lay
+# further from the root node will be omitted. Note that setting this option to 1
+# or 2 may greatly reduce the computation time needed for large code bases. Also
+# note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+# Minimum value: 0, maximum value: 1000, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+MAX_DOT_GRAPH_DEPTH    = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not seem
+# to support this out of the box.
+#
+# Warning: Depending on the platform used, enabling this option may lead to
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
+# read).
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_TRANSPARENT        = YES
+
+# Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10) support
+# this, this feature is disabled by default.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_MULTI_TARGETS      = YES
+
+# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
+# explaining the meaning of the various boxes and arrows in the dot generated
+# graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GENERATE_LEGEND        = YES
+
+# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate dot
+# files that are used to generate the various graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_CLEANUP            = YES
index 51440d4a3c90da83d77f8e57033c7e2287c188d6..452dfc9a6451ad219bfcfd3b84c9a06b924c504f 100644 (file)
@@ -42,17 +42,17 @@ $(QCCVERSIONFILE):
        $(RM) qccversion.*
        echo This file intentionally left blank. > $@
 
-FILES_CSPROGS = $(shell find client lib common warpzonelib csqcmodellib -type f -not -name fteqcc.log -not -name qc.asm)
+FILES_CSPROGS = $(shell find lib common client -type f)
 ../csprogs.dat: $(FILES_CSPROGS) $(QCCVERSIONFILE)
        @echo make[1]: Entering directory \`$(PWD)/client\'
        cd client && $(QCC) $(QCCFLAGS) -DCSQC
 
-FILES_PROGS = $(shell find server lib common warpzonelib csqcmodellib -type f -not -name fteqcc.log -not -name qc.asm)
+FILES_PROGS = $(shell find lib common server -type f)
 ../progs.dat: $(FILES_PROGS) $(QCCVERSIONFILE)
        @echo make[1]: Entering directory \`$(PWD)/server\'
        cd server && $(QCC) $(QCCFLAGS) -DSVQC
 
-FILES_MENU = $(shell find menu lib common warpzonelib -type f -not -name fteqcc.log -not -name qc.asm)
+FILES_MENU = $(shell find lib common menu -type f)
 ../menu.dat: $(FILES_MENU) $(QCCVERSIONFILE)
        @echo make[1]: Entering directory \`$(PWD)/menu\'
        cd menu && $(QCC) $(QCCFLAGS) -DMENUQC
index 0fe1c616fd687d4eb9adecfcf2fa8f62086f52f7..adff5ccff49eef81586f341d4ea2f94f66223ae1 100644 (file)
@@ -1,14 +1,15 @@
 #ifndef CLIENT_ALL_H
 #define CLIENT_ALL_H
 
+#include "../common/util.qh"
+
+#include "../common/effects/all.qh"
+#include "../common/models/all.qh"
+#include "../common/sounds/all.qh"
+
 #include "autocvars.qh"
 #include "defs.qh"
 #include "main.qh"
 #include "miscfunctions.qh"
 
-#include "../dpdefs/csprogsdefs.qh"
-
-#include "../common/models/all.qh"
-#include "../common/sounds/all.qh"
-
 #endif
index b7b7bb5c6e5d992c2a8c20ea1e9f8c8bce7332f2..e20557fa741300f05bb7dfd5027a7832f5b70638 100644 (file)
@@ -1,9 +1,7 @@
 #include "announcer.qh"
-#include "_all.qh"
 
 #include "../common/notifications.qh"
 #include "../common/stats.qh"
-#include "../common/util.qh"
 
 bool announcer_1min;
 bool announcer_5min;
index 620b84544e9589facd78018cede17afa85ce884b..64be1433af70bd80d6c0450a8b497c98a0a34205 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef ANNOUNCER_H
-#define ANNOUNCER_H
+#ifndef CLIENT_ANNOUNCER_H
+#define CLIENT_ANNOUNCER_H
 
 void Announcer();
 
index 894bf6955af35a3b376199c29e12fe351ca1f5e2..a984a19a32a283dfc7a12f2aacee211761f9e87e 100644 (file)
@@ -1,7 +1,4 @@
 #include "bgmscript.qh"
-#include "_all.qh"
-
-#include "../common/util.qh"
 
 #define CONSTANT_SPEED_DECAY
 
index 5921bb4bc7325126c5227353192a1aa1fe18c250..d979e79d0731042f9d26579e6917bf50a0d34bd4 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef BGMSCRIPT_H
-#define BGMSCRIPT_H
+#ifndef CLIENT_BGMSCRIPT_H
+#define CLIENT_BGMSCRIPT_H
 
 entityclass(BGMScript);
 class(BGMScript) .string bgmscript;
diff --git a/qcsrc/client/command/all.qc b/qcsrc/client/command/all.qc
deleted file mode 100644 (file)
index dcace65..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-#include "../_all.qh"
-
-#include "../../common/command/all.qc"
-
-#include "cl_cmd.qc"
diff --git a/qcsrc/client/command/all.qh b/qcsrc/client/command/all.qh
deleted file mode 100644 (file)
index 34fc423..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef CLIENT_COMMANDS_ALL_H
-#define CLIENT_COMMANDS_ALL_H
-
-#include "../../common/command/all.qh"
-
-#include "cl_cmd.qh"
-
-#endif
diff --git a/qcsrc/client/command/cl_cmd.qc b/qcsrc/client/command/cl_cmd.qc
deleted file mode 100644 (file)
index 88cd246..0000000
+++ /dev/null
@@ -1,675 +0,0 @@
-// ==============================================
-//  CSQC client commands code, written by Samual
-//  Last updated: December 28th, 2011
-// ==============================================
-
-#include "../../common/command/command.qh"
-#include "cl_cmd.qh"
-
-#include "../autocvars.qh"
-#include "../defs.qh"
-#include "../hud.qh"
-#include "../hud_config.qh"
-#include "../main.qh"
-#include "../mapvoting.qh"
-#include "../miscfunctions.qh"
-
-#include "../mutators/events.qh"
-
-#include "../../common/mapinfo.qh"
-
-#include "../../common/command/generic.qh"
-
-void DrawDebugModel(entity this)
-{
-       if(time - floor(time) > 0.5)
-       {
-               PolyDrawModel(self);
-               self.drawmask = 0;
-       }
-       else
-       {
-               self.renderflags = 0;
-               self.drawmask = MASK_NORMAL;
-       }
-}
-
-
-// =======================
-//  Command Sub-Functions
-// =======================
-
-void LocalCommand_blurtest(int request)
-{
-       // Simple command to work with postprocessing temporarily... possibly completely pointless, the glsl shader is used for a real feature now...
-       // Anyway, to enable it, just compile the client with -DBLURTEST and then you can use the command.
-
-       #ifdef BLURTEST
-       switch(request)
-       {
-               case CMD_REQUEST_COMMAND:
-               {
-                       blurtest_time0 = time;
-                       blurtest_time1 = time + stof(argv(1));
-                       blurtest_radius = stof(argv(2));
-                       blurtest_power = stof(argv(3));
-                       LOG_INFO("Enabled blurtest\n");
-                       return;
-               }
-
-               default:
-               case CMD_REQUEST_USAGE:
-               {
-                       LOG_INFO("\nUsage:^3 cl_cmd blurtest\n");
-                       LOG_INFO("  No arguments required.\n");
-                       return;
-               }
-       }
-       #else
-       if(request)
-       {
-               LOG_INFO("Blurtest is not enabled on this client.\n");
-               return;
-       }
-       #endif
-}
-
-void LocalCommand_boxparticles(int request, int argc)
-{
-       switch(request)
-       {
-               case CMD_REQUEST_COMMAND:
-               {
-                       if (argc == 9)
-                       {
-                               int effect = _particleeffectnum(argv(1));
-                               if (effect >= 0)
-                               {
-                                       int index = stoi(argv(2));
-                                       entity own;
-                                       if(index <= 0)
-                                               own = entitybyindex(-index);
-                                       else
-                                               own = findfloat(world, entnum, index);
-                                       vector org_from = stov(argv(3));
-                                       vector org_to = stov(argv(4));
-                                       vector dir_from = stov(argv(5));
-                                       vector dir_to = stov(argv(6));
-                                       int countmultiplier = stoi(argv(7));
-                                       int flags = stoi(argv(8));
-                                       boxparticles(effect, own, org_from, org_to, dir_from, dir_to, countmultiplier, flags);
-                                       return;
-                               }
-                       }
-               }
-
-               default:
-                       LOG_INFO("Incorrect parameters for ^2boxparticles^7\n");
-               case CMD_REQUEST_USAGE:
-               {
-                       LOG_INFO("\nUsage:^3 lv_cmd boxparticles effectname own org_from org_to, dir_from, dir_to, countmultiplier, flags\n");
-                       LOG_INFO("  'effectname' is the name of a particle effect in effectinfo.txt\n");
-                       LOG_INFO("  'own' is the entity number of the owner (negative for csqc ent, positive for svqc ent)\n");
-                       LOG_INFO("  'org_from' is the starting origin of the box\n");
-                       LOG_INFO("  'org_to' is the ending origin of the box\n");
-                       LOG_INFO("  'dir_from' is the minimum velocity\n");
-                       LOG_INFO("  'dir_to' is the maximum velocity\n");
-                       LOG_INFO("  'countmultiplier' defines a multiplier for the particle count (affects count only, not countabsolute or trailspacing)\n");
-                       LOG_INFO("  'flags' can contain:\n");
-                       LOG_INFO("    1 to respect globals particles_alphamin, particles_alphamax (set right before via prvm_globalset client)\n");
-                       LOG_INFO("    2 to respect globals particles_colormin, particles_colormax (set right before via prvm_globalset client)\n");
-                       LOG_INFO("    4 to respect globals particles_fade (set right before via prvm_globalset client)\n");
-                       LOG_INFO("    128 to draw a trail, not a box\n");
-                       return;
-               }
-       }
-}
-
-void LocalCommand_create_scrshot_ent(int request)
-{
-       switch(request)
-       {
-               case CMD_REQUEST_COMMAND:
-               {
-                       string filename = strcat(MapInfo_Map_bspname, "_scrshot_ent.txt");
-                       int fh = fopen(filename, FILE_WRITE);
-
-                       if(fh >= 0)
-                       {
-                               fputs(fh, "{\n");
-                               fputs(fh, strcat("\"classname\" \"info_autoscreenshot\"\n"));
-                               fputs(fh, strcat("\"origin\" \"", strcat(ftos(view_origin.x), " ", ftos(view_origin.y), " ", ftos(view_origin.z)), "\"\n"));
-                               fputs(fh, strcat("\"angles\" \"", strcat(ftos(view_angles.x), " ", ftos(view_angles.y), " ", ftos(view_angles.z)), "\"\n"));
-                               fputs(fh, "}\n");
-
-                               LOG_INFO("Completed screenshot entity dump in ^2data/data/", MapInfo_Map_bspname, "_scrshot_ent.txt^7.\n");
-
-                               fclose(fh);
-                       }
-                       else
-                       {
-                               LOG_INFO("^1Error: ^7Could not dump to file!\n");
-                       }
-                       return;
-               }
-
-               default:
-               case CMD_REQUEST_USAGE:
-               {
-                       LOG_INFO("\nUsage:^3 cl_cmd create_scrshot_ent\n");
-                       LOG_INFO("  No arguments required.\n");
-                       return;
-               }
-       }
-}
-
-void LocalCommand_debugmodel(int request, int argc)
-{
-       switch(request)
-       {
-               case CMD_REQUEST_COMMAND:
-               {
-                       string modelname = argv(1);
-                       entity debugmodel_entity;
-
-                       debugmodel_entity = spawn();
-                       precache_model(modelname);
-                       _setmodel(debugmodel_entity, modelname);
-                       setorigin(debugmodel_entity, view_origin);
-                       debugmodel_entity.angles = view_angles;
-                       debugmodel_entity.draw = DrawDebugModel;
-                       debugmodel_entity.classname = "debugmodel";
-
-                       return;
-               }
-
-               default:
-               case CMD_REQUEST_USAGE:
-               {
-                       LOG_INFO("\nUsage:^3 cl_cmd debugmodel model\n");
-                       LOG_INFO("  Where 'model' is a string of the model name to use for the debug model.\n");
-                       return;
-               }
-       }
-}
-
-void LocalCommand_handlevote(int request, int argc)
-{
-       switch(request)
-       {
-               case CMD_REQUEST_COMMAND:
-               {
-                       int vote_selection;
-                       string vote_string;
-
-                       if(InterpretBoolean(argv(1)))
-                       {
-                               vote_selection = 2;
-                               vote_string = "yes";
-                       }
-                       else
-                       {
-                               vote_selection = 1;
-                               vote_string = "no";
-                       }
-
-                       if(vote_selection)
-                       {
-                               if(uid2name_dialog) // handled by "uid2name" option
-                               {
-                                       vote_active = 0;
-                                       vote_prev = 0;
-                                       vote_change = -9999;
-                                       localcmd(strcat("setreport cl_allow_uid2name ", ftos(vote_selection - 1), "\n"));
-                                       uid2name_dialog = 0;
-                               }
-                               else { localcmd(strcat("cmd vote ", vote_string, "\n")); }
-
-                               return;
-                       }
-               }
-
-               default:
-                       LOG_INFO("Incorrect parameters for ^2handlevote^7\n");
-               case CMD_REQUEST_USAGE:
-               {
-                       LOG_INFO("\nUsage:^3 cl_cmd handlevote vote\n");
-                       LOG_INFO("  Where 'vote' is the selection for either the current poll or uid2name.\n");
-                       return;
-               }
-       }
-}
-
-void LocalCommand_hud(int request, int argc)
-{
-       switch(request)
-       {
-               case CMD_REQUEST_COMMAND:
-               {
-                       switch(argv(1))
-                       {
-                               case "configure":
-                               {
-                                       cvar_set("_hud_configure", ftos(!autocvar__hud_configure));
-                                       return;
-                               }
-
-                               case "quickmenu":
-                               {
-                                       if(QuickMenu_IsOpened())
-                                               QuickMenu_Close();
-                                       else
-                                               QuickMenu_Open(argv(2), argv(3)); // mode, submenu
-                                       return;
-                               }
-
-                               case "minigame":
-                               {
-                                       if(HUD_MinigameMenu_IsOpened())
-                                               HUD_MinigameMenu_Close();
-                                       else
-                                               HUD_MinigameMenu_Open();
-                                       return;
-                               }
-
-                               case "save":
-                               {
-                                       if(argv(2))
-                                       {
-                                               HUD_Panel_ExportCfg(argv(2));
-                                               return;
-                                       }
-                                       else
-                                       {
-                                               break; // go to usage, we're missing the paramater needed here.
-                                       }
-                               }
-
-                               case "scoreboard_columns_set":
-                               {
-                                       Cmd_HUD_SetFields(argc);
-                                       return;
-                               }
-
-                               case "scoreboard_columns_help":
-                               {
-                                       Cmd_HUD_Help();
-                                       return;
-                               }
-
-                               case "radar":
-                               {
-                                       if(argv(2))
-                                               HUD_Radar_Show_Maximized(InterpretBoolean(argv(2)),0);
-                                       else
-                                               HUD_Radar_Show_Maximized(!hud_panel_radar_maximized,0);
-                                       return;
-                               }
-
-                               case "clickradar":
-                               {
-                                       HUD_Radar_Show_Maximized(!hud_panel_radar_mouse,1);
-                                       return;
-                               }
-                       }
-               }
-
-               default:
-                       LOG_INFO("Incorrect parameters for ^2hud^7\n");
-               case CMD_REQUEST_USAGE:
-               {
-                       LOG_INFO("\nUsage:^3 cl_cmd hud action [configname | radartoggle | layout]\n");
-                       LOG_INFO("  Where 'action' is the command to complete,\n");
-                       LOG_INFO("  'configname' is the name to save to for \"save\" action,\n");
-                       LOG_INFO("  'radartoggle' is to control hud_panel_radar_maximized for \"radar\" action,\n");
-                       LOG_INFO("  and 'layout' is how to organize the scoreboard columns for the set action.\n");
-                       LOG_INFO("  quickmenu [[default | file | \"\"] submenu]\n");
-                       LOG_INFO("    Called without options (or with "") loads either the default quickmenu or a quickmenu file if hud_panel_quickmenu_file is set to a valid filename.\n");
-                       LOG_INFO("    Submenu option allows to open quickmenu directly in a submenu, it requires to specify 'default', 'file' or '\"\"' option.\n");
-                       LOG_INFO("  Full list of commands here: \"configure, minigame, save, scoreboard_columns_help, scoreboard_columns_set, radar.\"\n");
-                       return;
-               }
-       }
-}
-
-void LocalCommand_localprint(int request, int argc)
-{
-       switch(request)
-       {
-               case CMD_REQUEST_COMMAND:
-               {
-                       if(argv(1))
-                       {
-                               centerprint_hud(argv(1));
-                               return;
-                       }
-               }
-
-               default:
-                       LOG_INFO("Incorrect parameters for ^2localprint^7\n");
-               case CMD_REQUEST_USAGE:
-               {
-                       LOG_INFO("\nUsage:^3 cl_cmd localprint \"message\"\n");
-                       LOG_INFO("  'message' is the centerprint message to send to yourself.\n");
-                       return;
-               }
-       }
-}
-
-void LocalCommand_mv_download(int request, int argc)
-{
-       switch(request)
-       {
-               case CMD_REQUEST_COMMAND:
-               {
-                       if(argv(1))
-                       {
-                               Cmd_MapVote_MapDownload(argc);
-                               return;
-                       }
-               }
-
-               default:
-                       LOG_INFO("Incorrect parameters for ^2mv_download^7\n");
-               case CMD_REQUEST_USAGE:
-               {
-                       LOG_INFO("\nUsage:^3 cl_cmd mv_download mapid\n");
-                       LOG_INFO("  Where 'mapid' is the id number of the map to request an image of on the map vote selection menu.\n");
-                       return;
-               }
-       }
-}
-
-void LocalCommand_find(int request, int argc)
-{
-       switch(request)
-       {
-               case CMD_REQUEST_COMMAND:
-               {
-                       entity client;
-
-                       for(client = world; (client = find(client, classname, argv(1))); )
-                               LOG_INFO(etos(client), "\n");
-
-                       return;
-               }
-
-               default:
-                       LOG_INFO("Incorrect parameters for ^2find^7\n");
-               case CMD_REQUEST_USAGE:
-               {
-                       LOG_INFO("\nUsage:^3 cl_cmd find classname\n");
-                       LOG_INFO("  Where 'classname' is the classname to search for.\n");
-                       return;
-               }
-       }
-}
-
-void LocalCommand_sendcvar(int request, int argc)
-{
-       switch(request)
-       {
-               case CMD_REQUEST_COMMAND:
-               {
-                       if(argv(1))
-                       {
-                               // W_FixWeaponOrder will trash argv, so save what we need.
-                               string thiscvar = strzone(argv(1));
-                               string s = cvar_string(thiscvar);
-
-                               if(thiscvar == "cl_weaponpriority")
-                                       s = W_FixWeaponOrder(W_NumberWeaponOrder(s), 1);
-                               else if(substring(thiscvar, 0, 17) == "cl_weaponpriority" && strlen(thiscvar) == 18)
-                                       s = W_FixWeaponOrder(W_NumberWeaponOrder(s), 0);
-
-                               localcmd("cmd sentcvar ", thiscvar, " \"", s, "\"\n");
-                               strunzone(thiscvar);
-                               return;
-                       }
-               }
-
-               default:
-                       LOG_INFO("Incorrect parameters for ^2sendcvar^7\n");
-               case CMD_REQUEST_USAGE:
-               {
-                       LOG_INFO("\nUsage:^3 cl_cmd sendcvar <cvar>\n");
-                       LOG_INFO("  Where 'cvar' is the cvar plus arguments to send to the server.\n");
-                       return;
-               }
-       }
-}
-
-/* use this when creating a new command, making sure to place it in alphabetical order... also,
-** ADD ALL NEW COMMANDS TO commands.cfg WITH PROPER ALIASES IN THE SAME FASHION!
-void LocalCommand_(int request)
-{
-       switch(request)
-       {
-               case CMD_REQUEST_COMMAND:
-               {
-
-                       return;
-               }
-
-               default:
-               case CMD_REQUEST_USAGE:
-               {
-                       print("\nUsage:^3 cl_cmd \n");
-                       print("  No arguments required.\n");
-                       return;
-               }
-       }
-}
-*/
-
-
-// ==================================
-//  Macro system for client commands
-// ==================================
-
-// Normally do not hard code aliases for these, instead create them in commands.cfg... also: keep in alphabetical order, please ;)
-#define CLIENT_COMMANDS(request,arguments) \
-       CLIENT_COMMAND("blurtest", LocalCommand_blurtest(request), "Feature for testing blur postprocessing") \
-       CLIENT_COMMAND("boxparticles", LocalCommand_boxparticles(request, arguments), "Spawn particles manually") \
-       CLIENT_COMMAND("create_scrshot_ent", LocalCommand_create_scrshot_ent(request), "Create an entity at this location for automatic screenshots") \
-       CLIENT_COMMAND("debugmodel", LocalCommand_debugmodel(request, arguments), "Spawn a debug model manually") \
-       CLIENT_COMMAND("handlevote", LocalCommand_handlevote(request, arguments), "System to handle selecting a vote or option") \
-       CLIENT_COMMAND("hud", LocalCommand_hud(request, arguments), "Commands regarding/controlling the HUD system") \
-       CLIENT_COMMAND("localprint", LocalCommand_localprint(request, arguments), "Create your own centerprint sent to yourself") \
-       CLIENT_COMMAND("find", LocalCommand_find(request, arguments), "Search through entities for matching classname") \
-       CLIENT_COMMAND("mv_download", LocalCommand_mv_download(request, arguments), "Retrieve mapshot picture from the server") \
-       CLIENT_COMMAND("sendcvar", LocalCommand_sendcvar(request, arguments), "Send a cvar to the server (like weaponpriority)") \
-       /* nothing */
-
-void LocalCommand_macro_help()
-{
-       #define CLIENT_COMMAND(name,function,description) \
-               { if(strtolower(description) != "") { LOG_INFO("  ^2", name, "^7: ", description, "\n"); } }
-
-       CLIENT_COMMANDS(0, 0);
-       #undef CLIENT_COMMAND
-
-       return;
-}
-
-bool LocalCommand_macro_command(int argc)
-{
-       #define CLIENT_COMMAND(name,function,description) \
-               { if(name == strtolower(argv(0))) { function; return true; } }
-
-       CLIENT_COMMANDS(CMD_REQUEST_COMMAND, argc);
-       #undef CLIENT_COMMAND
-
-       return false;
-}
-
-bool LocalCommand_macro_usage(int argc)
-{
-       #define CLIENT_COMMAND(name,function,description) \
-               { if(name == strtolower(argv(1))) { function; return true; } }
-
-       CLIENT_COMMANDS(CMD_REQUEST_USAGE, argc);
-       #undef CLIENT_COMMAND
-
-       return false;
-}
-
-void LocalCommand_macro_write_aliases(int fh)
-{
-       #define CLIENT_COMMAND(name,function,description) \
-               { if(strtolower(description) != "") { CMD_Write_Alias("qc_cmd_cl", name, description); } }
-
-       CLIENT_COMMANDS(0, 0);
-       #undef CLIENT_COMMAND
-
-       return;
-}
-
-
-// =========================================
-//  Main Function Called By Engine (cl_cmd)
-// =========================================
-// If this function exists, client code handles gamecommand instead of the engine code.
-
-void GameCommand(string command)
-{
-       int argc = tokenize_console(command);
-
-       // Guide for working with argc arguments by example:
-       // argc:   1    - 2      - 3     - 4
-       // argv:   0    - 1      - 2     - 3
-       // cmd     vote - master - login - password
-       string s = strtolower(argv(0));
-       if (s == "help")
-       {
-               if(argc == 1)
-               {
-                       LOG_INFO("\nClient console commands:\n");
-                       LocalCommand_macro_help();
-
-                       LOG_INFO("\nGeneric commands shared by all programs:\n");
-                       GenericCommand_macro_help();
-
-                       LOG_INFO("\nUsage:^3 cl_cmd COMMAND...^7, where possible commands are listed above.\n");
-                       LOG_INFO("For help about a specific command, type cl_cmd help COMMAND\n");
-
-                       return;
-               }
-               else if(GenericCommand_macro_usage(argc)) // Instead of trying to call a command, we're going to see detailed information about it
-               {
-                       return;
-               }
-               else if(LocalCommand_macro_usage(argc)) // now try for normal commands too
-               {
-                       return;
-               }
-       }
-       // continue as usual and scan for normal commands
-       if (GenericCommand(command)// handled by common/command/generic.qc
-       || LocalCommand_macro_command(argc) // handled by one of the above LocalCommand_* functions
-       || MUTATOR_CALLHOOK(CSQC_ConsoleCommand, s, argc, command) // handled by a mutator
-       ) return;
-
-       // nothing above caught the command, must be invalid
-       LOG_INFO(((command != "") ? strcat("Unknown client command \"", command, "\"") : "No command provided"), ". For a list of supported commands, try cl_cmd help.\n");
-
-       return;
-}
-
-
-// ===================================
-//  Macro system for console commands
-// ===================================
-
-// These functions are here specifically to add special + - commands to the game, and are not really normal commands.
-// Please add client commands to the function above this, as this is only for special reasons.
-#define CONSOLE_COMMANDS_NORMAL() \
-       CONSOLE_COMMAND("+showscores", { scoreboard_showscores = true; }) \
-       CONSOLE_COMMAND("-showscores", { scoreboard_showscores = false; }) \
-       CONSOLE_COMMAND("+showaccuracy", { scoreboard_showaccuracy = true; }) \
-       CONSOLE_COMMAND("-showaccuracy", { scoreboard_showaccuracy = false; }) \
-       /* nothing */
-
-#define CONSOLE_COMMANDS_MOVEMENT() \
-       CONSOLE_COMMAND("+forward", { ++camera_direction.x; }) \
-       CONSOLE_COMMAND("-forward", { --camera_direction.x; }) \
-       CONSOLE_COMMAND("+back", { --camera_direction.x; }) \
-       CONSOLE_COMMAND("-back", { ++camera_direction.x; }) \
-       CONSOLE_COMMAND("+moveup", { ++camera_direction.z; }) \
-       CONSOLE_COMMAND("-moveup", { --camera_direction.z; }) \
-       CONSOLE_COMMAND("+movedown", { --camera_direction.z; }) \
-       CONSOLE_COMMAND("-movedown", { ++camera_direction.z; }) \
-       CONSOLE_COMMAND("+moveright", { --camera_direction.y; }) \
-       CONSOLE_COMMAND("-moveright", { ++camera_direction.y; }) \
-       CONSOLE_COMMAND("+moveleft", { ++camera_direction.y; }) \
-       CONSOLE_COMMAND("-moveleft", { --camera_direction.y; }) \
-       CONSOLE_COMMAND("+roll_right", { ++camera_roll; }) \
-       CONSOLE_COMMAND("-roll_right", { --camera_roll; }) \
-       CONSOLE_COMMAND("+roll_left", { --camera_roll; }) \
-       CONSOLE_COMMAND("-roll_left", { ++camera_roll; }) \
-       /* nothing */
-
-void ConsoleCommand_macro_init()
-{
-       // first init normal commands
-       #define CONSOLE_COMMAND(name,execution) \
-               { registercommand(name); }
-
-       CONSOLE_COMMANDS_NORMAL();
-       #undef CONSOLE_COMMAND
-
-       // then init movement commands
-       #ifndef CAMERATEST
-       if(isdemo())
-       {
-       #endif
-               #define CONSOLE_COMMAND(name,execution) \
-                       { registercommand(name); }
-
-               CONSOLE_COMMANDS_MOVEMENT();
-               #undef CONSOLE_COMMAND
-       #ifndef CAMERATEST
-       }
-       #endif
-}
-
-bool ConsoleCommand_macro_normal(string s, int argc)
-{
-       #define CONSOLE_COMMAND(name,execution) \
-               { if (name == s) { { execution } return true; } }
-
-       CONSOLE_COMMANDS_NORMAL();
-       #undef CONSOLE_COMMAND
-
-       return false;
-}
-
-bool ConsoleCommand_macro_movement(string s, int argc)
-{
-       if(camera_active)
-       {
-               #define CONSOLE_COMMAND(name,execution) \
-                       { if (name == s) { { execution } return true; } }
-
-               CONSOLE_COMMANDS_MOVEMENT();
-               #undef CONSOLE_COMMAND
-       }
-
-       return false;
-}
-
-
-// ======================================================
-//  Main Function Called By Engine (registered commands)
-// ======================================================
-// Used to parse commands in the console that have been registered with the "registercommand" function
-
-bool CSQC_ConsoleCommand(string command)
-{
-       int argc = tokenize_console(command);
-       string s = strtolower(argv(0));
-       // Return value should be true if CSQC handled the command, otherwise return false to have the engine handle it.
-       return (ConsoleCommand_macro_normal(s, argc)
-       || ConsoleCommand_macro_movement(s, argc)
-       );
-}
diff --git a/qcsrc/client/command/cl_cmd.qh b/qcsrc/client/command/cl_cmd.qh
deleted file mode 100644 (file)
index da34310..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef CL_CMD_H
-#define CL_CMD_H
-// ==============================================
-//  CSQC client commands code, written by Samual
-//  Last updated: December 17th, 2011
-// ==============================================
-
-void Cmd_HUD_SetFields(int);
-void Cmd_HUD_Help();
-
-// used by common/command/generic.qc:GenericCommand_dumpcommands to list all commands into a .txt file
-void LocalCommand_macro_write_aliases(int fh);
-#endif
diff --git a/qcsrc/client/commands/all.qc b/qcsrc/client/commands/all.qc
new file mode 100644 (file)
index 0000000..45d9eaa
--- /dev/null
@@ -0,0 +1,3 @@
+#include "../../common/command/all.qc"
+
+#include "cl_cmd.qc"
diff --git a/qcsrc/client/commands/all.qh b/qcsrc/client/commands/all.qh
new file mode 100644 (file)
index 0000000..eb092c1
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef CLIENT_COMMANDS_ALL_H
+#define CLIENT_COMMANDS_ALL_H
+
+#include "../../common/commands/all.qh"
+
+#include "cl_cmd.qh"
+
+#endif
diff --git a/qcsrc/client/commands/cl_cmd.qc b/qcsrc/client/commands/cl_cmd.qc
new file mode 100644 (file)
index 0000000..bed70f5
--- /dev/null
@@ -0,0 +1,685 @@
+// ==============================================
+//  CSQC client commands code, written by Samual
+//  Last updated: December 28th, 2011
+// ==============================================
+
+#include "../../common/command/command.qh"
+#include "cl_cmd.qh"
+
+#include "../autocvars.qh"
+#include "../defs.qh"
+#include "../hud.qh"
+#include "../hud_config.qh"
+#include "../main.qh"
+#include "../mapvoting.qh"
+#include "../miscfunctions.qh"
+
+#include "../mutators/events.qh"
+
+#include "../../common/mapinfo.qh"
+
+#include "../../common/command/generic.qh"
+
+void DrawDebugModel(entity this)
+{
+       if(time - floor(time) > 0.5)
+       {
+               PolyDrawModel(self);
+               self.drawmask = 0;
+       }
+       else
+       {
+               self.renderflags = 0;
+               self.drawmask = MASK_NORMAL;
+       }
+}
+
+
+// =======================
+//  Command Sub-Functions
+// =======================
+
+void LocalCommand_blurtest(int request)
+{
+       // Simple command to work with postprocessing temporarily... possibly completely pointless, the glsl shader is used for a real feature now...
+       // Anyway, to enable it, just compile the client with -DBLURTEST and then you can use the command.
+
+       #ifdef BLURTEST
+       switch(request)
+       {
+               case CMD_REQUEST_COMMAND:
+               {
+                       blurtest_time0 = time;
+                       blurtest_time1 = time + stof(argv(1));
+                       blurtest_radius = stof(argv(2));
+                       blurtest_power = stof(argv(3));
+                       LOG_INFO("Enabled blurtest\n");
+                       return;
+               }
+
+               default:
+               case CMD_REQUEST_USAGE:
+               {
+                       LOG_INFO("\nUsage:^3 cl_cmd blurtest\n");
+                       LOG_INFO("  No arguments required.\n");
+                       return;
+               }
+       }
+       #else
+       if(request)
+       {
+               LOG_INFO("Blurtest is not enabled on this client.\n");
+               return;
+       }
+       #endif
+}
+
+void LocalCommand_boxparticles(int request, int argc)
+{
+       switch(request)
+       {
+               case CMD_REQUEST_COMMAND:
+               {
+                       if (argc == 9)
+                       {
+                               int effect = _particleeffectnum(argv(1));
+                               if (effect >= 0)
+                               {
+                                       int index = stoi(argv(2));
+                                       entity own;
+                                       if(index <= 0)
+                                               own = entitybyindex(-index);
+                                       else
+                                               own = findfloat(world, entnum, index);
+                                       vector org_from = stov(argv(3));
+                                       vector org_to = stov(argv(4));
+                                       vector dir_from = stov(argv(5));
+                                       vector dir_to = stov(argv(6));
+                                       int countmultiplier = stoi(argv(7));
+                                       int flags = stoi(argv(8));
+                                       boxparticles(effect, own, org_from, org_to, dir_from, dir_to, countmultiplier, flags);
+                                       return;
+                               }
+                       }
+               }
+
+               default:
+                       LOG_INFO("Incorrect parameters for ^2boxparticles^7\n");
+               case CMD_REQUEST_USAGE:
+               {
+                       LOG_INFO("\nUsage:^3 lv_cmd boxparticles effectname own org_from org_to, dir_from, dir_to, countmultiplier, flags\n");
+                       LOG_INFO("  'effectname' is the name of a particle effect in effectinfo.txt\n");
+                       LOG_INFO("  'own' is the entity number of the owner (negative for csqc ent, positive for svqc ent)\n");
+                       LOG_INFO("  'org_from' is the starting origin of the box\n");
+                       LOG_INFO("  'org_to' is the ending origin of the box\n");
+                       LOG_INFO("  'dir_from' is the minimum velocity\n");
+                       LOG_INFO("  'dir_to' is the maximum velocity\n");
+                       LOG_INFO("  'countmultiplier' defines a multiplier for the particle count (affects count only, not countabsolute or trailspacing)\n");
+                       LOG_INFO("  'flags' can contain:\n");
+                       LOG_INFO("    1 to respect globals particles_alphamin, particles_alphamax (set right before via prvm_globalset client)\n");
+                       LOG_INFO("    2 to respect globals particles_colormin, particles_colormax (set right before via prvm_globalset client)\n");
+                       LOG_INFO("    4 to respect globals particles_fade (set right before via prvm_globalset client)\n");
+                       LOG_INFO("    128 to draw a trail, not a box\n");
+                       return;
+               }
+       }
+}
+
+void LocalCommand_create_scrshot_ent(int request)
+{
+       switch(request)
+       {
+               case CMD_REQUEST_COMMAND:
+               {
+                       string filename = strcat(MapInfo_Map_bspname, "_scrshot_ent.txt");
+                       int fh = fopen(filename, FILE_WRITE);
+
+                       if(fh >= 0)
+                       {
+                               fputs(fh, "{\n");
+                               fputs(fh, strcat("\"classname\" \"info_autoscreenshot\"\n"));
+                               fputs(fh, strcat("\"origin\" \"", strcat(ftos(view_origin.x), " ", ftos(view_origin.y), " ", ftos(view_origin.z)), "\"\n"));
+                               fputs(fh, strcat("\"angles\" \"", strcat(ftos(view_angles.x), " ", ftos(view_angles.y), " ", ftos(view_angles.z)), "\"\n"));
+                               fputs(fh, "}\n");
+
+                               LOG_INFO("Completed screenshot entity dump in ^2data/data/", MapInfo_Map_bspname, "_scrshot_ent.txt^7.\n");
+
+                               fclose(fh);
+                       }
+                       else
+                       {
+                               LOG_INFO("^1Error: ^7Could not dump to file!\n");
+                       }
+                       return;
+               }
+
+               default:
+               case CMD_REQUEST_USAGE:
+               {
+                       LOG_INFO("\nUsage:^3 cl_cmd create_scrshot_ent\n");
+                       LOG_INFO("  No arguments required.\n");
+                       return;
+               }
+       }
+}
+
+void LocalCommand_debugmodel(int request, int argc)
+{
+       switch(request)
+       {
+               case CMD_REQUEST_COMMAND:
+               {
+                       string modelname = argv(1);
+                       entity debugmodel_entity;
+
+                       debugmodel_entity = spawn();
+                       precache_model(modelname);
+                       _setmodel(debugmodel_entity, modelname);
+                       setorigin(debugmodel_entity, view_origin);
+                       debugmodel_entity.angles = view_angles;
+                       debugmodel_entity.draw = DrawDebugModel;
+                       debugmodel_entity.classname = "debugmodel";
+
+                       return;
+               }
+
+               default:
+               case CMD_REQUEST_USAGE:
+               {
+                       LOG_INFO("\nUsage:^3 cl_cmd debugmodel model\n");
+                       LOG_INFO("  Where 'model' is a string of the model name to use for the debug model.\n");
+                       return;
+               }
+       }
+}
+
+void LocalCommand_handlevote(int request, int argc)
+{
+       switch(request)
+       {
+               case CMD_REQUEST_COMMAND:
+               {
+                       int vote_selection;
+                       string vote_string;
+
+                       if(InterpretBoolean(argv(1)))
+                       {
+                               vote_selection = 2;
+                               vote_string = "yes";
+                       }
+                       else
+                       {
+                               vote_selection = 1;
+                               vote_string = "no";
+                       }
+
+                       if(vote_selection)
+                       {
+                               if(uid2name_dialog) // handled by "uid2name" option
+                               {
+                                       vote_active = 0;
+                                       vote_prev = 0;
+                                       vote_change = -9999;
+                                       localcmd(strcat("setreport cl_allow_uid2name ", ftos(vote_selection - 1), "\n"));
+                                       uid2name_dialog = 0;
+                               }
+                               else { localcmd(strcat("cmd vote ", vote_string, "\n")); }
+
+                               return;
+                       }
+               }
+
+               default:
+                       LOG_INFO("Incorrect parameters for ^2handlevote^7\n");
+               case CMD_REQUEST_USAGE:
+               {
+                       LOG_INFO("\nUsage:^3 cl_cmd handlevote vote\n");
+                       LOG_INFO("  Where 'vote' is the selection for either the current poll or uid2name.\n");
+                       return;
+               }
+       }
+}
+
+bool QuickMenu_IsOpened();
+void QuickMenu_Close();
+bool QuickMenu_Open(string mode, string submenu);
+
+bool HUD_MinigameMenu_IsOpened();
+void HUD_MinigameMenu_Close();
+void HUD_MinigameMenu_Open();
+
+void HUD_Radar_Show_Maximized(bool doshow, bool clickable);
+
+void LocalCommand_hud(int request, int argc)
+{
+       switch(request)
+       {
+               case CMD_REQUEST_COMMAND:
+               {
+                       switch(argv(1))
+                       {
+                               case "configure":
+                               {
+                                       cvar_set("_hud_configure", ftos(!autocvar__hud_configure));
+                                       return;
+                               }
+
+                               case "quickmenu":
+                               {
+                                       if(QuickMenu_IsOpened())
+                                               QuickMenu_Close();
+                                       else
+                                               QuickMenu_Open(argv(2), argv(3)); // mode, submenu
+                                       return;
+                               }
+
+                               case "minigame":
+                               {
+                                       if(HUD_MinigameMenu_IsOpened())
+                                               HUD_MinigameMenu_Close();
+                                       else
+                                               HUD_MinigameMenu_Open();
+                                       return;
+                               }
+
+                               case "save":
+                               {
+                                       if(argv(2))
+                                       {
+                                               HUD_Panel_ExportCfg(argv(2));
+                                               return;
+                                       }
+                                       else
+                                       {
+                                               break; // go to usage, we're missing the paramater needed here.
+                                       }
+                               }
+
+                               case "scoreboard_columns_set":
+                               {
+                                       Cmd_HUD_SetFields(argc);
+                                       return;
+                               }
+
+                               case "scoreboard_columns_help":
+                               {
+                                       Cmd_HUD_Help();
+                                       return;
+                               }
+
+                               case "radar":
+                               {
+                                       if(argv(2))
+                                               HUD_Radar_Show_Maximized(InterpretBoolean(argv(2)),0);
+                                       else
+                                               HUD_Radar_Show_Maximized(!hud_panel_radar_maximized,0);
+                                       return;
+                               }
+
+                               case "clickradar":
+                               {
+                                       HUD_Radar_Show_Maximized(!hud_panel_radar_mouse,1);
+                                       return;
+                               }
+                       }
+               }
+
+               default:
+                       LOG_INFO("Incorrect parameters for ^2hud^7\n");
+               case CMD_REQUEST_USAGE:
+               {
+                       LOG_INFO("\nUsage:^3 cl_cmd hud action [configname | radartoggle | layout]\n");
+                       LOG_INFO("  Where 'action' is the command to complete,\n");
+                       LOG_INFO("  'configname' is the name to save to for \"save\" action,\n");
+                       LOG_INFO("  'radartoggle' is to control hud_panel_radar_maximized for \"radar\" action,\n");
+                       LOG_INFO("  and 'layout' is how to organize the scoreboard columns for the set action.\n");
+                       LOG_INFO("  quickmenu [[default | file | \"\"] submenu]\n");
+                       LOG_INFO("    Called without options (or with "") loads either the default quickmenu or a quickmenu file if hud_panel_quickmenu_file is set to a valid filename.\n");
+                       LOG_INFO("    Submenu option allows to open quickmenu directly in a submenu, it requires to specify 'default', 'file' or '\"\"' option.\n");
+                       LOG_INFO("  Full list of commands here: \"configure, minigame, save, scoreboard_columns_help, scoreboard_columns_set, radar.\"\n");
+                       return;
+               }
+       }
+}
+
+void LocalCommand_localprint(int request, int argc)
+{
+       switch(request)
+       {
+               case CMD_REQUEST_COMMAND:
+               {
+                       if(argv(1))
+                       {
+                               centerprint_hud(argv(1));
+                               return;
+                       }
+               }
+
+               default:
+                       LOG_INFO("Incorrect parameters for ^2localprint^7\n");
+               case CMD_REQUEST_USAGE:
+               {
+                       LOG_INFO("\nUsage:^3 cl_cmd localprint \"message\"\n");
+                       LOG_INFO("  'message' is the centerprint message to send to yourself.\n");
+                       return;
+               }
+       }
+}
+
+void LocalCommand_mv_download(int request, int argc)
+{
+       switch(request)
+       {
+               case CMD_REQUEST_COMMAND:
+               {
+                       if(argv(1))
+                       {
+                               Cmd_MapVote_MapDownload(argc);
+                               return;
+                       }
+               }
+
+               default:
+                       LOG_INFO("Incorrect parameters for ^2mv_download^7\n");
+               case CMD_REQUEST_USAGE:
+               {
+                       LOG_INFO("\nUsage:^3 cl_cmd mv_download mapid\n");
+                       LOG_INFO("  Where 'mapid' is the id number of the map to request an image of on the map vote selection menu.\n");
+                       return;
+               }
+       }
+}
+
+void LocalCommand_find(int request, int argc)
+{
+       switch(request)
+       {
+               case CMD_REQUEST_COMMAND:
+               {
+                       entity client;
+
+                       for(client = world; (client = find(client, classname, argv(1))); )
+                               LOG_INFO(etos(client), "\n");
+
+                       return;
+               }
+
+               default:
+                       LOG_INFO("Incorrect parameters for ^2find^7\n");
+               case CMD_REQUEST_USAGE:
+               {
+                       LOG_INFO("\nUsage:^3 cl_cmd find classname\n");
+                       LOG_INFO("  Where 'classname' is the classname to search for.\n");
+                       return;
+               }
+       }
+}
+
+void LocalCommand_sendcvar(int request, int argc)
+{
+       switch(request)
+       {
+               case CMD_REQUEST_COMMAND:
+               {
+                       if(argv(1))
+                       {
+                               // W_FixWeaponOrder will trash argv, so save what we need.
+                               string thiscvar = strzone(argv(1));
+                               string s = cvar_string(thiscvar);
+
+                               if(thiscvar == "cl_weaponpriority")
+                                       s = W_FixWeaponOrder(W_NumberWeaponOrder(s), 1);
+                               else if(substring(thiscvar, 0, 17) == "cl_weaponpriority" && strlen(thiscvar) == 18)
+                                       s = W_FixWeaponOrder(W_NumberWeaponOrder(s), 0);
+
+                               localcmd("cmd sentcvar ", thiscvar, " \"", s, "\"\n");
+                               strunzone(thiscvar);
+                               return;
+                       }
+               }
+
+               default:
+                       LOG_INFO("Incorrect parameters for ^2sendcvar^7\n");
+               case CMD_REQUEST_USAGE:
+               {
+                       LOG_INFO("\nUsage:^3 cl_cmd sendcvar <cvar>\n");
+                       LOG_INFO("  Where 'cvar' is the cvar plus arguments to send to the server.\n");
+                       return;
+               }
+       }
+}
+
+/* use this when creating a new command, making sure to place it in alphabetical order... also,
+** ADD ALL NEW COMMANDS TO commands.cfg WITH PROPER ALIASES IN THE SAME FASHION!
+void LocalCommand_(int request)
+{
+       switch(request)
+       {
+               case CMD_REQUEST_COMMAND:
+               {
+
+                       return;
+               }
+
+               default:
+               case CMD_REQUEST_USAGE:
+               {
+                       print("\nUsage:^3 cl_cmd \n");
+                       print("  No arguments required.\n");
+                       return;
+               }
+       }
+}
+*/
+
+
+// ==================================
+//  Macro system for client commands
+// ==================================
+
+// Normally do not hard code aliases for these, instead create them in commands.cfg... also: keep in alphabetical order, please ;)
+#define CLIENT_COMMANDS(request,arguments) \
+       CLIENT_COMMAND("blurtest", LocalCommand_blurtest(request), "Feature for testing blur postprocessing") \
+       CLIENT_COMMAND("boxparticles", LocalCommand_boxparticles(request, arguments), "Spawn particles manually") \
+       CLIENT_COMMAND("create_scrshot_ent", LocalCommand_create_scrshot_ent(request), "Create an entity at this location for automatic screenshots") \
+       CLIENT_COMMAND("debugmodel", LocalCommand_debugmodel(request, arguments), "Spawn a debug model manually") \
+       CLIENT_COMMAND("handlevote", LocalCommand_handlevote(request, arguments), "System to handle selecting a vote or option") \
+       CLIENT_COMMAND("hud", LocalCommand_hud(request, arguments), "Commands regarding/controlling the HUD system") \
+       CLIENT_COMMAND("localprint", LocalCommand_localprint(request, arguments), "Create your own centerprint sent to yourself") \
+       CLIENT_COMMAND("find", LocalCommand_find(request, arguments), "Search through entities for matching classname") \
+       CLIENT_COMMAND("mv_download", LocalCommand_mv_download(request, arguments), "Retrieve mapshot picture from the server") \
+       CLIENT_COMMAND("sendcvar", LocalCommand_sendcvar(request, arguments), "Send a cvar to the server (like weaponpriority)") \
+       /* nothing */
+
+void LocalCommand_macro_help()
+{
+       #define CLIENT_COMMAND(name,function,description) \
+               { if(strtolower(description) != "") { LOG_INFO("  ^2", name, "^7: ", description, "\n"); } }
+
+       CLIENT_COMMANDS(0, 0);
+       #undef CLIENT_COMMAND
+
+       return;
+}
+
+bool LocalCommand_macro_command(int argc)
+{
+       #define CLIENT_COMMAND(name,function,description) \
+               { if(name == strtolower(argv(0))) { function; return true; } }
+
+       CLIENT_COMMANDS(CMD_REQUEST_COMMAND, argc);
+       #undef CLIENT_COMMAND
+
+       return false;
+}
+
+bool LocalCommand_macro_usage(int argc)
+{
+       #define CLIENT_COMMAND(name,function,description) \
+               { if(name == strtolower(argv(1))) { function; return true; } }
+
+       CLIENT_COMMANDS(CMD_REQUEST_USAGE, argc);
+       #undef CLIENT_COMMAND
+
+       return false;
+}
+
+void LocalCommand_macro_write_aliases(int fh)
+{
+       #define CLIENT_COMMAND(name,function,description) \
+               { if(strtolower(description) != "") { CMD_Write_Alias("qc_cmd_cl", name, description); } }
+
+       CLIENT_COMMANDS(0, 0);
+       #undef CLIENT_COMMAND
+
+       return;
+}
+
+
+// =========================================
+//  Main Function Called By Engine (cl_cmd)
+// =========================================
+// If this function exists, client code handles gamecommand instead of the engine code.
+
+void GameCommand(string command)
+{
+       int argc = tokenize_console(command);
+
+       // Guide for working with argc arguments by example:
+       // argc:   1    - 2      - 3     - 4
+       // argv:   0    - 1      - 2     - 3
+       // cmd     vote - master - login - password
+       string s = strtolower(argv(0));
+       if (s == "help")
+       {
+               if(argc == 1)
+               {
+                       LOG_INFO("\nClient console commands:\n");
+                       LocalCommand_macro_help();
+
+                       LOG_INFO("\nGeneric commands shared by all programs:\n");
+                       GenericCommand_macro_help();
+
+                       LOG_INFO("\nUsage:^3 cl_cmd COMMAND...^7, where possible commands are listed above.\n");
+                       LOG_INFO("For help about a specific command, type cl_cmd help COMMAND\n");
+
+                       return;
+               }
+               else if(GenericCommand_macro_usage(argc)) // Instead of trying to call a command, we're going to see detailed information about it
+               {
+                       return;
+               }
+               else if(LocalCommand_macro_usage(argc)) // now try for normal commands too
+               {
+                       return;
+               }
+       }
+       // continue as usual and scan for normal commands
+       if (GenericCommand(command)// handled by common/command/generic.qc
+       || LocalCommand_macro_command(argc) // handled by one of the above LocalCommand_* functions
+       || MUTATOR_CALLHOOK(CSQC_ConsoleCommand, s, argc, command) // handled by a mutator
+       ) return;
+
+       // nothing above caught the command, must be invalid
+       LOG_INFO(((command != "") ? strcat("Unknown client command \"", command, "\"") : "No command provided"), ". For a list of supported commands, try cl_cmd help.\n");
+
+       return;
+}
+
+
+// ===================================
+//  Macro system for console commands
+// ===================================
+
+// These functions are here specifically to add special + - commands to the game, and are not really normal commands.
+// Please add client commands to the function above this, as this is only for special reasons.
+#define CONSOLE_COMMANDS_NORMAL() \
+       CONSOLE_COMMAND("+showscores", { scoreboard_showscores = true; }) \
+       CONSOLE_COMMAND("-showscores", { scoreboard_showscores = false; }) \
+       CONSOLE_COMMAND("+showaccuracy", { scoreboard_showaccuracy = true; }) \
+       CONSOLE_COMMAND("-showaccuracy", { scoreboard_showaccuracy = false; }) \
+       /* nothing */
+
+#define CONSOLE_COMMANDS_MOVEMENT() \
+       CONSOLE_COMMAND("+forward", { ++camera_direction.x; }) \
+       CONSOLE_COMMAND("-forward", { --camera_direction.x; }) \
+       CONSOLE_COMMAND("+back", { --camera_direction.x; }) \
+       CONSOLE_COMMAND("-back", { ++camera_direction.x; }) \
+       CONSOLE_COMMAND("+moveup", { ++camera_direction.z; }) \
+       CONSOLE_COMMAND("-moveup", { --camera_direction.z; }) \
+       CONSOLE_COMMAND("+movedown", { --camera_direction.z; }) \
+       CONSOLE_COMMAND("-movedown", { ++camera_direction.z; }) \
+       CONSOLE_COMMAND("+moveright", { --camera_direction.y; }) \
+       CONSOLE_COMMAND("-moveright", { ++camera_direction.y; }) \
+       CONSOLE_COMMAND("+moveleft", { ++camera_direction.y; }) \
+       CONSOLE_COMMAND("-moveleft", { --camera_direction.y; }) \
+       CONSOLE_COMMAND("+roll_right", { ++camera_roll; }) \
+       CONSOLE_COMMAND("-roll_right", { --camera_roll; }) \
+       CONSOLE_COMMAND("+roll_left", { --camera_roll; }) \
+       CONSOLE_COMMAND("-roll_left", { ++camera_roll; }) \
+       /* nothing */
+
+void ConsoleCommand_macro_init()
+{
+       // first init normal commands
+       #define CONSOLE_COMMAND(name,execution) \
+               { registercommand(name); }
+
+       CONSOLE_COMMANDS_NORMAL();
+       #undef CONSOLE_COMMAND
+
+       // then init movement commands
+       #ifndef CAMERATEST
+       if(isdemo())
+       {
+       #endif
+               #define CONSOLE_COMMAND(name,execution) \
+                       { registercommand(name); }
+
+               CONSOLE_COMMANDS_MOVEMENT();
+               #undef CONSOLE_COMMAND
+       #ifndef CAMERATEST
+       }
+       #endif
+}
+
+bool ConsoleCommand_macro_normal(string s, int argc)
+{
+       #define CONSOLE_COMMAND(name,execution) \
+               { if (name == s) { { execution } return true; } }
+
+       CONSOLE_COMMANDS_NORMAL();
+       #undef CONSOLE_COMMAND
+
+       return false;
+}
+
+bool ConsoleCommand_macro_movement(string s, int argc)
+{
+       if(camera_active)
+       {
+               #define CONSOLE_COMMAND(name,execution) \
+                       { if (name == s) { { execution } return true; } }
+
+               CONSOLE_COMMANDS_MOVEMENT();
+               #undef CONSOLE_COMMAND
+       }
+
+       return false;
+}
+
+
+// ======================================================
+//  Main Function Called By Engine (registered commands)
+// ======================================================
+// Used to parse commands in the console that have been registered with the "registercommand" function
+
+bool CSQC_ConsoleCommand(string command)
+{
+       int argc = tokenize_console(command);
+       string s = strtolower(argv(0));
+       // Return value should be true if CSQC handled the command, otherwise return false to have the engine handle it.
+       return (ConsoleCommand_macro_normal(s, argc)
+       || ConsoleCommand_macro_movement(s, argc)
+       );
+}
diff --git a/qcsrc/client/commands/cl_cmd.qh b/qcsrc/client/commands/cl_cmd.qh
new file mode 100644 (file)
index 0000000..ba3151c
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef CLIENT_COMMANDS_CL_CMD_H
+#define CLIENT_COMMANDS_CL_CMD_H
+// ==============================================
+//  CSQC client commands code, written by Samual
+//  Last updated: December 17th, 2011
+// ==============================================
+
+void Cmd_HUD_SetFields(int);
+void Cmd_HUD_Help();
+
+// used by common/command/generic.qc:GenericCommand_dumpcommands to list all commands into a .txt file
+void LocalCommand_macro_write_aliases(int fh);
+#endif
index 34301d8063dc50501381721eaf01040ad7ebc51a..575bce513c763aec1b942a260539a8a522c7e27c 100644 (file)
@@ -1,8 +1,9 @@
 #include "controlpoint.qh"
-#include "gibs.qh"
+
 #include "teamradar.qh"
 #include "../common/movetypes/movetypes.qh"
 
+.vector colormod;
 .float alpha;
 .int count;
 .float pain_finished;
index 31485519d4eefee415115cd3098d03fc80d821cd..5f2e89b4d7a33e93b350a005c44b855a587f6ce3 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef CONTROLPOINT_H
-#define CONTROLPOINT_H
+#ifndef CLIENT_CONTROLPOINT_H
+#define CLIENT_CONTROLPOINT_H
 
 const vector CPICON_MIN = '-32 -32 -9';
 const vector CPICON_MAX = '32 32 25';
index 09d217bc2c0075fea962f918a59516f557390597..584f001f88ad0b9763658c1fce02d4eaed3006e3 100644 (file)
@@ -1,8 +1,5 @@
-#ifndef CSQC_CONSTANTS
-#define CSQC_CONSTANTS
-
-// MenuQC redefines world, change define it here to be safe
-#define world world
+#ifndef CLIENT_CSQC_CONSTANTS
+#define CLIENT_CSQC_CONSTANTS
 
 // Mask Constants (set .drawmask on entities; use R_AddEntities to add all entities based on mask)
 const int              MASK_ENGINE                                             = 1;
index c7e05799dbcbf37ab6f0db25f036195c8f35bf05..6e7e5a8de77444946bec59756357d218a838975c 100644 (file)
@@ -1,22 +1,12 @@
-#include "_all.qh"
-
-#include "gibs.qh"
+#include "mutators/events.qh"
 #include "player_skeleton.qh"
-
 #include "weapons/projectile.qh"
-
 #include "../common/animdecide.qh"
-#include "../common/csqcmodel_settings.qh"
-#include "../common/effects/effects.qh"
-#include "../common/teams.qh"
-#include "../common/triggers/trigger/viewloc.qh"
-
-#include "mutators/events.qh"
-
-#include "../csqcmodellib/cl_model.qh"
-#include "../csqcmodellib/cl_player.qh"
-#include "../csqcmodellib/interpolate.qh"
-
+#include "../common/movetypes/movetypes.qh"
+#include "../common/viewloc.qh"
+#include "../lib/csqcmodel/cl_model.qh"
+#include "../lib/csqcmodel/cl_player.qh"
+#include "../lib/csqcmodel/interpolate.qh"
 
 .float death_time;
 .int modelflags;
@@ -401,11 +391,7 @@ void CSQCModel_AutoTagIndex_Apply(void)
        if(self.tag_entity && wasfreed(self.tag_entity))
                self.tag_entity = world;
 
-       if(self.viewloc && wasfreed(self.viewloc))
-               self.viewloc = world;
-
-       if(self.viewloc.entnum != self.tag_networkviewloc)
-               self.viewloc = findfloat(world, entnum, self.tag_networkviewloc);
+       viewloc_SetTags();
 
        MUTATOR_CALLHOOK(TagIndex_Update, self);
 
index 94560a8332d214bd2223718d2ffcc4af0c18bd04..34890e034eaaeb323495e02d606eda203a0eb7af 100644 (file)
@@ -1,16 +1,9 @@
 #include "damage.qh"
-#include "_all.qh"
 
 #include "gibs.qh"
-
-#include "../common/vehicles/all.qh"
-
-#include "../common/constants.qh"
 #include "../common/deathtypes/all.qh"
-#include "../common/effects/effects.qh"
 #include "../common/movetypes/movetypes.qh"
-#include "../common/util.qh"
-
+#include "../common/vehicles/all.qh"
 #include "../common/weapons/all.qh"
 
 .entity tag_entity;
index 0de69a02d850a478906840ff353ed81902061059..3f11b9a49e71232f2920d6fa1f5685dd39e9aeb5 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef DAMAGE_H
-#define DAMAGE_H
+#ifndef CLIENT_DAMAGE_H
+#define CLIENT_DAMAGE_H
 
 .float total_damages; // number of effects which currently are attached to a player
 
index c0c378fd1a42c4cb5fb697902e8bdca4c743539c..21fa1ce037137e187a35bd29ed70e42b0eb757e2 100644 (file)
@@ -1,5 +1,4 @@
 #include "effects.qh"
-#include "_all.qh"
 
 /*
 .vector fx_start;
index 0bebdb95de40c14c98821fd57aab014b70e8ab2f..2d93f41d71b506c99362c5cf5fcd42e34d5d60ea 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef EFFECTS_H
-#define EFFECTS_H
+#ifndef CLIENT_EFFECTS_H
+#define CLIENT_EFFECTS_H
 
 void Net_ReadArc();
 
index eed682785e0ec2ee8877f4aa71546c6843c20be4..d7114d1bf4b904ae36d685fb6444507e50eb0151 100644 (file)
@@ -1,5 +1,10 @@
 #include "generator.qh"
 
+#include "teamradar.qh"
+#include "../common/movetypes/movetypes.qh"
+
+.float alpha;
+.float scale;
 .int count;
 .float max_health;
 
index 744bc5589f47a39edba81e1bf1fe78dbc215d617..c60aff4009ac5d113b0ff0039ed5baf04de030d4 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef GENERATOR_H
-#define GENERATOR_H
+#ifndef CLIENT_GENERATOR_H
+#define CLIENT_GENERATOR_H
 const vector GENERATOR_MIN = '-52 -52 -14';
 const vector GENERATOR_MAX = '52 52 75';
 
index 360f7b5c361bdb6b99435575f8dfb5553e6de855..4afa5eb88ac47a45155b614a69854d78b9060226 100644 (file)
@@ -1,11 +1,7 @@
 #include "gibs.qh"
-#include "_all.qh"
 
 #include "rubble.qh"
-
-#include "../common/constants.qh"
 #include "../common/movetypes/movetypes.qh"
-#include "../common/util.qh"
 
 .float scale;
 .float alpha;
index f4b60948af7cf0a103c19da8645e18317e7178cf..eb63aa1fe5ec29e8344c3089e1395c0622bcb175 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef GIBS_H
-#define GIBS_H
+#ifndef CLIENT_GIBS_H
+#define CLIENT_GIBS_H
 
 .vector colormod;
 
index 07123f06b5ec278b9bb1d609a7e9e8d195032836..3f623b276ed068bb3baeb4582680b37c495b0ea7 100644 (file)
@@ -1,13 +1,7 @@
 #include "hook.qh"
-#include "_all.qh"
 
-#include "hud.qh"
-
-#include "../common/teams.qh"
-
-#include "../csqcmodellib/interpolate.qh"
-
-#include "../warpzonelib/common.qh"
+#include "../lib/csqcmodel/interpolate.qh"
+#include "../lib/warpzone/common.qh"
 
 entityclass(Hook);
 class(Hook) .float HookType; // ENT_CLIENT_*
index e513ed6afa4451ee0271a1bc33d15716b869edfc..9e6ee548cfab5ae0a97a169b213c9596d497ff85 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef HOOK_H
-#define HOOK_H
+#ifndef CLIENT_HOOK_H
+#define CLIENT_HOOK_H
 
 void Draw_CylindricLine(vector from, vector to, float thickness, string texture, float aspect, float shift, vector rgb, float theAlpha, float drawflag, vector vieworg);
 
index 5ae44f41655788d9005497bf6f71542d360ca56b..90be935df3b43528717b39aa53e0eefc1404ab4e 100644 (file)
@@ -1,27 +1,19 @@
 #include "hud.qh"
-#include "_all.qh"
 
 #include "hud_config.qh"
 #include "mapvoting.qh"
 #include "scoreboard.qh"
 #include "teamradar.qh"
 #include "t_items.qh"
-
-#include "../dpdefs/keycodes.qh"
-
 #include "../common/buffs/all.qh"
-#include "../common/constants.qh"
 #include "../common/deathtypes/all.qh"
 #include "../common/items/all.qc"
 #include "../common/mapinfo.qh"
-#include "../common/nades/all.qh"
-
 #include "../common/mutators/mutator/waypoints/all.qh"
-#include "../server/mutators/gamemode_ctf.qh"
-
+#include "../common/nades/all.qh"
 #include "../common/stats.qh"
-
-#include "../csqcmodellib/cl_player.qh"
+#include "../lib/csqcmodel/cl_player.qh"
+#include "../server/mutators/gamemode_ctf.qh"
 
 
 /*
@@ -206,12 +198,6 @@ HUD panels
 ==================
 */
 
-// draw the background/borders
-#define HUD_Panel_DrawBg(theAlpha) do {                                                                                                                                                                \
-       if(panel.current_panel_bg != "0" && panel.current_panel_bg != "")                                                                                               \
-               draw_BorderPicture(panel_pos - '1 1 0' * panel_bg_border, panel.current_panel_bg, panel_size + '1 1 0' * 2 * panel_bg_border, panel_bg_color, panel_bg_alpha * theAlpha, '1 1 0' * (panel_bg_border/BORDER_MULTIPLIER));\
-} while(0)
-
 //basically the same code of draw_ButtonPicture and draw_VertButtonPicture for the menu
 void HUD_Panel_DrawProgressBar(vector theOrigin, vector theSize, string pic, float length_ratio, bool vertical, float baralign, vector theColor, float theAlpha, int drawflag)
 {
@@ -4465,7 +4451,7 @@ void HUD_CenterPrint (void)
                        reset_centerprint_messages();
                if (time > hud_configure_cp_generation_time)
                {
-                       if(HUD_PANEL(CENTERPRINT) == highlightedPanel)
+                       if(highlightedPanel == HUD_PANEL(CENTERPRINT))
                        {
                                float r;
                                r = random();
@@ -4800,18 +4786,18 @@ void HUD_Main (void)
 
        // cache the panel order into the panel_order array
        if(autocvar__hud_panelorder != hud_panelorder_prev) {
-               for(i = 0; i < HUD_PANEL_NUM; ++i)
+               for(i = 0; i < hud_panels_COUNT; ++i)
                        panel_order[i] = -1;
                string s = "";
                int p_num;
                bool warning = false;
                int argc = tokenize_console(autocvar__hud_panelorder);
-               if (argc > HUD_PANEL_NUM)
+               if (argc > hud_panels_COUNT)
                        warning = true;
                //first detect wrong/missing panel numbers
-               for(i = 0; i < HUD_PANEL_NUM; ++i) {
+               for(i = 0; i < hud_panels_COUNT; ++i) {
                        p_num = stoi(argv(i));
-                       if (p_num >= 0 && p_num < HUD_PANEL_NUM) { //correct panel number?
+                       if (p_num >= 0 && p_num < hud_panels_COUNT) { //correct panel number?
                                if (panel_order[p_num] == -1) //found for the first time?
                                        s = strcat(s, ftos(p_num), " ");
                                panel_order[p_num] = 1; //mark as found
@@ -4819,7 +4805,7 @@ void HUD_Main (void)
                        else
                                warning = true;
                }
-               for(i = 0; i < HUD_PANEL_NUM; ++i) {
+               for(i = 0; i < hud_panels_COUNT; ++i) {
                        if (panel_order[i] == -1) {
                                warning = true;
                                s = strcat(s, ftos(i), " "); //add missing panel number
@@ -4835,15 +4821,15 @@ void HUD_Main (void)
 
                //now properly set panel_order
                tokenize_console(s);
-               for(i = 0; i < HUD_PANEL_NUM; ++i) {
+               for(i = 0; i < hud_panels_COUNT; ++i) {
                        panel_order[i] = stof(argv(i));
                }
        }
 
        hud_draw_maximized = 0;
        // draw panels in the order specified by panel_order array
-       for(i = HUD_PANEL_NUM - 1; i >= 0; --i)
-               HUD_Panel_Draw(hud_panel[panel_order[i]]);
+       for(i = hud_panels_COUNT - 1; i >= 0; --i)
+               HUD_Panel_Draw(hud_panels[panel_order[i]]);
 
        hud_draw_maximized = 1; // panels that may be maximized must check this var
        // draw maximized panels on top
index ebde4b12b8c4e81abca18085b68c31afea751b26..517fd8c07bcd521b7b86b73fe79e1dc110ecec26 100644 (file)
@@ -1,15 +1,32 @@
-#ifndef HUD_H
-#define HUD_H
+#ifndef CLIENT_HUD_H
+#define CLIENT_HUD_H
 
 #include "../common/weapons/all.qh"
 
-const int HUD_PANEL_MAX = 24;
-entity hud_panel[HUD_PANEL_MAX];
-const int HUD_PANEL_FIRST = 0;
-int HUD_PANEL_NUM;
-int HUD_PANEL_LAST;
+bool HUD_Radar_Clickable();
+void HUD_Radar_Mouse();
 
-int panel_order[HUD_PANEL_MAX];
+REGISTRY(hud_panels, 24)
+REGISTER_REGISTRY(Registerhud_panels)
+
+#define REGISTER_HUD_PANEL(id, draw_func, name, showflags) \
+       void draw_func(); \
+       REGISTER(Registerhud_panels, HUD_PANEL, hud_panels, id, m_id, new(hud_panel)) { \
+               this.panel_id = this.m_id; \
+               this.panel_draw = draw_func; \
+               this.panel_name = #name; \
+               this.panel_showflags = showflags; \
+       }
+
+#define HUD_PANEL(NAME) HUD_PANEL_##NAME
+
+// draw the background/borders
+#define HUD_Panel_DrawBg(theAlpha) do {                                                                                                                                                                \
+       if(panel.current_panel_bg != "0" && panel.current_panel_bg != "")                                                                                               \
+               draw_BorderPicture(panel_pos - '1 1 0' * panel_bg_border, panel.current_panel_bg, panel_size + '1 1 0' * 2 * panel_bg_border, panel_bg_color, panel_bg_alpha * theAlpha, '1 1 0' * (panel_bg_border/BORDER_MULTIPLIER));\
+} while(0)
+
+int panel_order[hud_panels_MAX];
 string hud_panelorder_prev;
 
 bool hud_draw_maximized;
@@ -20,6 +37,7 @@ bool hud_panel_radar_temp_hidden;
 bool chat_panel_modified;
 bool radar_panel_modified;
 
+float HUD_Radar_InputEvent(float bInputType, float nPrimary, float nSecondary);
 void HUD_Radar_Hide_Maximized();
 
 void HUD_Reset (void);
@@ -156,55 +174,31 @@ int prev_p_health, prev_p_armor;
 
 void HUD_ItemsTime();
 
-#define HUD_PANELS(HUD_PANEL) \
-       HUD_PANEL(WEAPONS      , HUD_Weapons      , weapons,        PANEL_SHOW_MAINGAME ) \
-       HUD_PANEL(AMMO         , HUD_Ammo         , ammo,           PANEL_SHOW_MAINGAME ) \
-       HUD_PANEL(POWERUPS     , HUD_Powerups     , powerups,       PANEL_SHOW_MAINGAME ) \
-       HUD_PANEL(HEALTHARMOR  , HUD_HealthArmor  , healtharmor,    PANEL_SHOW_MAINGAME ) \
-       HUD_PANEL(NOTIFY       , HUD_Notify       , notify,         PANEL_SHOW_ALWAYS   ) \
-       HUD_PANEL(TIMER        , HUD_Timer        , timer,          PANEL_SHOW_ALWAYS   ) \
-       HUD_PANEL(RADAR        , HUD_Radar        , radar,          PANEL_SHOW_MAINGAME ) \
-       HUD_PANEL(SCORE        , HUD_Score        , score,          PANEL_SHOW_ALWAYS   ) \
-       HUD_PANEL(RACETIMER    , HUD_RaceTimer    , racetimer,      PANEL_SHOW_MAINGAME ) \
-       HUD_PANEL(VOTE         , HUD_Vote         , vote,           PANEL_SHOW_ALWAYS   ) \
-       HUD_PANEL(MODICONS     , HUD_ModIcons     , modicons,       PANEL_SHOW_MAINGAME ) \
-       HUD_PANEL(PRESSEDKEYS  , HUD_PressedKeys  , pressedkeys,    PANEL_SHOW_MAINGAME ) \
-       HUD_PANEL(CHAT         , HUD_Chat         , chat,           PANEL_SHOW_ALWAYS   ) \
-       HUD_PANEL(ENGINEINFO   , HUD_EngineInfo   , engineinfo,     PANEL_SHOW_ALWAYS   ) \
-       HUD_PANEL(INFOMESSAGES , HUD_InfoMessages , infomessages,   PANEL_SHOW_MAINGAME ) \
-       HUD_PANEL(PHYSICS      , HUD_Physics      , physics,        PANEL_SHOW_MAINGAME ) \
-       HUD_PANEL(CENTERPRINT  , HUD_CenterPrint  , centerprint,    PANEL_SHOW_MAINGAME ) \
-       HUD_PANEL(MINIGAME_BOARD, HUD_MinigameBoard ,minigameboard, PANEL_SHOW_MINIGAME ) \
-       HUD_PANEL(MINIGAME_STATUS,HUD_MinigameStatus,minigamestatus,PANEL_SHOW_MINIGAME ) \
-       HUD_PANEL(MINIGAME_HELP,  HUD_MinigameHelp  ,minigamehelp,  PANEL_SHOW_MINIGAME ) \
-       HUD_PANEL(MINIGAME_MENU,  HUD_MinigameMenu  ,minigamemenu,  PANEL_SHOW_ALWAYS   ) \
-       HUD_PANEL(MAPVOTE      ,  MapVote_Draw      ,mapvote,       PANEL_SHOW_ALWAYS   ) \
-       HUD_PANEL(ITEMSTIME    ,  HUD_ItemsTime     ,itemstime,     PANEL_SHOW_MAINGAME ) \
-       HUD_PANEL(QUICKMENU    , HUD_QuickMenu    , quickmenu,      PANEL_SHOW_MAINGAME ) \
-       // always add new panels to the end of list
-
-
-#define HUD_PANEL(NAME, draw_func, name, showflags)                                                                                                                                                    \
-       int HUD_PANEL_##NAME;                                                                                                                                                                                   \
-       void draw_func(void);                                                                                                                                                                                   \
-       void RegisterHUD_Panel_##NAME() {                                                                                                                                                               \
-               HUD_PANEL_LAST = HUD_PANEL_##NAME = HUD_PANEL_NUM;                                                                                                                      \
-               entity hud_panelent = spawn();                                                                                                                                                          \
-               hud_panel[HUD_PANEL_##NAME] = hud_panelent;                                                                                                                             \
-               hud_panelent.classname = "hud_panel";                                                                                                                                           \
-               hud_panelent.panel_name = #name;                                                                                                                                                        \
-               hud_panelent.panel_id = HUD_PANEL_##NAME;                                                                                                                                       \
-               hud_panelent.panel_draw = draw_func;                                                                                                                                            \
-               hud_panelent.panel_showflags = showflags;                                                                                                                                       \
-               HUD_PANEL_NUM++;                                                                                                                                                                                        \
-       }                                                                                                                                                                                                                               \
-       ACCUMULATE_FUNCTION(RegisterHUD_Panels, RegisterHUD_Panel_##NAME)
-
-HUD_PANELS(HUD_PANEL)
-#undef HUD_PANEL
-
-#define HUD_PANEL(NAME) hud_panel[HUD_PANEL_##NAME]
-
+REGISTER_HUD_PANEL(WEAPONS,         HUD_Weapons,        weapons,        PANEL_SHOW_MAINGAME)
+REGISTER_HUD_PANEL(AMMO,            HUD_Ammo,           ammo,           PANEL_SHOW_MAINGAME)
+REGISTER_HUD_PANEL(POWERUPS,        HUD_Powerups,       powerups,       PANEL_SHOW_MAINGAME)
+REGISTER_HUD_PANEL(HEALTHARMOR,     HUD_HealthArmor,    healtharmor,    PANEL_SHOW_MAINGAME)
+REGISTER_HUD_PANEL(NOTIFY,          HUD_Notify,         notify,         PANEL_SHOW_ALWAYS  )
+REGISTER_HUD_PANEL(TIMER,           HUD_Timer,          timer,          PANEL_SHOW_ALWAYS  )
+REGISTER_HUD_PANEL(RADAR,           HUD_Radar,          radar,          PANEL_SHOW_MAINGAME)
+REGISTER_HUD_PANEL(SCORE,           HUD_Score,          score,          PANEL_SHOW_ALWAYS  )
+REGISTER_HUD_PANEL(RACETIMER,       HUD_RaceTimer,      racetimer,      PANEL_SHOW_MAINGAME)
+REGISTER_HUD_PANEL(VOTE,            HUD_Vote,           vote,           PANEL_SHOW_ALWAYS  )
+REGISTER_HUD_PANEL(MODICONS,        HUD_ModIcons,       modicons,       PANEL_SHOW_MAINGAME)
+REGISTER_HUD_PANEL(PRESSEDKEYS,     HUD_PressedKeys,    pressedkeys,    PANEL_SHOW_MAINGAME)
+REGISTER_HUD_PANEL(CHAT,            HUD_Chat,           chat,           PANEL_SHOW_ALWAYS  )
+REGISTER_HUD_PANEL(ENGINEINFO,      HUD_EngineInfo,     engineinfo,     PANEL_SHOW_ALWAYS  )
+REGISTER_HUD_PANEL(INFOMESSAGES,    HUD_InfoMessages,   infomessages,   PANEL_SHOW_MAINGAME)
+REGISTER_HUD_PANEL(PHYSICS,         HUD_Physics,        physics,        PANEL_SHOW_MAINGAME)
+REGISTER_HUD_PANEL(CENTERPRINT,     HUD_CenterPrint,    centerprint,    PANEL_SHOW_MAINGAME)
+REGISTER_HUD_PANEL(MINIGAME_BOARD,  HUD_MinigameBoard,  minigameboard,  PANEL_SHOW_MINIGAME)
+REGISTER_HUD_PANEL(MINIGAME_STATUS, HUD_MinigameStatus, minigamestatus, PANEL_SHOW_MINIGAME)
+REGISTER_HUD_PANEL(MINIGAME_HELP,   HUD_MinigameHelp,   minigamehelp,   PANEL_SHOW_MINIGAME)
+REGISTER_HUD_PANEL(MINIGAME_MENU,   HUD_MinigameMenu,   minigamemenu,   PANEL_SHOW_ALWAYS  )
+REGISTER_HUD_PANEL(MAPVOTE,         MapVote_Draw,       mapvote,        PANEL_SHOW_ALWAYS  )
+REGISTER_HUD_PANEL(ITEMSTIME,       HUD_ItemsTime,      itemstime,      PANEL_SHOW_MAINGAME)
+REGISTER_HUD_PANEL(QUICKMENU,       HUD_QuickMenu,      quickmenu,      PANEL_SHOW_MAINGAME)
+// always add new panels to the end of list
 
 // Because calling lots of functions in QC apparently cuts fps in half on many machines:
 // ----------------------
index 0216a43b087b6b0352148f12ac95ba41a8cc1a7d..148c0ec8e057ca0c523fb1d46a61d310438a8087 100644 (file)
@@ -1,13 +1,7 @@
 #include "hud_config.qh"
-#include "_all.qh"
 
 #include "hud.qh"
 
-#include "../common/constants.qh"
-
-#include "../dpdefs/keycodes.qh"
-
-
 #define HUD_Write(s) fputs(fh, s)
 // q: quoted, n: not quoted
 #define HUD_Write_Cvar_n(cvar) HUD_Write(strcat("seta ", cvar, " ", cvar_string(cvar), "\n"))
@@ -59,10 +53,9 @@ void HUD_Panel_ExportCfg(string cfgname)
                HUD_Write("\n");
 
                // common cvars for all panels
-               int i;
-               for (i = 0; i < HUD_PANEL_NUM; ++i)
+               for (int i = 0; i < hud_panels_COUNT; ++i)
                {
-                       panel = hud_panel[i];
+                       panel = hud_panels[i];
 
                        HUD_Write_PanelCvar_n("");
                        HUD_Write_PanelCvar_q("_pos");
@@ -73,7 +66,7 @@ void HUD_Panel_ExportCfg(string cfgname)
                        HUD_Write_PanelCvar_q("_bg_alpha");
                        HUD_Write_PanelCvar_q("_bg_border");
                        HUD_Write_PanelCvar_q("_bg_padding");
-                       switch(i) {
+                       switch(panel) {
                                case HUD_PANEL_WEAPONS:
                                        HUD_Write_PanelCvar_q("_accuracy");
                                        HUD_Write_PanelCvar_q("_label");
@@ -240,8 +233,8 @@ vector HUD_Panel_CheckMove(vector myPos, vector mySize)
        vector myCenter, targCenter;
        vector myTarget = myPos;
        int i;
-       for (i = 0; i < HUD_PANEL_NUM; ++i) {
-               panel = hud_panel[i];
+       for (i = 0; i < hud_panels_COUNT; ++i) {
+               panel = hud_panels[i];
                if(panel == HUD_PANEL(MAPVOTE)) continue;
                if(panel == highlightedPanel) continue;
                HUD_Panel_UpdatePosSize();
@@ -337,8 +330,8 @@ vector HUD_Panel_CheckResize(vector mySize, vector resizeorigin) {
        vector dist;
        float ratio = mySize.x/mySize.y;
        int i;
-       for (i = 0; i < HUD_PANEL_NUM; ++i) {
-               panel = hud_panel[i];
+       for (i = 0; i < hud_panels_COUNT; ++i) {
+               panel = hud_panels[i];
                if(panel == HUD_PANEL(MAPVOTE)) continue;
                if(panel == highlightedPanel) continue;
                HUD_Panel_UpdatePosSize();
@@ -639,7 +632,7 @@ void HUD_Panel_Arrow_Action(float nPrimary)
 }
 
 void HUD_Panel_EnableMenu();
-entity tab_panels[HUD_PANEL_MAX];
+entity tab_panels[hud_panels_MAX];
 entity tab_panel;
 vector tab_panel_pos;
 float tab_backward;
@@ -647,7 +640,7 @@ void HUD_Panel_FirstInDrawQ(float id);
 void reset_tab_panels()
 {
        int i;
-       for(i = 0; i < HUD_PANEL_NUM; ++i)
+       for(i = 0; i < hud_panels_COUNT; ++i)
                tab_panels[i] = world;
 }
 float HUD_Panel_InputEvent(float bInputType, float nPrimary, float nSecondary)
@@ -788,9 +781,9 @@ float HUD_Panel_InputEvent(float bInputType, float nPrimary, float nSecondary)
                k=0;
                while(++k)
                {
-                       for(i = 0; i < HUD_PANEL_NUM; ++i)
+                       for(i = 0; i < hud_panels_COUNT; ++i)
                        {
-                               panel = hud_panel[i];
+                               panel = hud_panels[i];
                                if(panel == HUD_PANEL(MAPVOTE))
                                        continue;
                                if (panel == tab_panels[i] || panel == starting_panel)
@@ -934,12 +927,12 @@ float HUD_Panel_InputEvent(float bInputType, float nPrimary, float nSecondary)
 float HUD_Panel_Check_Mouse_Pos(float allow_move)
 {
        int i, j = 0;
-       while(j < HUD_PANEL_NUM)
+       while(j < hud_panels_COUNT)
        {
                i = panel_order[j];
                j += 1;
 
-               panel = hud_panel[i];
+               panel = hud_panels[i];
                if(panel == HUD_PANEL(MAPVOTE)) continue;
                HUD_Panel_UpdatePosSize();
 
@@ -980,7 +973,7 @@ void HUD_Panel_FirstInDrawQ(float id)
        int i;
        int place = -1;
        // find out where in the array our current id is, save into place
-       for(i = 0; i < HUD_PANEL_NUM; ++i)
+       for(i = 0; i < hud_panels_COUNT; ++i)
        {
                if(panel_order[i] == id)
                {
@@ -990,7 +983,7 @@ void HUD_Panel_FirstInDrawQ(float id)
        }
        // place last if we didn't find a place for it yet (probably new panel, or screwed up cvar)
        if(place == -1)
-               place = HUD_PANEL_NUM - 1;
+               place = hud_panels_COUNT - 1;
 
        // move all ids up by one step in the array until "place"
        for(i = place; i > 0; --i)
@@ -1002,7 +995,7 @@ void HUD_Panel_FirstInDrawQ(float id)
 
        // let's save them into the cvar by some strcat trickery
        string s = "";
-       for(i = 0; i < HUD_PANEL_NUM; ++i)
+       for(i = 0; i < hud_panels_COUNT; ++i)
        {
                s = strcat(s, ftos(panel_order[i]), " ");
        }
@@ -1016,12 +1009,12 @@ void HUD_Panel_Highlight(float allow_move)
 {
        int i, j = 0;
 
-       while(j < HUD_PANEL_NUM)
+       while(j < hud_panels_COUNT)
        {
                i = panel_order[j];
                j += 1;
 
-               panel = hud_panel[i];
+               panel = hud_panels[i];
                if(panel == HUD_PANEL(MAPVOTE))
                        continue;
                HUD_Panel_UpdatePosSize();
@@ -1031,7 +1024,7 @@ void HUD_Panel_Highlight(float allow_move)
                // move
                if(allow_move && mousepos.x > panel_pos.x && mousepos.y > panel_pos.y && mousepos.x < panel_pos.x + panel_size.x && mousepos.y < panel_pos.y + panel_size.y)
                {
-                       highlightedPanel = hud_panel[i];
+                       highlightedPanel = hud_panels[i];
                        HUD_Panel_FirstInDrawQ(i);
                        highlightedAction = 1;
                        panel_click_distance = mousepos - panel_pos;
@@ -1040,7 +1033,7 @@ void HUD_Panel_Highlight(float allow_move)
                // resize from topleft border
                else if(mousepos.x >= panel_pos.x - border && mousepos.y >= panel_pos.y - border && mousepos.x <= panel_pos.x + 0.5 * panel_size.x && mousepos.y <= panel_pos.y + 0.5 * panel_size.y)
                {
-                       highlightedPanel = hud_panel[i];
+                       highlightedPanel = hud_panels[i];
                        HUD_Panel_FirstInDrawQ(i);
                        highlightedAction = 2;
                        resizeCorner = 1;
@@ -1051,7 +1044,7 @@ void HUD_Panel_Highlight(float allow_move)
                // resize from topright border
                else if(mousepos.x >= panel_pos.x + 0.5 * panel_size.x && mousepos.y >= panel_pos.y - border && mousepos.x <= panel_pos.x + panel_size.x + border && mousepos.y <= panel_pos.y + 0.5 * panel_size.y)
                {
-                       highlightedPanel = hud_panel[i];
+                       highlightedPanel = hud_panels[i];
                        HUD_Panel_FirstInDrawQ(i);
                        highlightedAction = 2;
                        resizeCorner = 2;
@@ -1063,7 +1056,7 @@ void HUD_Panel_Highlight(float allow_move)
                // resize from bottomleft border
                else if(mousepos.x >= panel_pos.x - border && mousepos.y >= panel_pos.y + 0.5 * panel_size.y && mousepos.x <= panel_pos.x + 0.5 * panel_size.x && mousepos.y <= panel_pos.y + panel_size.y + border)
                {
-                       highlightedPanel = hud_panel[i];
+                       highlightedPanel = hud_panels[i];
                        HUD_Panel_FirstInDrawQ(i);
                        highlightedAction = 2;
                        resizeCorner = 3;
@@ -1075,7 +1068,7 @@ void HUD_Panel_Highlight(float allow_move)
                // resize from bottomright border
                else if(mousepos.x >= panel_pos.x + 0.5 * panel_size.x && mousepos.y >= panel_pos.y + 0.5 * panel_size.y && mousepos.x <= panel_pos.x + panel_size.x + border && mousepos.y <= panel_pos.y + panel_size.y + border)
                {
-                       highlightedPanel = hud_panel[i];
+                       highlightedPanel = hud_panels[i];
                        HUD_Panel_FirstInDrawQ(i);
                        highlightedAction = 2;
                        resizeCorner = 4;
@@ -1249,8 +1242,8 @@ void HUD_Configure_Frame()
                        if(autocvar_hud_cursormode)
                                setcursormode(1);
                        hudShiftState = 0;
-                       for(i = HUD_PANEL_NUM - 1; i >= 0; --i)
-                               hud_panel[panel_order[i]].update_time = time;
+                       for(i = hud_panels_COUNT - 1; i >= 0; --i)
+                               hud_panels[panel_order[i]].update_time = time;
                }
 
                // NOTE this check is necessary because _menu_alpha isn't updated the frame the menu gets enabled
index bac199750e11a40c94fa81b5aa704cfb23804007..05792286da30ae888483227e59178f0065fb7c28 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef HUD_CONFIG_H
-#define HUD_CONFIG_H
+#ifndef CLIENT_HUD_CONFIG_H
+#define CLIENT_HUD_CONFIG_H
 
 const int S_MOUSE1 = 1;
 const int S_MOUSE2 = 2;
index 93c4103a9cd993ae2fdc7c45e050bd7e887ce2c3..1c63a0dc2456e30420ce61f8d641fe93e2ff431a 100644 (file)
@@ -1,12 +1,6 @@
 #include "laser.qh"
-#include "_all.qh"
 
-#include "hook.qh"
-
-#include "../common/buffs/all.qh"
-
-#include "../csqcmodellib/cl_model.qh"
-#include "../csqcmodellib/interpolate.qh"
+#include "../lib/csqcmodel/interpolate.qh"
 
 // a laser goes from origin in direction angles
 // it has color 'colormod'
index 86210eee1d4265db7ddbf722db510b6262c367ea..32c6cd81e400174ba00ff225f87a257e9d8cc072 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef LASER_H
-#define LASER_H
+#ifndef CLIENT_LASER_H
+#define CLIENT_LASER_H
 
 void Ent_Laser();
 
index 9dd6538033094b144de0a26e1647a02cd5f3909b..c641bf61e0f5911d78310e943b9922e5a321b972 100644 (file)
@@ -1,5 +1,4 @@
 #include "main.qh"
-#include "_all.qh"
 
 #include "controlpoint.qh"
 #include "damage.qh"
 #include "laser.qh"
 #include "mapvoting.qh"
 #include "modeleffects.qh"
+#include "mutators/events.qh"
 #include "particles.qh"
+#include "quickmenu.qh"
 #include "scoreboard.qh"
 #include "shownames.qh"
 #include "tuba.qh"
 #include "t_items.qh"
 #include "wall.qh"
-
-#include "../common/vehicles/all.qh"
-
-#include "mutators/events.qh"
-
 #include "weapons/projectile.qh"
-
-#include "../common/buffs/all.qh"
 #include "../common/deathtypes/all.qh"
-#include "../common/effects/effects.qh"
+#include "../common/items/all.qh"
 #include "../common/mapinfo.qh"
-#include "../common/monsters/all.qh"
-#include "../common/nades/all.qh"
+#include "../common/minigames/cl_minigames.qh"
+#include "../common/minigames/cl_minigames_hud.qh"
 #include "../common/net_notice.qh"
-#include "../common/notifications.qh"
-#include "../common/stats.qh"
-#include "../common/teams.qh"
-
-#include "../common/items/all.qh"
-
-#include "../common/mutators/base.qh"
-
-#include "../common/weapons/all.qh"
-
-#include "../csqcmodellib/cl_model.qh"
-#include "../csqcmodellib/interpolate.qh"
-
 #include "../common/triggers/include.qh"
-
 #include "../common/turrets/cl_turrets.qh"
-
-#include "../warpzonelib/client.qh"
+#include "../common/vehicles/all.qh"
+#include "../lib/csqcmodel/cl_model.qh"
+#include "../lib/csqcmodel/interpolate.qh"
+#include "../lib/warpzone/client.qh"
 
 // --------------------------------------------------------------------------
 // BEGIN REQUIRED CSQC FUNCTIONS
@@ -148,7 +130,6 @@ void CSQC_Init(void)
 
        // needs to be done so early because of the constants they create
        static_init();
-       CALL_ACCUMULATED_FUNCTION(RegisterHUD_Panels);
 
        // precaches
 
index d403984d38a08bcac4073496dee4e320310ac14e..acd0bcb1ef3651f2c0f7798ae756fcc6e36dd88a 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef MAIN_H
-#define MAIN_H
+#ifndef CLIENT_MAIN_H
+#define CLIENT_MAIN_H
 
 #include "../common/constants.qh"
 
index 945f312ab29a29592806145c248229b94c1fcf92..21bb421a960d3a0a4b8738b32ad9bc6d1ba0df26 100644 (file)
@@ -1,13 +1,9 @@
 #include "mapvoting.qh"
-#include "_all.qh"
 
 #include "hud.qh"
 #include "scoreboard.qh"
 
 #include "../common/mapinfo.qh"
-#include "../common/util.qh"
-
-#include "../dpdefs/keycodes.qh"
 
 
 int mv_num_maps;
index 7a9a511a2be129fb6e292c85e2e24f468bcea786..c1c27ad5b13640cf39fa69e4be6e19c427bbe98b 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef MAPVOTING_H
-#define MAPVOTING_H
+#ifndef CLIENT_MAPVOTING_H
+#define CLIENT_MAPVOTING_H
 
 #include "../common/constants.qh"
 void MapVote_Draw();
index 9bf0a855fa5375e53db412db0f7cae6d89e3efa0..7983e740f1a0862d90a958fa2b64f214653249ef 100644 (file)
@@ -1,14 +1,12 @@
 #include "miscfunctions.qh"
-#include "_all.qh"
 
 #include "hud.qh"
 
 #include "../common/command/generic.qh"
 
 #include "../common/teams.qh"
-#include "../common/util.qh"
 
-#include "../csqcmodellib/cl_model.qh"
+#include "../lib/csqcmodel/cl_model.qh"
 
 
 void AuditLists()
index 9ac46340dd45a40ec01982bd9961d25ac5baec6b..b223d88b9ee1408f755ad627acf9c6aeff6558a6 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef MISCFUNCTIONS_H
-#define MISCFUNCTIONS_H
+#ifndef CLIENT_MISCFUNCTIONS_H
+#define CLIENT_MISCFUNCTIONS_H
 
 entity players;
 entity teams;
index a10062a9f758c21c795824c464b9d2097102eab9..d870d81e98a32d487600821a91bc5bdac553c1ec 100644 (file)
@@ -1,5 +1,4 @@
 #include "modeleffects.qh"
-#include "_all.qh"
 
 .float cnt;
 .float scale;
index d4b98e0a5928c6a87f802bfc07aaa534a97f00cb..32641f394e495812740e3b296510ade106369e0b 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef MODELEFFECTS_H
-#define MODELEFFECTS_H
+#ifndef CLIENT_MODELEFFECTS_H
+#define CLIENT_MODELEFFECTS_H
 
 entityclass(ModelEffect);
 class(ModelEffect) .float frame1time;
index 6d73e24b0bb514f323706a1d75b45610d7fe0a52..0c7f7a39f8284710280807bfce42bcb83b04f8fc 100644 (file)
@@ -1,10 +1,8 @@
 #include "particles.qh"
-#include "_all.qh"
 
 #include "../common/stats.qh"
-#include "../common/util.qh"
 
-#include "../warpzonelib/common.qh"
+#include "../lib/warpzone/common.qh"
 
 void Net_ReadVortexBeamParticle()
 {
index 06cd72523dafe02c7da53b33db59e35837fc2b6c..3735641afa6d7ee03f66957e4b2769d131f57464 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef PARTICLES_H
-#define PARTICLES_H
+#ifndef CLIENT_PARTICLES_H
+#define CLIENT_PARTICLES_H
 .int dphitcontentsmask;
 
 entityclass(PointParticles);
index 584a1978015222c3e4604cec92bb2b2666706e29..d6b2b0d44a72ce7ff878f0bb20aa0340a863a8ec 100644 (file)
@@ -1,8 +1,10 @@
 #include "player_skeleton.qh"
 
-#include "../common/csqcmodel_settings.qh"
+#include "mutators/events.qh"
+#include "../lib/csqcmodel/cl_player.qh"
+#include "../lib/warpzone/anglestransform.qh"
 
-#include "../warpzonelib/anglestransform.qh"
+.vector v_angle;
 
 class(Skeleton) .float skeleton_info_modelindex;
 class(Skeleton) .float skeleton_info_skin;
index 4a37df5e458b4923b3ca6fa298a3c34feb78aa89..48a3111d32210cd12b7d272b65f859137c719966 100644 (file)
@@ -1,7 +1,5 @@
-#ifndef PLAYER_SKELETON
-#define PLAYER_SKELETON
-
-#include "../common/util.qh"
+#ifndef CLIENT_PLAYER_SKELETON
+#define CLIENT_PLAYER_SKELETON
 
 void free_skeleton_from_frames(entity e);
 void skeleton_from_frames(entity e, float is_dead);
index ec19dd5b2d3c3275fcfd0f23fb0b8335bd40c488..0c3884f6797a489efb9b1ddb3f0d5fc4d711993a 100644 (file)
@@ -1,8 +1,5 @@
-#include "../common/util-pre.qh"
-#include "../dpdefs/csprogsdefs.qh"
-#include "../common/util-post.qh"
-
 #include "../lib/_all.inc"
+#include "_all.qh"
 
 #include "announcer.qc"
 #include "bgmscript.qc"
 #include "view.qc"
 #include "wall.qc"
 
-#include "command/all.qc"
+#include "commands/all.qc"
 
 #include "weapons/projectile.qc" // TODO
 
 #include "../common/animdecide.qc"
-#include "../common/effects/effects.qc"
 #include "../common/effects/effectinfo.qc"
 #include "../common/mapinfo.qc"
 #include "../common/movetypes/include.qc"
@@ -53,6 +49,8 @@
 
 #include "../common/buffs/all.qc"
 #include "../common/deathtypes/all.qc"
+#include "../common/effects/all.qc"
+#include "../common/gamemodes/all.qc"
 #include "../common/items/all.qc"
 #include "../common/monsters/all.qc"
 #include "../common/mutators/all.qc"
 
 #include "../common/triggers/include.qc"
 
-#include "../csqcmodellib/cl_model.qc"
-#include "../csqcmodellib/cl_player.qc"
-#include "../csqcmodellib/interpolate.qc"
+#include "../lib/csqcmodel/cl_model.qc"
+#include "../lib/csqcmodel/cl_player.qc"
+#include "../lib/csqcmodel/interpolate.qc"
 
 #include "../server/mutators/mutator_multijump.qc"
 
-#include "../warpzonelib/anglestransform.qc"
-#include "../warpzonelib/client.qc"
-#include "../warpzonelib/common.qc"
-#include "../warpzonelib/util_server.qc"
+#include "../lib/warpzone/anglestransform.qc"
+#include "../lib/warpzone/client.qc"
+#include "../lib/warpzone/common.qc"
+#include "../lib/warpzone/util_server.qc"
 
 #if BUILD_MOD
 #include "../../mod/client/progs.inc"
index 5f896beea56bcafca0b9d35deca04654c4ad71b3..1f7be0c500ca33663a11463d1e96233982b048ed 100644 (file)
@@ -1,8 +1,8 @@
-#include "_all.qh"
+#include "quickmenu.qh"
 
+#include "hud.qh"
 #include "hud_config.qh"
-
-#include "../dpdefs/keycodes.qh"
+#include "mapvoting.qh"
 
 // QUICKMENU_MAXLINES must be <= 10
 const int QUICKMENU_MAXLINES = 10;
diff --git a/qcsrc/client/quickmenu.qh b/qcsrc/client/quickmenu.qh
new file mode 100644 (file)
index 0000000..cf5f666
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef CLIENT_QUICKMENU_H
+#define CLIENT_QUICKMENU_H
+
+bool QuickMenu_InputEvent(float bInputType, float nPrimary, float nSecondary);
+bool QuickMenu_IsOpened();
+void QuickMenu_Mouse();
+
+#endif
index b19406c77e3e0afc9ce1719aa49db9dd8db92295..944116802559089519025d01219e79a9f50cb5be 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef RUBBLE_H
-#define RUBBLE_H
+#ifndef CLIENT_RUBBLE_H
+#define CLIENT_RUBBLE_H
 entityclass(Rubble);
 class(Rubble) .float creationtime;
 void RubbleLimit(string cname, float limit, void() deleteproc);
index a1d9a50dcd5aeb1943a3fc896cd0d46e440e07bc..adbac93c8fed9fd56b28bf2ffb2e25d5baba951b 100644 (file)
@@ -1,6 +1,6 @@
 #include "scoreboard.qh"
-#include "_all.qh"
 
+#include "quickmenu.qh"
 #include "hud.qh"
 
 #include "../common/constants.qh"
@@ -8,7 +8,6 @@
 #include "../common/minigames/cl_minigames.qh"
 #include "../common/stats.qh"
 #include "../common/teams.qh"
-#include "../common/util.qh"
 
 float scoreboard_alpha_bg;
 float scoreboard_alpha_fg;
index e1c5addb49f0474861188f571b5f0520c7a2e181..5b5f812a0ab448e43d058313894e926b45eb4e02 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef SCOREBOARD_H
-#define SCOREBOARD_H
+#ifndef CLIENT_SCOREBOARD_H
+#define CLIENT_SCOREBOARD_H
 
 float xmin, xmax, ymin, ymax, sbwidth;
 
index fc4649537a4c689763d13e7452fe7ff0e4ecb1f4..80a15ad38b49d064c9557a5e994e20afe078991e 100644 (file)
@@ -1,14 +1,12 @@
 #include "shownames.qh"
-#include "_all.qh"
 
 #include "hud.qh"
 
 #include "../common/constants.qh"
 #include "../common/mapinfo.qh"
 #include "../common/teams.qh"
-#include "../common/util.qh"
 
-#include "../csqcmodellib/cl_model.qh"
+#include "../lib/csqcmodel/cl_model.qh"
 
 // self.isactive = player is in range and coordinates/status (health and armor) are up to date
 // self.origin = player origin TODO: should maybe move this so it's the origin of the shownames tag already in SSQC for culling?
index 63fd92e041da6e2505d0d015e2cac576904f2f86..1304c537059f232cc8f82e60018b1f2d469eff3c 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef SHOWNAMES_H
-#define SHOWNAMES_H
+#ifndef CLIENT_SHOWNAMES_H
+#define CLIENT_SHOWNAMES_H
 
 entityclass(ShowNames);
 class(ShowNames) .float healthvalue;
index 4e43a9662469377c2f2c383c47bddb5cf5b6b5ae..f4096b87a6a8fabed875b52faf37a62ca3e2edfc 100644 (file)
@@ -1,10 +1,8 @@
-#include "_all.qh"
 
 #include "../common/buffs/all.qh"
 #include "../common/movetypes/movetypes.qh"
-#include "../common/util.qh"
 #include "../common/weapons/all.qh"
-#include "../csqcmodellib/cl_model.qh"
-#include "../csqcmodellib/common.qh"
+#include "../lib/csqcmodel/cl_model.qh"
+#include "../lib/csqcmodel/common.qh"
 
 #include "../server/t_items.qc"
index 7623e9df86dd8d3ad637e0a9768321a7392c17e1..c866a1b73e4eb1ef6d95a975531b3bab646c5926 100644 (file)
@@ -1,11 +1,10 @@
 #include "teamradar.qh"
-#include "_all.qh"
 
 #include "hud.qh"
 
-#include "../common/util.qh"
+#include "../common/mutators/mutator/waypoints/all.qh"
 
-#include "../csqcmodellib/interpolate.qh"
+#include "../lib/csqcmodel/interpolate.qh"
 
 vector teamradar_3dcoord_to_texcoord(vector in)
 {
index 78ef5ee714e93f17c41841e8716368c1bc370179..b882f39fbdafa7e14e4a5c5c4de18cb57a2f0c23 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef TEAMRADAR_H
-#define TEAMRADAR_H
+#ifndef CLIENT_TEAMRADAR_H
+#define CLIENT_TEAMRADAR_H
 
 const int MAX_TEAMRADAR_TIMES = 32;
 
index 91ccbba5c853e7d1d7367e1da60c0f404cefefca..ed2964936a3bd3942ba90cf1af2921c5d5197fcd 100644 (file)
@@ -1,8 +1,6 @@
 #include "tuba.qh"
-#include "_all.qh"
 
 #include "../common/constants.qh"
-#include "../common/util.qh"
 
 
 #define TUBA_STARTNOTE(i, n) W_Sound(strcat("tuba", (i ? ftos(i) : ""), "_loopnote", ftos(n)))
index 6fe103f70676c62ff4f156e30aadea7a8f4a075f..e936dcd6ec61885fa2ad2748f23048375cfa5d1b 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef TUBA_H
-#define TUBA_H
+#ifndef CLIENT_TUBA_H
+#define CLIENT_TUBA_H
 void Ent_TubaNote(bool isNew);
 void Tuba_Precache();
 
index 381ead7869362d94bc98025544a1af291efccaab..4430c94e28ebe0bf44b3b82abd20393a03c029ab 100644 (file)
@@ -1,4 +1,3 @@
-#include "_all.qh"
 
 #include "announcer.qh"
 #include "hook.qh"
@@ -7,23 +6,28 @@
 #include "mapvoting.qh"
 #include "scoreboard.qh"
 #include "shownames.qh"
+#include "quickmenu.qh"
 
 #include "mutators/events.qh"
 
 #include "../common/constants.qh"
 #include "../common/mapinfo.qh"
+#include "../common/gamemodes/all.qh"
 #include "../common/nades/all.qh"
 #include "../common/stats.qh"
 #include "../common/triggers/target/music.qh"
 #include "../common/teams.qh"
-#include "../common/util.qh"
 
+#include "../common/vehicles/all.qh"
 #include "../common/weapons/all.qh"
+#include "../common/viewloc.qh"
+#include "../common/minigames/cl_minigames.qh"
+#include "../common/minigames/cl_minigames_hud.qh"
 
-#include "../csqcmodellib/cl_player.qh"
+#include "../lib/csqcmodel/cl_player.qh"
 
-#include "../warpzonelib/client.qh"
-#include "../warpzonelib/common.qh"
+#include "../lib/warpzone/client.qh"
+#include "../lib/warpzone/common.qh"
 
 entity porto;
 vector polyline[16];
@@ -1027,7 +1031,6 @@ void CSQC_UpdateView(float w, float h)
        entity e;
        float fov;
        float f;
-       int i;
        vector vf_size, vf_min;
        float a;
 
@@ -1078,8 +1081,7 @@ void CSQC_UpdateView(float w, float h)
        if(myteam != prev_myteam)
        {
                myteamcolors = colormapPaletteColor(myteam, 1);
-               for(i = 0; i < HUD_PANEL_NUM; ++i)
-                       hud_panel[i].update_time = time;
+               FOREACH(hud_panels, true, LAMBDA(it.update_time = time));
                prev_myteam = myteam;
        }
 
index f17b54a5caa7bf0f877593c1cd1a811d148fcb46..9da9bb5b658338fdacca81cbc3e7ef2d7dafd90d 100644 (file)
@@ -1,11 +1,9 @@
 #include "wall.qh"
-#include "_all.qh"
 
 #include "bgmscript.qh"
 
-#include "../common/util.qh"
 
-#include "../csqcmodellib/interpolate.qh"
+#include "../lib/csqcmodel/interpolate.qh"
 
 .float alpha;
 .float scale;
index f44355fc284092de6498b94cbccc2eef03e5deb9..e05bb615edcf8713700d674e46f34be6326578ac 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef WALL_H
-#define WALL_H
+#ifndef CLIENT_WALL_H
+#define CLIENT_WALL_H
 
 entityclass(Wall);
 class(Wall) .float lip;
index 22443043d2ae4b699e0360a466c8c7518dd8c6a8..807d95cb4ca2144cf22a6ccdf0b80bf242cdfe30 100644 (file)
@@ -3,15 +3,15 @@
 #include "../autocvars.qh"
 #include "../defs.qh"
 #include "../main.qh"
+#include "../mutators/events.qh"
 
 #include "../../common/constants.qh"
 #include "../../common/nades/all.qh"
 #include "../../common/movetypes/movetypes.qh"
-#include "../../common/util.qh"
 
-#include "../../csqcmodellib/interpolate.qh"
+#include "../../lib/csqcmodel/interpolate.qh"
 
-#include "../../warpzonelib/anglestransform.qh"
+#include "../../lib/warpzone/anglestransform.qh"
 
 .float alpha;
 .float scale;
index dd289817ec15b034e01d1a3b89ec13cc51227dac..5a0deb4990d20af00bf47f54f265e7f4c562976d 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef PROJECTILE_H
-#define PROJECTILE_H
+#ifndef CLIENT_WEAPONS_PROJECTILE_H
+#define CLIENT_WEAPONS_PROJECTILE_H
 
 entityclass(Projectile);
 class(Projectile) .int traileffect;
index 0db1a6afdfea74ce714a72b538901783bb3e06bb..23f43b9e94a74535614eb5919480d1a2db41236c 100644 (file)
@@ -1,12 +1,9 @@
-#if defined(CSQC)
-       #include "../dpdefs/csprogsdefs.qh"
-       #include "animdecide.qh"
-#elif defined(MENUQC)
-#elif defined(SVQC)
-       #include "../dpdefs/progsdefs.qh"
-    #include "../dpdefs/dpextensions.qh"
+#include "animdecide.qh"
+
+#include "monsters/all.qh"
+
+#if defined(SVQC)
     #include "util.qh"
-    #include "animdecide.qh"
     #include "../server/defs.qh"
 #endif
 
index 190c627ceabdf5da88bd401e5f8b279f327abf45..c6a6f49f02b4b43d0cb8b2f4b18546130d495324 100644 (file)
@@ -1,10 +1,7 @@
 #if defined(CSQC)
-       #include "../../dpdefs/csprogsdefs.qh"
        #include "../../client/defs.qh"
 #elif defined(MENUQC)
 #elif defined(SVQC)
-       #include "../../dpdefs/progsdefs.qh"
-    #include "../../dpdefs/dpextensions.qh"
 #endif
 #include "all.qh"
 
index 69dbb0b1d3af124d6900d59381e6f67919f31036..a8bbe8e856c430a7fdfaf85e9ab5a4988c96a13d 100644 (file)
@@ -1,8 +1,6 @@
 #if defined(CSQC)
 #elif defined(MENUQC)
 #elif defined(SVQC)
-       #include "../dpdefs/progsdefs.qh"
-    #include "../dpdefs/dpextensions.qh"
     #include "util.qh"
     #include "campaign_common.qh"
 #endif
index b822c34942a49eece429b68f32e9e43675b6bcdd..8c20c755c31a33881a6b37933d464b63ab5bb329 100644 (file)
@@ -1,7 +1,6 @@
 #if defined(CSQC)
 #elif defined(MENUQC)
 #elif defined(SVQC)
-       #include "../dpdefs/progsdefs.qh"
     #include "campaign_common.qh"
     #include "mapinfo.qh"
 #endif
index 7eeb5c3233a5e77ea532206c948d7b4630c29e21..756b36d5987ad3debe1b873d951845d6670bc163 100644 (file)
@@ -1,6 +1,23 @@
 #ifndef COMMON_COMMANDS_ALL_H
 #define COMMON_COMMANDS_ALL_H
 
+#include "command.qh"
+REGISTRY(GENERIC_COMMANDS, 50)
+REGISTER_REGISTRY(RegisterGENERIC_COMMANDS)
+REGISTRY_SORT(GENERIC_COMMANDS, m_name, 0)
+
+#define GENERIC_COMMAND(id, description) \
+       CLASS(genericcommand_##id, Command) \
+               ATTRIB(genericcommand_##id, m_name, string, #id); \
+       ATTRIB(genericcommand_##id, m_description, string, description); \
+       ENDCLASS(genericcommand_##id) \
+    REGISTER(RegisterGENERIC_COMMANDS, CMD_G, GENERIC_COMMANDS, id, m_id, NEW(genericcommand_##id)); \
+       METHOD(genericcommand_##id, m_invokecmd, void(int request, int arguments, string command))
+
+STATIC_INIT(GENERIC_COMMANDS_aliases) {
+       FOREACH(GENERIC_COMMANDS, true, LAMBDA(localcmd(sprintf("alias %1$s \"%2$s %1$s ${* ?}\"\n", it.m_name, "qc_cmd_svmenu"))));
+}
+
 #include "generic.qh"
 #include "markup.qh"
 #include "rpn.qh"
index fa310fdfc56ca780ff989965d708ff8c8d7739d3..31909549a68f82d1d39bfc348601961ab1ca8a48 100644 (file)
@@ -1,12 +1,13 @@
 #ifndef COMMAND_H
 #define COMMAND_H
 
-// =========================================================
-//  Shared declarations for all commands, written by Samual
-//  Last updated: December 13th, 2011
-// =========================================================
-
-// identifiers for subfunction requests by the command code structure
 const int CMD_REQUEST_COMMAND = 1;
 const int CMD_REQUEST_USAGE = 2;
+
+CLASS(Command, Object)
+       ATTRIB(Command, m_name, string, string_null);
+       ATTRIB(Command, m_description, string, string_null);
+       METHOD(Command, m_invokecmd, void(int request, int arguments, string command)) { }
+ENDCLASS(Command)
+
 #endif
index 20826f64e21f74853743cd7e757da8a3f4031552..5412c22b4b8436bc07b36ac2c974a98ab29903b4 100644 (file)
@@ -1,5 +1,4 @@
-#include "command.qh"
-#include "generic.qh"
+#include "all.qh"
 
 #include "markup.qh"
 #include "rpn.qh"
@@ -11,7 +10,7 @@
 #endif
 
 #ifdef CSQC
-       #include "../../client/command/cl_cmd.qh"
+       #include "../../client/commands/cl_cmd.qh"
 #endif
 
 #ifdef SVQC
@@ -185,7 +184,7 @@ void GenericCommand_qc_curl(float request, float argc)
        }
 }
 
-void GenericCommand_dumpcommands(float request)
+GENERIC_COMMAND(dumpcommands, "Dump all commands on the program to *_cmd_dump.txt")
 {
        switch(request)
        {
@@ -240,224 +239,6 @@ void GenericCommand_dumpcommands(float request)
        }
 }
 
-#ifndef MENUQC
-void effectinfo_dump(int fh, bool alsoprint);
-#endif
-void GenericCommand_dumpeffectinfo(float request)
-{
-    switch (request) {
-        case CMD_REQUEST_COMMAND: {
-            #ifndef MENUQC
-            string filename = argv(1);
-                       bool alsoprint = false;
-            if (filename == "") {
-                filename = "effectinfo_dump.txt";
-                alsoprint = false;
-            } else if (filename == "-") {
-                filename = "effectinfo_dump.txt";
-                alsoprint = true;
-            }
-            int fh = fopen(filename, FILE_WRITE);
-            if (fh >= 0) {
-               effectinfo_dump(fh, alsoprint);
-                LOG_INFOF("Dumping effectinfo... File located at ^2data/data/%s^7.\n", filename);
-                               LOG_INFOF("Reload with ^2cl_particles_reloadeffects data/%s^7.\n", filename);
-                fclose(fh);
-            } else {
-                LOG_WARNINGF("Could not open file '%s'!\n", filename);
-            }
-            #else
-            LOG_INFO(_("Effectinfo dump command only works with cl_cmd and sv_cmd.\n"));
-            #endif
-            return;
-        }
-        default:
-        case CMD_REQUEST_USAGE: {
-            LOG_INFO(strcat("\nUsage:^3 ", GetProgramCommandPrefix(), " dumpeffectinfo [filename]"));
-            LOG_INFO("  Where 'filename' is the file to write (default is effectinfo_dump.txt),\n");
-            LOG_INFO("  if supplied with '-' output to console as well as default,\n");
-            LOG_INFO("  if left blank, it will only write to default.\n");
-            return;
-        }
-    }
-}
-STATIC_INIT(dumpeffectinfo) { localcmd("alias dumpeffectinfo \"qc_cmd_svcl dumpeffectinfo ${* ?}\"\n"); }
-
-void GenericCommand_dumpitems(float request)
-{
-       switch(request)
-       {
-               case CMD_REQUEST_COMMAND:
-               {
-                       Dump_Items();
-                       return;
-               }
-
-               default:
-               case CMD_REQUEST_USAGE:
-               {
-                       LOG_INFOF("\nUsage:^3 %s dumpitems", GetProgramCommandPrefix());
-                       return;
-               }
-       }
-}
-
-void GenericCommand_dumpnotifs(float request)
-{
-       switch(request)
-       {
-               case CMD_REQUEST_COMMAND:
-               {
-                       #ifndef MENUQC
-                       float fh, alsoprint = false;
-                       string filename = argv(1);
-
-                       if(filename == "")
-                       {
-                               filename = "notifications_dump.cfg";
-                               alsoprint = false;
-                       }
-                       else if(filename == "-")
-                       {
-                               filename = "notifications_dump.cfg";
-                               alsoprint = true;
-                       }
-                       fh = fopen(filename, FILE_WRITE);
-
-                       if(fh >= 0)
-                       {
-                               Dump_Notifications(fh, alsoprint);
-                               LOG_INFOF("Dumping notifications... File located in ^2data/data/%s^7.\n", filename);
-                               fclose(fh);
-                       }
-                       else
-                       {
-                               LOG_INFOF("^1Error: ^7Could not open file '%s'!\n", filename);
-                       }
-                       #else
-                       LOG_INFO(_("Notification dump command only works with cl_cmd and sv_cmd.\n"));
-                       #endif
-                       return;
-               }
-
-               default:
-               case CMD_REQUEST_USAGE:
-               {
-                       LOG_INFO(strcat("\nUsage:^3 ", GetProgramCommandPrefix(), " dumpnotifs [filename]"));
-                       LOG_INFO("  Where 'filename' is the file to write (default is notifications_dump.cfg),\n");
-                       LOG_INFO("  if supplied with '-' output to console as well as default,\n");
-                       LOG_INFO("  if left blank, it will only write to default.\n");
-                       return;
-               }
-       }
-}
-
-void GenericCommand_dumpweapons(float request) // WEAPONTODO: make this work with other progs than just server
-{
-       switch(request)
-       {
-               case CMD_REQUEST_COMMAND:
-               {
-                       #ifdef SVQC
-                       wep_config_file = -1;
-                       wep_config_alsoprint = -1;
-                       string filename = argv(1);
-
-                       if(filename == "")
-                       {
-                               filename = "weapons_dump.cfg";
-                               wep_config_alsoprint = false;
-                       }
-                       else if(filename == "-")
-                       {
-                               filename = "weapons_dump.cfg";
-                               wep_config_alsoprint = true;
-                       }
-                       wep_config_file = fopen(filename, FILE_WRITE);
-
-                       if(wep_config_file >= 0)
-                       {
-                               Dump_Weapon_Settings();
-                               LOG_INFO(sprintf("Dumping weapons... File located in ^2data/data/%s^7.\n", filename));
-                               fclose(wep_config_file);
-                               wep_config_file = -1;
-                               wep_config_alsoprint = -1;
-                       }
-                       else
-                       {
-                               LOG_INFO(sprintf("^1Error: ^7Could not open file '%s'!\n", filename));
-                       }
-                       #else
-                       LOG_INFO(_("Weapons dump command only works with sv_cmd.\n"));
-                       #endif
-                       return;
-               }
-
-               default:
-               case CMD_REQUEST_USAGE:
-               {
-                       LOG_INFO(strcat("\nUsage:^3 ", GetProgramCommandPrefix(), " dumpweapons [filename]"));
-                       LOG_INFO("  Where 'filename' is the file to write (default is weapons_dump.cfg),\n");
-                       LOG_INFO("  if supplied with '-' output to console as well as default,\n");
-                       LOG_INFO("  if left blank, it will only write to default.\n");
-                       return;
-               }
-       }
-}
-
-void GenericCommand_dumpturrets(float request)
-{
-       switch(request)
-       {
-               case CMD_REQUEST_COMMAND:
-               {
-                       #ifdef SVQC
-                       tur_config_file = -1;
-                       tur_config_alsoprint = -1;
-                       string filename = argv(1);
-
-                       if(filename == "")
-                       {
-                               filename = "turrets_dump.cfg";
-                               tur_config_alsoprint = FALSE;
-                       }
-                       else if(filename == "-")
-                       {
-                               filename = "turrets_dump.cfg";
-                               tur_config_alsoprint = TRUE;
-                       }
-                       tur_config_file = fopen(filename, FILE_WRITE);
-
-                       if(tur_config_file >= 0)
-                       {
-                               Dump_Turret_Settings();
-                               LOG_INFO(sprintf("Dumping turrets... File located in ^2data/data/%s^7.\n", filename));
-                               fclose(tur_config_file);
-                               tur_config_file = -1;
-                               tur_config_alsoprint = -1;
-                       }
-                       else
-                       {
-                               LOG_INFO(sprintf("^1Error: ^7Could not open file '%s'!\n", filename));
-                       }
-                       #else
-                       LOG_INFO(_("Turrets dump command only works with sv_cmd.\n"));
-                       #endif
-                       return;
-               }
-
-               default:
-               case CMD_REQUEST_USAGE:
-               {
-                       LOG_INFO(strcat("\nUsage:^3 ", GetProgramCommandPrefix(), " dumpturrets [filename]"));
-                       LOG_INFO("  Where 'filename' is the file to write (default is turrets_dump.cfg),\n");
-                       LOG_INFO("  if supplied with '-' output to console as well as default,\n");
-                       LOG_INFO("  if left blank, it will only write to default.\n");
-                       return;
-               }
-       }
-}
-
 void GenericCommand_maplist(float request, float argc)
 {
        switch(request)
@@ -757,72 +538,46 @@ void GenericCommand_(float request)
 }
 */
 
-// ==================================
-//  Macro system for server commands
-// ==================================
-
 // Do not hard code aliases for these, instead create them in commands.cfg... also: keep in alphabetical order, please ;)
-#define GENERIC_COMMANDS(request,arguments,command) \
-       GENERIC_COMMAND("addtolist", GenericCommand_addtolist(request, arguments), "Add a string to a cvar") \
-       GENERIC_COMMAND("dumpcommands", GenericCommand_dumpcommands(request), "Dump all commands on the program to *_cmd_dump.txt") \
-       GENERIC_COMMAND("dumpeffectinfo", GenericCommand_dumpeffectinfo(request), "Dump all effectinfo to effectinfo_dump.txt") \
-       GENERIC_COMMAND("dumpitems", GenericCommand_dumpitems(request), "Dump all items to the console") \
-       GENERIC_COMMAND("dumpnotifs", GenericCommand_dumpnotifs(request), "Dump all notifications into notifications_dump.txt") \
-       GENERIC_COMMAND("dumpturrets", GenericCommand_dumpturrets(request), "Dump all turrets into turrets_dump.txt") \
-       GENERIC_COMMAND("dumpweapons", GenericCommand_dumpweapons(request), "Dump all weapons into weapons_dump.txt") \
-       GENERIC_COMMAND("maplist", GenericCommand_maplist(request, arguments), "Automatic control of maplist") \
-       GENERIC_COMMAND("nextframe", GenericCommand_nextframe(request, arguments, command), "Execute the given command next frame of this VM") \
-       GENERIC_COMMAND("qc_curl", GenericCommand_qc_curl(request, arguments), "Queries a URL") \
-       GENERIC_COMMAND("removefromlist", GenericCommand_removefromlist(request, arguments), "Remove a string from a cvar") \
-       GENERIC_COMMAND("restartnotifs", GenericCommand_restartnotifs(request), "Re-initialize all notifications") \
-       GENERIC_COMMAND("rpn", GenericCommand_rpn(request, arguments, command), "RPN calculator") \
-       GENERIC_COMMAND("settemp", GenericCommand_settemp(request, arguments), "Temporarily set a value to a cvar which is restored later") \
-       GENERIC_COMMAND("settemp_restore", GenericCommand_settemp_restore(request, arguments), "Restore all cvars set by settemp command") \
-       GENERIC_COMMAND("runtest", GenericCommand_runtest(request, arguments), "Run unit tests") \
-       /* nothing */
+GENERIC_COMMAND(addtolist, "Add a string to a cvar") { GenericCommand_addtolist(request, arguments); }
+GENERIC_COMMAND(maplist, "Automatic control of maplist") { GenericCommand_maplist(request, arguments); }
+GENERIC_COMMAND(nextframe, "Execute the given command next frame of this VM") { GenericCommand_nextframe(request, arguments, command); }
+GENERIC_COMMAND(qc_curl, "Queries a URL") { GenericCommand_qc_curl(request, arguments); }
+GENERIC_COMMAND(removefromlist, "Remove a string from a cvar") { GenericCommand_removefromlist(request, arguments); }
+GENERIC_COMMAND(restartnotifs, "Re-initialize all notifications") { GenericCommand_restartnotifs(request); }
+GENERIC_COMMAND(rpn, "RPN calculator") { GenericCommand_rpn(request, arguments, command); }
+GENERIC_COMMAND(settemp, "Temporarily set a value to a cvar which is restored later") { GenericCommand_settemp(request, arguments); }
+GENERIC_COMMAND(settemp_restore, "Restore all cvars set by settemp command") { GenericCommand_settemp_restore(request, arguments); }
+GENERIC_COMMAND(runtest, "Run unit tests") { GenericCommand_runtest(request, arguments); }
 
 void GenericCommand_macro_help()
 {
-       #define GENERIC_COMMAND(name,function,description) \
-               { LOG_INFO("  ^2", name, "^7: ", description, "\n"); }
-
-       GENERIC_COMMANDS(0, 0, "");
-       #undef GENERIC_COMMAND
-
-       return;
+       FOREACH(GENERIC_COMMANDS, true, LAMBDA(LOG_INFOF("  ^2%s^7: %s\n", it.m_name, it.m_description)));
 }
 
 float GenericCommand_macro_command(float argc, string command)
 {
-       #define GENERIC_COMMAND(name,function,description) \
-               { if(name == strtolower(argv(0))) { function; return true; } }
-
-       GENERIC_COMMANDS(CMD_REQUEST_COMMAND, argc, command);
-       #undef GENERIC_COMMAND
-
+       string c = strtolower(argv(0));
+       FOREACH(GENERIC_COMMANDS, it.m_name == c, LAMBDA(
+               it.m_invokecmd(CMD_REQUEST_COMMAND, argc, command);
+               return true;
+       ));
        return false;
 }
 
 float GenericCommand_macro_usage(float argc)
 {
-       #define GENERIC_COMMAND(name,function,description) \
-               { if(name == strtolower(argv(1))) { function; return true; } }
-
-       GENERIC_COMMANDS(CMD_REQUEST_USAGE, argc, "");
-       #undef GENERIC_COMMAND
-
+       string c = strtolower(argv(1));
+       FOREACH(GENERIC_COMMANDS, it.m_name == c, LAMBDA(
+               it.m_invokecmd(CMD_REQUEST_USAGE, argc, "");
+               return true;
+       ));
        return false;
 }
 
 void GenericCommand_macro_write_aliases(float fh)
 {
-       #define GENERIC_COMMAND(name,function,description) \
-               { CMD_Write_Alias("qc_cmd_svmenu", name, description); }
-
-       GENERIC_COMMANDS(0, 0, "");
-       #undef GENERIC_COMMAND
-
-       return;
+       FOREACH(GENERIC_COMMANDS, true, LAMBDA(CMD_Write_Alias("qc_cmd_svmenu", it.m_name, it.m_description)));
 }
 
 
diff --git a/qcsrc/common/effects/all.inc b/qcsrc/common/effects/all.inc
new file mode 100644 (file)
index 0000000..d53ded9
--- /dev/null
@@ -0,0 +1,295 @@
+// Global list of effects, networked to CSQC by ID to save bandwidth and to use client particle numbers (allows mismatching effectinfos to some degree)
+// Not too concerned about the order of this list, just keep the weapon effects together!
+
+#include "../teams.qh"
+
+// EFFECT(istrail, EFFECT_NAME,     "effectinfo_string")
+EFFECT(0, EXPLOSION_SMALL,          "explosion_small")
+EFFECT(0, EXPLOSION_MEDIUM,         "explosion_medium")
+EFFECT(0, EXPLOSION_BIG,            "explosion_big")
+
+EFFECT(0, SMOKE_SMALL,              "smoke_small")
+EFFECT(0, SMOKE_LARGE,              "smoke_large")
+
+
+
+EFFECT(0, BLASTER_IMPACT,           "laser_impact")
+EFFECT(0, BLASTER_MUZZLEFLASH,      "laser_muzzleflash")
+
+EFFECT(0, SHOTGUN_IMPACT,           "shotgun_impact")
+EFFECT(0, SHOTGUN_MUZZLEFLASH,      "shotgun_muzzleflash")
+
+EFFECT(0, ARC_BEAM,                 "arc_beam")
+EFFECT(0, ARC_BEAM_HEAL,            "arc_beam_heal")
+EFFECT(0, ARC_BEAM_HEAL_IMPACT,     "arc_beam_healimpact")
+EFFECT(0, ARC_BEAM_HEAL_IMPACT2,    "healray_impact")
+EFFECT(0, ARC_LIGHTNING,            "arc_lightning")
+EFFECT(0, ARC_LIGHTNING2,           "electro_lightning")
+
+EFFECT(0, MACHINEGUN_IMPACT,        "machinegun_impact")
+EFFECT(0, MACHINEGUN_MUZZLEFLASH,   "uzi_muzzleflash")
+
+EFFECT(0, GRENADE_EXPLODE,          "grenade_explode")
+EFFECT(0, GRENADE_MUZZLEFLASH,      "grenadelauncher_muzzleflash")
+
+EFFECT(0, ELECTRO_BALLEXPLODE,      "electro_ballexplode")
+EFFECT(0, ELECTRO_COMBO,            "electro_combo")
+EFFECT(0, ELECTRO_IMPACT,           "electro_impact")
+EFFECT(0, ELECTRO_MUZZLEFLASH,      "electro_muzzleflash")
+
+EFFECT(0, CRYLINK_IMPACT,           "crylink_impactbig")
+EFFECT(0, CRYLINK_IMPACT2,          "crylink_impact")
+EFFECT(0, CRYLINK_JOINEXPLODE,      "crylink_joinexplode")
+EFFECT(0, CRYLINK_MUZZLEFLASH,      "crylink_muzzleflash")
+
+EFFECT(0, VORTEX_BEAM,              "nex_beam")
+EFFECT(0, VORTEX_BEAM_OLD,          "TE_TEI_G3")
+EFFECT(0, VORTEX_IMPACT,            "nex_impact")
+EFFECT(0, VORTEX_MUZZLEFLASH,       "nex_muzzleflash")
+
+EFFECT(1, VAPORIZER_RED,            "TE_TEI_G3RED")
+EFFECT(1, VAPORIZER_HIT_RED,        "TE_TEI_G3RED_HIT")
+EFFECT(1, VAPORIZER_BLUE,           "TE_TEI_G3BLUE")
+EFFECT(1, VAPORIZER_HIT_BLUE,       "TE_TEI_G3BLUE_HIT")
+EFFECT(1, VAPORIZER_YELLOW,         "TE_TEI_G3YELLOW")
+EFFECT(1, VAPORIZER_HIT_YELLOW,     "TE_TEI_G3YELLOW_HIT")
+EFFECT(1, VAPORIZER_PINK,           "TE_TEI_G3PINK")
+EFFECT(1, VAPORIZER_HIT_PINK,       "TE_TEI_G3PINK_HIT")
+EFFECT(1, VAPORIZER_NEUTRAL,        "TE_TEI_G3")
+EFFECT(1, VAPORIZER_HIT_NEUTRAL,    "TE_TEI_G3_HIT")
+entity EFFECT_VAPORIZER(int teamid)
+{
+    switch (teamid) {
+        case NUM_TEAM_1:    return EFFECT_VAPORIZER_RED;
+        case NUM_TEAM_2:    return EFFECT_VAPORIZER_BLUE;
+        case NUM_TEAM_3:    return EFFECT_VAPORIZER_YELLOW;
+        case NUM_TEAM_4:    return EFFECT_VAPORIZER_PINK;
+        default:            return EFFECT_VAPORIZER_NEUTRAL;
+    }
+}
+entity EFFECT_VAPORIZER_HIT(int teamid)
+{
+    switch (teamid) {
+        case NUM_TEAM_1:    return EFFECT_VAPORIZER_HIT_RED;
+        case NUM_TEAM_2:    return EFFECT_VAPORIZER_HIT_BLUE;
+        case NUM_TEAM_3:    return EFFECT_VAPORIZER_HIT_YELLOW;
+        case NUM_TEAM_4:    return EFFECT_VAPORIZER_HIT_PINK;
+        default:            return EFFECT_VAPORIZER_HIT_NEUTRAL;
+    }
+}
+
+EFFECT(0, RIFLE_IMPACT,             "machinegun_impact")
+EFFECT(0, RIFLE_MUZZLEFLASH,        "rifle_muzzleflash")
+EFFECT(1, RIFLE,                    "tr_rifle")
+EFFECT(1, RIFLE_WEAK,               "tr_rifle_weak")
+
+EFFECT(0, HAGAR_BOUNCE,             "hagar_bounce")
+EFFECT(0, HAGAR_EXPLODE,            "hagar_explode")
+EFFECT(0, HAGAR_MUZZLEFLASH,        "hagar_muzzleflash")
+EFFECT(1, HAGAR_ROCKET,             "tr_hagar")
+
+EFFECT(0, ROCKET_EXPLODE,           "rocket_explode")
+EFFECT(0, ROCKET_GUIDE,             "rocket_guide")
+EFFECT(0, ROCKET_MUZZLEFLASH,       "rocketlauncher_muzzleflash")
+
+EFFECT(0, HOOK_EXPLODE,             "hookbomb_explode")
+EFFECT(0, HOOK_IMPACT,              "grapple_impact")
+EFFECT(0, HOOK_MUZZLEFLASH,         "grapple_muzzleflash")
+
+EFFECT(0, SEEKER_MUZZLEFLASH,       "seeker_muzzleflash")
+
+EFFECT(0, FLAK_BOUNCE,              "flak_bounce")
+
+EFFECT(1, FIREBALL,                 "fireball")
+EFFECT(0, FIREBALL_BFGDAMAGE,       "fireball_bfgdamage")
+EFFECT(0, FIREBALL_EXPLODE,         "fireball_explode")
+EFFECT(0, FIREBALL_LASER,           "fireball_laser")
+EFFECT(0, FIREBALL_MUZZLEFLASH,     "fireball_muzzleflash")
+EFFECT(0, FIREBALL_PRE_MUZZLEFLASH, "fireball_preattack_muzzleflash")
+
+
+
+EFFECT(0, RAPTOR_CANNON_IMPACT,     "raptor_cannon_impact")
+EFFECT(0, RAPTOR_BOMB_IMPACT,       "raptor_bomb_impact")
+EFFECT(0, RAPTOR_BOMB_SPREAD,       "raptor_bomb_spread")
+EFFECT(0, RAPTOR_MUZZLEFLASH,       "raptor_cannon_muzzleflash")
+
+EFFECT(0, RACER_BOOSTER,            "wakizashi_booster_smoke")
+EFFECT(0, RACER_IMPACT,             "wakizashi_gun_impact")
+EFFECT(0, RACER_MUZZLEFLASH,        "wakizashi_gun_muzzleflash")
+EFFECT(0, RACER_ROCKETLAUNCH,       "wakizashi_rocket_launch")
+EFFECT(0, RACER_ROCKET_EXPLODE,     "wakizashi_rocket_launch")
+EFFECT(1, RACER_ROCKET_TRAIL,       "wakizashi_rocket_thrust")
+
+EFFECT(0, SPIDERBOT_ROCKETLAUNCH,           "spiderbot_rocket_launch")
+EFFECT(1, SPIDERBOT_ROCKET_TRAIL,           "spiderbot_rocket_thrust")
+EFFECT(0, SPIDERBOT_ROCKET_EXPLODE,         "spiderbot_rocket_explode")
+EFFECT(0, SPIDERBOT_MINIGUN_IMPACT,         "spiderbot_minigun_impact")
+EFFECT(0, SPIDERBOT_MINIGUN_MUZZLEFLASH,    "spiderbot_minigun_muzzleflash")
+
+EFFECT(0, BUMBLEBEE_HEAL_MUZZLEFLASH,   "healray_muzzleflash")
+EFFECT(0, BUMBLEBEE_HEAL_IMPACT,        "healray_impact")
+
+EFFECT(0, BIGPLASMA_IMPACT,         "bigplasma_impact")
+EFFECT(0, BIGPLASMA_MUZZLEFLASH,    "bigplasma_muzzleflash")
+
+EFFECT(0, TELEPORT,                 "teleport")
+
+EFFECT(0, SPAWNPOINT_RED,           "spawn_point_red")
+EFFECT(0, SPAWN_RED,                "spawn_event_red")
+EFFECT(0, SPAWNPOINT_BLUE,          "spawn_point_blue")
+EFFECT(0, SPAWN_BLUE,               "spawn_event_blue")
+EFFECT(0, SPAWNPOINT_YELLOW,        "spawn_point_yellow")
+EFFECT(0, SPAWN_YELLOW,             "spawn_event_yellow")
+EFFECT(0, SPAWNPOINT_PINK,          "spawn_point_pink")
+EFFECT(0, SPAWN_PINK,               "spawn_event_pink")
+EFFECT(0, SPAWNPOINT_NEUTRAL,       "spawn_point_neutral")
+EFFECT(0, SPAWN_NEUTRAL,            "spawn_event_neutral")
+
+EFFECT(0, NADE_EXPLODE_RED,         "nade_red_explode")
+EFFECT(0, NADE_EXPLODE_BLUE,        "nade_blue_explode")
+EFFECT(0, NADE_EXPLODE_YELLOW,      "nade_yellow_explode")
+EFFECT(0, NADE_EXPLODE_PINK,        "nade_pink_explode")
+EFFECT(0, NADE_EXPLODE_NEUTRAL,     "nade_neutral_explode")
+entity EFFECT_NADE_EXPLODE(int teamid)
+{
+    switch (teamid) {
+        case NUM_TEAM_1:    return EFFECT_NADE_EXPLODE_RED;
+        case NUM_TEAM_2:    return EFFECT_NADE_EXPLODE_BLUE;
+        case NUM_TEAM_3:    return EFFECT_NADE_EXPLODE_YELLOW;
+        case NUM_TEAM_4:    return EFFECT_NADE_EXPLODE_PINK;
+        default:                   return EFFECT_NADE_EXPLODE_NEUTRAL;
+    }
+}
+
+EFFECT(1, NADE_TRAIL_RED,           "nade_red")
+EFFECT(1, NADE_TRAIL_BLUE,          "nade_blue")
+EFFECT(1, NADE_TRAIL_YELLOW,        "nade_yellow")
+EFFECT(1, NADE_TRAIL_PINK,          "nade_pink")
+EFFECT(1, NADE_TRAIL_NEUTRAL,       "nade_neutral")
+entity EFFECT_NADE_TRAIL(int teamid)
+{
+    switch (teamid) {
+        case NUM_TEAM_1:    return EFFECT_NADE_TRAIL_RED;
+        case NUM_TEAM_2:    return EFFECT_NADE_TRAIL_BLUE;
+        case NUM_TEAM_3:    return EFFECT_NADE_TRAIL_YELLOW;
+        case NUM_TEAM_4:    return EFFECT_NADE_TRAIL_PINK;
+        default:            return EFFECT_NADE_TRAIL_NEUTRAL;
+    }
+}
+
+EFFECT(1, NADE_TRAIL_BURN_RED,      "nade_red_burn")
+EFFECT(1, NADE_TRAIL_BURN_BLUE,     "nade_blue_burn")
+EFFECT(1, NADE_TRAIL_BURN_YELLOW,   "nade_yellow_burn")
+EFFECT(1, NADE_TRAIL_BURN_PINK,     "nade_pink_burn")
+EFFECT(1, NADE_TRAIL_BURN_NEUTRAL,  "nade_neutral_burn")
+entity EFFECT_NADE_TRAIL_BURN(int teamid)
+{
+    switch (teamid) {
+        case NUM_TEAM_1:    return EFFECT_NADE_TRAIL_BURN_RED;
+        case NUM_TEAM_2:    return EFFECT_NADE_TRAIL_BURN_BLUE;
+        case NUM_TEAM_3:    return EFFECT_NADE_TRAIL_BURN_YELLOW;
+        case NUM_TEAM_4:    return EFFECT_NADE_TRAIL_BURN_PINK;
+        default:            return EFFECT_NADE_TRAIL_BURN_NEUTRAL;
+    }
+}
+
+EFFECT(0, ICEORGLASS,               "iceorglass")
+EFFECT(0, ICEFIELD,                 "icefield")
+EFFECT(0, FIREFIELD,                "firefield")
+EFFECT(0, HEALING,                  "healing_fx")
+EFFECT(1, LASER_BEAM_FAST,          "nex242_misc_laser_beam_fast")
+EFFECT(0, RESPAWN_GHOST,            "respawn_ghost")
+
+EFFECT(0, FLAG_TOUCH_RED,           "redflag_touch")
+EFFECT(0, FLAG_TOUCH_BLUE,          "blueflag_touch")
+EFFECT(0, FLAG_TOUCH_YELLOW,        "yellowflag_touch")
+EFFECT(0, FLAG_TOUCH_PINK,          "pinkflag_touch")
+EFFECT(0, FLAG_TOUCH_NEUTRAL,       "neutralflag_touch")
+entity EFFECT_FLAG_TOUCH(int teamid)
+{
+    switch (teamid) {
+        case NUM_TEAM_1:    return EFFECT_FLAG_TOUCH_RED;
+        case NUM_TEAM_2:    return EFFECT_FLAG_TOUCH_BLUE;
+        case NUM_TEAM_3:    return EFFECT_FLAG_TOUCH_YELLOW;
+        case NUM_TEAM_4:    return EFFECT_FLAG_TOUCH_PINK;
+        default:            return EFFECT_FLAG_TOUCH_NEUTRAL;
+    }
+}
+
+EFFECT(1, PASS_RED,                 "red_pass")
+EFFECT(1, PASS_BLUE,                "blue_pass")
+EFFECT(1, PASS_YELLOW,              "yellow_pass")
+EFFECT(1, PASS_PINK,                "pink_pass")
+EFFECT(1, PASS_NEUTRAL,             "neutral_pass")
+
+EFFECT(0, CAP_RED,                  "red_cap")
+EFFECT(0, CAP_BLUE,                 "blue_cap")
+EFFECT(0, CAP_YELLOW,               "yellow_cap")
+EFFECT(0, CAP_PINK,                 "pink_cap")
+EFFECT(0, CAP_NEUTRAL,              "neutral_cap")
+entity EFFECT_CAP(int teamid)
+{
+    switch (teamid) {
+        case NUM_TEAM_1:    return EFFECT_CAP_RED;
+        case NUM_TEAM_2:    return EFFECT_CAP_BLUE;
+        case NUM_TEAM_3:    return EFFECT_CAP_YELLOW;
+        case NUM_TEAM_4:    return EFFECT_CAP_PINK;
+        default:            return EFFECT_CAP_NEUTRAL;
+    }
+}
+
+EFFECT(0, ITEM_PICKUP,              "item_pickup")
+EFFECT(0, ITEM_RESPAWN,             "item_respawn")
+
+EFFECT(0, ONS_GENERATOR_DAMAGED,    "torch_small")
+EFFECT(0, ONS_GENERATOR_GIB,        "onslaught_generator_gib_explode")
+EFFECT(0, ONS_GENERATOR_EXPLODE,    "onslaught_generator_smallexplosion")
+EFFECT(0, ONS_GENERATOR_EXPLODE2,   "onslaught_generator_finalexplosion")
+
+
+
+EFFECT(0, LASER_DEADLY,             "laser_deadly")
+EFFECT(1, FLAC_TRAIL,               "TR_SEEKER")
+EFFECT(1, SEEKER_TRAIL,             "TR_SEEKER")
+EFFECT(1, FIREMINE,                 "firemine")
+EFFECT(0, BALL_SPARKS,              "kaball_sparks")
+EFFECT(0, ELECTRIC_SPARKS,          "electricity_sparks")
+EFFECT(0, SPARKS,                   "sparks")
+EFFECT(0, RAGE,                     "rage")
+EFFECT(0, SMOKING,                  "smoking")
+EFFECT(0, SMOKE_RING,               "smoke_ring")
+EFFECT(0, JUMPPAD,                  "jumppad_activate")
+EFFECT(1, BULLET,                   "tr_bullet")
+EFFECT(0, EF_FLAME,                 "EF_FLAME")
+EFFECT(0, EF_STARDUST,              "EF_STARDUST")
+EFFECT(0, TE_EXPLOSION,             "TE_EXPLOSION")
+EFFECT(1, TR_NEXUIZPLASMA,          "TR_NEXUIZPLASMA")
+EFFECT(1, TR_CRYLINKPLASMA,         "TR_CRYLINKPLASMA")
+EFFECT(1, TR_ROCKET,                "TR_ROCKET")
+EFFECT(1, TR_GRENADE,               "TR_GRENADE")
+EFFECT(1, TR_BLOOD,                 "TR_BLOOD")
+EFFECT(1, TR_WIZSPIKE,              "TR_WIZSPIKE")
+EFFECT(1, TR_SLIGHTBLOOD,           "TR_SLIGHTBLOOD")
+EFFECT(1, TR_KNIGHTSPIKE,           "TR_KNIGHTSPIKE")
+EFFECT(1, TR_VORESPIKE,             "TR_VORESPIKE")
+EFFECT(0, TE_SPARK,                 "TE_SPARK")
+
+EFFECT(1, ROCKETMINSTA_LASER_RED,       "rocketminsta_laser_red")
+EFFECT(1, ROCKETMINSTA_LASER_BLUE,      "rocketminsta_laser_blue")
+EFFECT(1, ROCKETMINSTA_LASER_YELLOW,    "rocketminsta_laser_yellow")
+EFFECT(1, ROCKETMINSTA_LASER_PINK,      "rocketminsta_laser_pink")
+EFFECT(1, ROCKETMINSTA_LASER_NEUTRAL,   "rocketminsta_laser_neutral")
+entity EFFECT_ROCKETMINSTA_LASER(int teamid)
+{
+    entity e;
+    switch (teamid) {
+        case NUM_TEAM_1:    e = EFFECT_ROCKETMINSTA_LASER_RED; break;
+        case NUM_TEAM_2:    e = EFFECT_ROCKETMINSTA_LASER_BLUE; break;
+        case NUM_TEAM_3:    e = EFFECT_ROCKETMINSTA_LASER_YELLOW; break;
+        case NUM_TEAM_4:    e = EFFECT_ROCKETMINSTA_LASER_PINK; break;
+        default:            e = EFFECT_ROCKETMINSTA_LASER_NEUTRAL; break;
+    }
+    if (particleeffectnum(e) < 0 || Team_TeamToNumber(teamid) == -1) { e = EFFECT_TR_NEXUIZPLASMA; }
+    return e;
+}
diff --git a/qcsrc/common/effects/all.qc b/qcsrc/common/effects/all.qc
new file mode 100644 (file)
index 0000000..e90f3c6
--- /dev/null
@@ -0,0 +1,93 @@
+#include "all.qh"
+
+#ifdef CSQC
+void Read_Effect(bool is_new)
+{
+       int net_name = (Effects_COUNT >= 255) ? ReadShort() : ReadByte();
+
+       entity eff = Effects[net_name];
+
+       vector v, vel = '0 0 0';
+       int eff_cnt = 1;
+       bool eff_trail = eff.eent_eff_trail;
+       v_x = ReadCoord();
+       v_y = ReadCoord();
+       v_z = ReadCoord();
+
+       bool use_vel = ReadByte();
+       if(use_vel)
+       {
+               vel_x = ReadCoord();
+               vel_y = ReadCoord();
+               vel_z = ReadCoord();
+       }
+
+       if(!eff_trail)
+               eff_cnt = ReadByte();
+
+       if(is_new)
+       {
+               if(eff_trail)
+                       WarpZone_TrailParticles(world, particleeffectnum(eff), v, vel);
+               else
+                       pointparticles(particleeffectnum(eff), v, vel, eff_cnt);
+       }
+}
+#endif
+
+#ifdef SVQC
+bool Net_Write_Effect(entity this, entity client, int sf)
+{
+       WriteByte(MSG_ENTITY, ENT_CLIENT_EFFECT);
+       (Effects_COUNT >= 255)
+       ? WriteShort(MSG_ENTITY, self.m_id)
+       : WriteByte(MSG_ENTITY, self.m_id);
+       WriteCoord(MSG_ENTITY, self.eent_net_location_x);
+       WriteCoord(MSG_ENTITY, self.eent_net_location_y);
+       WriteCoord(MSG_ENTITY, self.eent_net_location_z);
+
+       // attempt to save a tiny bit more bandwidth by not sending velocity if it isn't set
+       if(self.eent_net_velocity)
+       {
+               WriteByte(MSG_ENTITY, true);
+               WriteCoord(MSG_ENTITY, self.eent_net_velocity_x);
+               WriteCoord(MSG_ENTITY, self.eent_net_velocity_y);
+               WriteCoord(MSG_ENTITY, self.eent_net_velocity_z);
+       }
+       else { WriteByte(MSG_ENTITY, false); }
+
+       if(!self.eent_eff_trail) { WriteByte(MSG_ENTITY, self.eent_net_count); }
+       return true;
+}
+
+void Send_Effect(entity eff, vector eff_loc, vector eff_vel, int eff_cnt)
+{
+       if(!eff) { return; }
+       if(!eff.eent_eff_trail && !eff_cnt) { return; } // effect has no count!
+       entity net_eff = spawn();
+       net_eff.owner = eff;
+       net_eff.classname = "net_effect";
+       //net_eff.eent_broadcast = broadcast;
+       net_eff.m_id = eff.m_id;
+       net_eff.eent_net_velocity = eff_vel;
+       net_eff.eent_net_location = eff_loc;
+       net_eff.eent_net_count = eff_cnt;
+       net_eff.eent_eff_trail = eff.eent_eff_trail;
+
+       net_eff.think = SUB_Remove;
+       net_eff.nextthink = time + 0.2; // don't need to keep this long
+
+       Net_LinkEntity(net_eff, false, 0, Net_Write_Effect);
+}
+
+void Send_Effect_(string eff_name, vector eff_loc, vector eff_vel, int eff_cnt)
+{
+       // problem with this is, we might not have all the available effects for it
+       FOREACH(Effects, it.eent_eff_name == eff_name, LAMBDA(
+               Send_Effect(it, eff_loc, eff_vel, eff_cnt);
+               return;
+       ));
+       // revert to engine handling
+       pointparticles(_particleeffectnum(eff_name), eff_loc, eff_vel, eff_cnt);
+}
+#endif
diff --git a/qcsrc/common/effects/all.qh b/qcsrc/common/effects/all.qh
new file mode 100644 (file)
index 0000000..7046af1
--- /dev/null
@@ -0,0 +1,41 @@
+#ifndef EFFECTS_ALL_H
+#define EFFECTS_ALL_H
+
+#include "effect.qh"
+
+#ifdef CSQC
+void Read_Effect(bool is_new);
+#elif defined(SVQC)
+void Send_Effect(entity eff, vector eff_loc, vector eff_vel, int eff_cnt);
+void Send_Effect_(string eff_name, vector eff_loc, vector eff_vel, int eff_cnt);
+#endif
+
+REGISTRY(Effects, BIT(8))
+REGISTER_REGISTRY(RegisterEffects)
+#define EFFECT(istrail, name, realname) \
+    REGISTER(RegisterEffects, EFFECT, Effects, name, m_id, Create_Effect_Entity(realname, istrail));
+
+void RegisterEffects_First()
+{
+    #ifdef SVQC
+    #define dedi (server_is_dedicated ? "a dedicated " : "")
+    #else
+    #define dedi ""
+    #endif
+
+    LOG_TRACEF("Beginning effect initialization on %s%s program...\n", dedi, PROGNAME);
+    #undef dedi
+}
+
+void RegisterEffects_Done()
+{
+    LOG_TRACE("Effects initialization successful!\n");
+}
+
+// NOW we actually activate the declarations
+ACCUMULATE_FUNCTION(RegisterEffects, RegisterEffects_First)
+EFFECT(0, Null, string_null)
+#include "all.inc"
+ACCUMULATE_FUNCTION(RegisterEffects, RegisterEffects_Done)
+
+#endif
diff --git a/qcsrc/common/effects/effect.qh b/qcsrc/common/effects/effect.qh
new file mode 100644 (file)
index 0000000..bd9cd99
--- /dev/null
@@ -0,0 +1,22 @@
+#ifndef EFFECT_H
+#define EFFECT_H
+
+#define particleeffectnum(e) _particleeffectnum(e.eent_eff_name)
+
+.int m_id;
+.string eent_eff_name;
+.int eent_eff_trail;
+
+.vector eent_net_location;
+.vector eent_net_velocity;
+.int eent_net_count;
+
+entity Create_Effect_Entity(string eff_name, bool eff_trail)
+{
+       entity this = new(effect_entity);
+       this.eent_eff_name = eff_name;
+       this.eent_eff_trail = eff_trail;
+       return this;
+}
+
+#endif
index 731903b6353e7413c3d51db8970138fea9ee734d..deff4dc1563ba74d61d0ba3f7abf912a1d3466d1 100644 (file)
@@ -283,6 +283,41 @@ void effectinfo_dump(int fh, bool alsoprint)
     #undef WRITE
 }
 
+GENERIC_COMMAND(dumpeffectinfo, "Dump all effectinfo to effectinfo_dump.txt")
+{
+    switch (request) {
+        case CMD_REQUEST_COMMAND: {
+            string filename = argv(1);
+                       bool alsoprint = false;
+            if (filename == "") {
+                filename = "effectinfo_dump.txt";
+                alsoprint = false;
+            } else if (filename == "-") {
+                filename = "effectinfo_dump.txt";
+                alsoprint = true;
+            }
+            int fh = fopen(filename, FILE_WRITE);
+            if (fh >= 0) {
+               effectinfo_dump(fh, alsoprint);
+                LOG_INFOF("Dumping effectinfo... File located at ^2data/data/%s^7.\n", filename);
+                               LOG_INFOF("Reload with ^2cl_particles_reloadeffects data/%s^7.\n", filename);
+                fclose(fh);
+            } else {
+                LOG_WARNINGF("Could not open file '%s'!\n", filename);
+            }
+            return;
+        }
+        default:
+        case CMD_REQUEST_USAGE: {
+            LOG_INFO(strcat("\nUsage:^3 ", GetProgramCommandPrefix(), " dumpeffectinfo [filename]"));
+            LOG_INFO("  Where 'filename' is the file to write (default is effectinfo_dump.txt),\n");
+            LOG_INFO("  if supplied with '-' output to console as well as default,\n");
+            LOG_INFO("  if left blank, it will only write to default.\n");
+            return;
+        }
+    }
+}
+
 
 REGISTRY(EffectInfos, BIT(9))
 REGISTER_REGISTRY(RegisterEffectInfos)
diff --git a/qcsrc/common/effects/effects.inc b/qcsrc/common/effects/effects.inc
deleted file mode 100644 (file)
index 4d82087..0000000
+++ /dev/null
@@ -1,293 +0,0 @@
-// Global list of effects, networked to CSQC by ID to save bandwidth and to use client particle numbers (allows mismatching effectinfos to some degree)
-// Not too concerned about the order of this list, just keep the weapon effects together!
-
-// EFFECT(istrail, EFFECT_NAME,     "effectinfo_string")
-EFFECT(0, EXPLOSION_SMALL,          "explosion_small")
-EFFECT(0, EXPLOSION_MEDIUM,         "explosion_medium")
-EFFECT(0, EXPLOSION_BIG,            "explosion_big")
-
-EFFECT(0, SMOKE_SMALL,              "smoke_small")
-EFFECT(0, SMOKE_LARGE,              "smoke_large")
-
-
-
-EFFECT(0, BLASTER_IMPACT,           "laser_impact")
-EFFECT(0, BLASTER_MUZZLEFLASH,      "laser_muzzleflash")
-
-EFFECT(0, SHOTGUN_IMPACT,           "shotgun_impact")
-EFFECT(0, SHOTGUN_MUZZLEFLASH,      "shotgun_muzzleflash")
-
-EFFECT(0, ARC_BEAM,                 "arc_beam")
-EFFECT(0, ARC_BEAM_HEAL,            "arc_beam_heal")
-EFFECT(0, ARC_BEAM_HEAL_IMPACT,     "arc_beam_healimpact")
-EFFECT(0, ARC_BEAM_HEAL_IMPACT2,    "healray_impact")
-EFFECT(0, ARC_LIGHTNING,            "arc_lightning")
-EFFECT(0, ARC_LIGHTNING2,           "electro_lightning")
-
-EFFECT(0, MACHINEGUN_IMPACT,        "machinegun_impact")
-EFFECT(0, MACHINEGUN_MUZZLEFLASH,   "uzi_muzzleflash")
-
-EFFECT(0, GRENADE_EXPLODE,          "grenade_explode")
-EFFECT(0, GRENADE_MUZZLEFLASH,      "grenadelauncher_muzzleflash")
-
-EFFECT(0, ELECTRO_BALLEXPLODE,      "electro_ballexplode")
-EFFECT(0, ELECTRO_COMBO,            "electro_combo")
-EFFECT(0, ELECTRO_IMPACT,           "electro_impact")
-EFFECT(0, ELECTRO_MUZZLEFLASH,      "electro_muzzleflash")
-
-EFFECT(0, CRYLINK_IMPACT,           "crylink_impactbig")
-EFFECT(0, CRYLINK_IMPACT2,          "crylink_impact")
-EFFECT(0, CRYLINK_JOINEXPLODE,      "crylink_joinexplode")
-EFFECT(0, CRYLINK_MUZZLEFLASH,      "crylink_muzzleflash")
-
-EFFECT(0, VORTEX_BEAM,              "nex_beam")
-EFFECT(0, VORTEX_BEAM_OLD,          "TE_TEI_G3")
-EFFECT(0, VORTEX_IMPACT,            "nex_impact")
-EFFECT(0, VORTEX_MUZZLEFLASH,       "nex_muzzleflash")
-
-EFFECT(1, VAPORIZER_RED,            "TE_TEI_G3RED")
-EFFECT(1, VAPORIZER_HIT_RED,        "TE_TEI_G3RED_HIT")
-EFFECT(1, VAPORIZER_BLUE,           "TE_TEI_G3BLUE")
-EFFECT(1, VAPORIZER_HIT_BLUE,       "TE_TEI_G3BLUE_HIT")
-EFFECT(1, VAPORIZER_YELLOW,         "TE_TEI_G3YELLOW")
-EFFECT(1, VAPORIZER_HIT_YELLOW,     "TE_TEI_G3YELLOW_HIT")
-EFFECT(1, VAPORIZER_PINK,           "TE_TEI_G3PINK")
-EFFECT(1, VAPORIZER_HIT_PINK,       "TE_TEI_G3PINK_HIT")
-EFFECT(1, VAPORIZER_NEUTRAL,        "TE_TEI_G3")
-EFFECT(1, VAPORIZER_HIT_NEUTRAL,    "TE_TEI_G3_HIT")
-entity EFFECT_VAPORIZER(int teamid)
-{
-    switch (teamid) {
-        case NUM_TEAM_1:    return EFFECT_VAPORIZER_RED;
-        case NUM_TEAM_2:    return EFFECT_VAPORIZER_BLUE;
-        case NUM_TEAM_3:    return EFFECT_VAPORIZER_YELLOW;
-        case NUM_TEAM_4:    return EFFECT_VAPORIZER_PINK;
-        default:            return EFFECT_VAPORIZER_NEUTRAL;
-    }
-}
-entity EFFECT_VAPORIZER_HIT(int teamid)
-{
-    switch (teamid) {
-        case NUM_TEAM_1:    return EFFECT_VAPORIZER_HIT_RED;
-        case NUM_TEAM_2:    return EFFECT_VAPORIZER_HIT_BLUE;
-        case NUM_TEAM_3:    return EFFECT_VAPORIZER_HIT_YELLOW;
-        case NUM_TEAM_4:    return EFFECT_VAPORIZER_HIT_PINK;
-        default:            return EFFECT_VAPORIZER_HIT_NEUTRAL;
-    }
-}
-
-EFFECT(0, RIFLE_IMPACT,             "machinegun_impact")
-EFFECT(0, RIFLE_MUZZLEFLASH,        "rifle_muzzleflash")
-EFFECT(1, RIFLE,                    "tr_rifle")
-EFFECT(1, RIFLE_WEAK,               "tr_rifle_weak")
-
-EFFECT(0, HAGAR_BOUNCE,             "hagar_bounce")
-EFFECT(0, HAGAR_EXPLODE,            "hagar_explode")
-EFFECT(0, HAGAR_MUZZLEFLASH,        "hagar_muzzleflash")
-EFFECT(1, HAGAR_ROCKET,             "tr_hagar")
-
-EFFECT(0, ROCKET_EXPLODE,           "rocket_explode")
-EFFECT(0, ROCKET_GUIDE,             "rocket_guide")
-EFFECT(0, ROCKET_MUZZLEFLASH,       "rocketlauncher_muzzleflash")
-
-EFFECT(0, HOOK_EXPLODE,             "hookbomb_explode")
-EFFECT(0, HOOK_IMPACT,              "grapple_impact")
-EFFECT(0, HOOK_MUZZLEFLASH,         "grapple_muzzleflash")
-
-EFFECT(0, SEEKER_MUZZLEFLASH,       "seeker_muzzleflash")
-
-EFFECT(0, FLAK_BOUNCE,              "flak_bounce")
-
-EFFECT(1, FIREBALL,                 "fireball")
-EFFECT(0, FIREBALL_BFGDAMAGE,       "fireball_bfgdamage")
-EFFECT(0, FIREBALL_EXPLODE,         "fireball_explode")
-EFFECT(0, FIREBALL_LASER,           "fireball_laser")
-EFFECT(0, FIREBALL_MUZZLEFLASH,     "fireball_muzzleflash")
-EFFECT(0, FIREBALL_PRE_MUZZLEFLASH, "fireball_preattack_muzzleflash")
-
-
-
-EFFECT(0, RAPTOR_CANNON_IMPACT,     "raptor_cannon_impact")
-EFFECT(0, RAPTOR_BOMB_IMPACT,       "raptor_bomb_impact")
-EFFECT(0, RAPTOR_BOMB_SPREAD,       "raptor_bomb_spread")
-EFFECT(0, RAPTOR_MUZZLEFLASH,       "raptor_cannon_muzzleflash")
-
-EFFECT(0, RACER_BOOSTER,            "wakizashi_booster_smoke")
-EFFECT(0, RACER_IMPACT,             "wakizashi_gun_impact")
-EFFECT(0, RACER_MUZZLEFLASH,        "wakizashi_gun_muzzleflash")
-EFFECT(0, RACER_ROCKETLAUNCH,       "wakizashi_rocket_launch")
-EFFECT(0, RACER_ROCKET_EXPLODE,     "wakizashi_rocket_launch")
-EFFECT(1, RACER_ROCKET_TRAIL,       "wakizashi_rocket_thrust")
-
-EFFECT(0, SPIDERBOT_ROCKETLAUNCH,           "spiderbot_rocket_launch")
-EFFECT(1, SPIDERBOT_ROCKET_TRAIL,           "spiderbot_rocket_thrust")
-EFFECT(0, SPIDERBOT_ROCKET_EXPLODE,         "spiderbot_rocket_explode")
-EFFECT(0, SPIDERBOT_MINIGUN_IMPACT,         "spiderbot_minigun_impact")
-EFFECT(0, SPIDERBOT_MINIGUN_MUZZLEFLASH,    "spiderbot_minigun_muzzleflash")
-
-EFFECT(0, BUMBLEBEE_HEAL_MUZZLEFLASH,   "healray_muzzleflash")
-EFFECT(0, BUMBLEBEE_HEAL_IMPACT,        "healray_impact")
-
-EFFECT(0, BIGPLASMA_IMPACT,         "bigplasma_impact")
-EFFECT(0, BIGPLASMA_MUZZLEFLASH,    "bigplasma_muzzleflash")
-
-EFFECT(0, TELEPORT,                 "teleport")
-
-EFFECT(0, SPAWNPOINT_RED,           "spawn_point_red")
-EFFECT(0, SPAWN_RED,                "spawn_event_red")
-EFFECT(0, SPAWNPOINT_BLUE,          "spawn_point_blue")
-EFFECT(0, SPAWN_BLUE,               "spawn_event_blue")
-EFFECT(0, SPAWNPOINT_YELLOW,        "spawn_point_yellow")
-EFFECT(0, SPAWN_YELLOW,             "spawn_event_yellow")
-EFFECT(0, SPAWNPOINT_PINK,          "spawn_point_pink")
-EFFECT(0, SPAWN_PINK,               "spawn_event_pink")
-EFFECT(0, SPAWNPOINT_NEUTRAL,       "spawn_point_neutral")
-EFFECT(0, SPAWN_NEUTRAL,            "spawn_event_neutral")
-
-EFFECT(0, NADE_EXPLODE_RED,         "nade_red_explode")
-EFFECT(0, NADE_EXPLODE_BLUE,        "nade_blue_explode")
-EFFECT(0, NADE_EXPLODE_YELLOW,      "nade_yellow_explode")
-EFFECT(0, NADE_EXPLODE_PINK,        "nade_pink_explode")
-EFFECT(0, NADE_EXPLODE_NEUTRAL,     "nade_neutral_explode")
-entity EFFECT_NADE_EXPLODE(int teamid)
-{
-    switch (teamid) {
-        case NUM_TEAM_1:    return EFFECT_NADE_EXPLODE_RED;
-        case NUM_TEAM_2:    return EFFECT_NADE_EXPLODE_BLUE;
-        case NUM_TEAM_3:    return EFFECT_NADE_EXPLODE_YELLOW;
-        case NUM_TEAM_4:    return EFFECT_NADE_EXPLODE_PINK;
-        default:                   return EFFECT_NADE_EXPLODE_NEUTRAL;
-    }
-}
-
-EFFECT(1, NADE_TRAIL_RED,           "nade_red")
-EFFECT(1, NADE_TRAIL_BLUE,          "nade_blue")
-EFFECT(1, NADE_TRAIL_YELLOW,        "nade_yellow")
-EFFECT(1, NADE_TRAIL_PINK,          "nade_pink")
-EFFECT(1, NADE_TRAIL_NEUTRAL,       "nade_neutral")
-entity EFFECT_NADE_TRAIL(int teamid)
-{
-    switch (teamid) {
-        case NUM_TEAM_1:    return EFFECT_NADE_TRAIL_RED;
-        case NUM_TEAM_2:    return EFFECT_NADE_TRAIL_BLUE;
-        case NUM_TEAM_3:    return EFFECT_NADE_TRAIL_YELLOW;
-        case NUM_TEAM_4:    return EFFECT_NADE_TRAIL_PINK;
-        default:            return EFFECT_NADE_TRAIL_NEUTRAL;
-    }
-}
-
-EFFECT(1, NADE_TRAIL_BURN_RED,      "nade_red_burn")
-EFFECT(1, NADE_TRAIL_BURN_BLUE,     "nade_blue_burn")
-EFFECT(1, NADE_TRAIL_BURN_YELLOW,   "nade_yellow_burn")
-EFFECT(1, NADE_TRAIL_BURN_PINK,     "nade_pink_burn")
-EFFECT(1, NADE_TRAIL_BURN_NEUTRAL,  "nade_neutral_burn")
-entity EFFECT_NADE_TRAIL_BURN(int teamid)
-{
-    switch (teamid) {
-        case NUM_TEAM_1:    return EFFECT_NADE_TRAIL_BURN_RED;
-        case NUM_TEAM_2:    return EFFECT_NADE_TRAIL_BURN_BLUE;
-        case NUM_TEAM_3:    return EFFECT_NADE_TRAIL_BURN_YELLOW;
-        case NUM_TEAM_4:    return EFFECT_NADE_TRAIL_BURN_PINK;
-        default:            return EFFECT_NADE_TRAIL_BURN_NEUTRAL;
-    }
-}
-
-EFFECT(0, ICEORGLASS,               "iceorglass")
-EFFECT(0, ICEFIELD,                 "icefield")
-EFFECT(0, FIREFIELD,                "firefield")
-EFFECT(0, HEALING,                  "healing_fx")
-EFFECT(1, LASER_BEAM_FAST,          "nex242_misc_laser_beam_fast")
-EFFECT(0, RESPAWN_GHOST,            "respawn_ghost")
-
-EFFECT(0, FLAG_TOUCH_RED,           "redflag_touch")
-EFFECT(0, FLAG_TOUCH_BLUE,          "blueflag_touch")
-EFFECT(0, FLAG_TOUCH_YELLOW,        "yellowflag_touch")
-EFFECT(0, FLAG_TOUCH_PINK,          "pinkflag_touch")
-EFFECT(0, FLAG_TOUCH_NEUTRAL,       "neutralflag_touch")
-entity EFFECT_FLAG_TOUCH(int teamid)
-{
-    switch (teamid) {
-        case NUM_TEAM_1:    return EFFECT_FLAG_TOUCH_RED;
-        case NUM_TEAM_2:    return EFFECT_FLAG_TOUCH_BLUE;
-        case NUM_TEAM_3:    return EFFECT_FLAG_TOUCH_YELLOW;
-        case NUM_TEAM_4:    return EFFECT_FLAG_TOUCH_PINK;
-        default:            return EFFECT_FLAG_TOUCH_NEUTRAL;
-    }
-}
-
-EFFECT(1, PASS_RED,                 "red_pass")
-EFFECT(1, PASS_BLUE,                "blue_pass")
-EFFECT(1, PASS_YELLOW,              "yellow_pass")
-EFFECT(1, PASS_PINK,                "pink_pass")
-EFFECT(1, PASS_NEUTRAL,             "neutral_pass")
-
-EFFECT(0, CAP_RED,                  "red_cap")
-EFFECT(0, CAP_BLUE,                 "blue_cap")
-EFFECT(0, CAP_YELLOW,               "yellow_cap")
-EFFECT(0, CAP_PINK,                 "pink_cap")
-EFFECT(0, CAP_NEUTRAL,              "neutral_cap")
-entity EFFECT_CAP(int teamid)
-{
-    switch (teamid) {
-        case NUM_TEAM_1:    return EFFECT_CAP_RED;
-        case NUM_TEAM_2:    return EFFECT_CAP_BLUE;
-        case NUM_TEAM_3:    return EFFECT_CAP_YELLOW;
-        case NUM_TEAM_4:    return EFFECT_CAP_PINK;
-        default:            return EFFECT_CAP_NEUTRAL;
-    }
-}
-
-EFFECT(0, ITEM_PICKUP,              "item_pickup")
-EFFECT(0, ITEM_RESPAWN,             "item_respawn")
-
-EFFECT(0, ONS_GENERATOR_DAMAGED,    "torch_small")
-EFFECT(0, ONS_GENERATOR_GIB,        "onslaught_generator_gib_explode")
-EFFECT(0, ONS_GENERATOR_EXPLODE,    "onslaught_generator_smallexplosion")
-EFFECT(0, ONS_GENERATOR_EXPLODE2,   "onslaught_generator_finalexplosion")
-
-
-
-EFFECT(0, LASER_DEADLY,             "laser_deadly")
-EFFECT(1, FLAC_TRAIL,               "TR_SEEKER")
-EFFECT(1, SEEKER_TRAIL,             "TR_SEEKER")
-EFFECT(1, FIREMINE,                 "firemine")
-EFFECT(0, BALL_SPARKS,              "kaball_sparks")
-EFFECT(0, ELECTRIC_SPARKS,          "electricity_sparks")
-EFFECT(0, SPARKS,                   "sparks")
-EFFECT(0, RAGE,                     "rage")
-EFFECT(0, SMOKING,                  "smoking")
-EFFECT(0, SMOKE_RING,               "smoke_ring")
-EFFECT(0, JUMPPAD,                  "jumppad_activate")
-EFFECT(1, BULLET,                   "tr_bullet")
-EFFECT(0, EF_FLAME,                 "EF_FLAME")
-EFFECT(0, EF_STARDUST,              "EF_STARDUST")
-EFFECT(0, TE_EXPLOSION,             "TE_EXPLOSION")
-EFFECT(1, TR_NEXUIZPLASMA,          "TR_NEXUIZPLASMA")
-EFFECT(1, TR_CRYLINKPLASMA,         "TR_CRYLINKPLASMA")
-EFFECT(1, TR_ROCKET,                "TR_ROCKET")
-EFFECT(1, TR_GRENADE,               "TR_GRENADE")
-EFFECT(1, TR_BLOOD,                 "TR_BLOOD")
-EFFECT(1, TR_WIZSPIKE,              "TR_WIZSPIKE")
-EFFECT(1, TR_SLIGHTBLOOD,           "TR_SLIGHTBLOOD")
-EFFECT(1, TR_KNIGHTSPIKE,           "TR_KNIGHTSPIKE")
-EFFECT(1, TR_VORESPIKE,             "TR_VORESPIKE")
-EFFECT(0, TE_SPARK,                 "TE_SPARK")
-
-EFFECT(1, ROCKETMINSTA_LASER_RED,       "rocketminsta_laser_red")
-EFFECT(1, ROCKETMINSTA_LASER_BLUE,      "rocketminsta_laser_blue")
-EFFECT(1, ROCKETMINSTA_LASER_YELLOW,    "rocketminsta_laser_yellow")
-EFFECT(1, ROCKETMINSTA_LASER_PINK,      "rocketminsta_laser_pink")
-EFFECT(1, ROCKETMINSTA_LASER_NEUTRAL,   "rocketminsta_laser_neutral")
-entity EFFECT_ROCKETMINSTA_LASER(int teamid)
-{
-    entity e;
-    switch (teamid) {
-        case NUM_TEAM_1:    e = EFFECT_ROCKETMINSTA_LASER_RED; break;
-        case NUM_TEAM_2:    e = EFFECT_ROCKETMINSTA_LASER_BLUE; break;
-        case NUM_TEAM_3:    e = EFFECT_ROCKETMINSTA_LASER_YELLOW; break;
-        case NUM_TEAM_4:    e = EFFECT_ROCKETMINSTA_LASER_PINK; break;
-        default:            e = EFFECT_ROCKETMINSTA_LASER_NEUTRAL; break;
-    }
-    if (particleeffectnum(e) < 0 || Team_TeamToNumber(teamid) == -1) { e = EFFECT_TR_NEXUIZPLASMA; }
-    return e;
-}
diff --git a/qcsrc/common/effects/effects.qc b/qcsrc/common/effects/effects.qc
deleted file mode 100644 (file)
index 78bb675..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-#ifdef CSQC
-void Read_Effect(bool is_new)
-{
-       int net_name = (Effects_COUNT >= 255) ? ReadShort() : ReadByte();
-
-       entity eff = Effects[net_name];
-
-       vector v, vel = '0 0 0';
-       int eff_cnt = 1;
-       bool eff_trail = eff.eent_eff_trail;
-       v_x = ReadCoord();
-       v_y = ReadCoord();
-       v_z = ReadCoord();
-
-       bool use_vel = ReadByte();
-       if(use_vel)
-       {
-               vel_x = ReadCoord();
-               vel_y = ReadCoord();
-               vel_z = ReadCoord();
-       }
-
-       if(!eff_trail)
-               eff_cnt = ReadByte();
-
-       if(is_new)
-       {
-               if(eff_trail)
-                       WarpZone_TrailParticles(world, particleeffectnum(eff), v, vel);
-               else
-                       pointparticles(particleeffectnum(eff), v, vel, eff_cnt);
-       }
-}
-#endif
-
-#ifdef SVQC
-bool Net_Write_Effect(entity this, entity client, int sf)
-{
-       WriteByte(MSG_ENTITY, ENT_CLIENT_EFFECT);
-       (Effects_COUNT >= 255)
-       ? WriteShort(MSG_ENTITY, self.m_id)
-       : WriteByte(MSG_ENTITY, self.m_id);
-       WriteCoord(MSG_ENTITY, self.eent_net_location_x);
-       WriteCoord(MSG_ENTITY, self.eent_net_location_y);
-       WriteCoord(MSG_ENTITY, self.eent_net_location_z);
-
-       // attempt to save a tiny bit more bandwidth by not sending velocity if it isn't set
-       if(self.eent_net_velocity)
-       {
-               WriteByte(MSG_ENTITY, true);
-               WriteCoord(MSG_ENTITY, self.eent_net_velocity_x);
-               WriteCoord(MSG_ENTITY, self.eent_net_velocity_y);
-               WriteCoord(MSG_ENTITY, self.eent_net_velocity_z);
-       }
-       else { WriteByte(MSG_ENTITY, false); }
-
-       if(!self.eent_eff_trail) { WriteByte(MSG_ENTITY, self.eent_net_count); }
-       return true;
-}
-
-void Send_Effect(entity eff, vector eff_loc, vector eff_vel, int eff_cnt)
-{
-       if(!eff) { return; }
-       if(!eff.eent_eff_trail && !eff_cnt) { return; } // effect has no count!
-       entity net_eff = spawn();
-       net_eff.owner = eff;
-       net_eff.classname = "net_effect";
-       //net_eff.eent_broadcast = broadcast;
-       net_eff.m_id = eff.m_id;
-       net_eff.eent_net_velocity = eff_vel;
-       net_eff.eent_net_location = eff_loc;
-       net_eff.eent_net_count = eff_cnt;
-       net_eff.eent_eff_trail = eff.eent_eff_trail;
-
-       net_eff.think = SUB_Remove;
-       net_eff.nextthink = time + 0.2; // don't need to keep this long
-
-       Net_LinkEntity(net_eff, false, 0, Net_Write_Effect);
-}
-
-void Send_Effect_(string eff_name, vector eff_loc, vector eff_vel, int eff_cnt)
-{
-       // problem with this is, we might not have all the available effects for it
-       FOREACH(Effects, it.eent_eff_name == eff_name, LAMBDA(
-               Send_Effect(it, eff_loc, eff_vel, eff_cnt);
-               return;
-       ));
-       // revert to engine handling
-       pointparticles(_particleeffectnum(eff_name), eff_loc, eff_vel, eff_cnt);
-}
-#endif
diff --git a/qcsrc/common/effects/effects.qh b/qcsrc/common/effects/effects.qh
deleted file mode 100644 (file)
index 2182175..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-#ifndef P_EFFECTS_H
-#define P_EFFECTS_H
-
-#ifdef CSQC
-void Read_Effect(bool is_new);
-#elif defined(SVQC)
-void Send_Effect(entity eff, vector eff_loc, vector eff_vel, int eff_cnt);
-void Send_Effect_(string eff_name, vector eff_loc, vector eff_vel, int eff_cnt);
-#endif
-
-#define particleeffectnum(e) _particleeffectnum(e.eent_eff_name)
-
-REGISTRY(Effects, BIT(8))
-REGISTER_REGISTRY(RegisterEffects)
-#define EFFECT(istrail, name, realname) \
-    REGISTER(RegisterEffects, EFFECT, Effects, name, m_id, Create_Effect_Entity(realname, istrail));
-
-.int m_id;
-.string eent_eff_name;
-.int eent_eff_trail;
-
-.vector eent_net_location;
-.vector eent_net_velocity;
-.int eent_net_count;
-
-entity Create_Effect_Entity(string eff_name, bool eff_trail)
-{
-       entity this = new(effect_entity);
-       this.eent_eff_name = eff_name;
-       this.eent_eff_trail = eff_trail;
-       return this;
-}
-
-void RegisterEffects_First()
-{
-    #ifdef SVQC
-    #define dedi (server_is_dedicated ? "a dedicated " : "")
-    #else
-    #define dedi ""
-    #endif
-
-    LOG_TRACEF("Beginning effect initialization on %s%s program...\n", dedi, PROGNAME);
-    #undef dedi
-}
-
-void RegisterEffects_Done()
-{
-    LOG_TRACE("Effects initialization successful!\n");
-}
-
-// NOW we actually activate the declarations
-ACCUMULATE_FUNCTION(RegisterEffects, RegisterEffects_First)
-EFFECT(0, Null, string_null)
-#include "effects.inc"
-ACCUMULATE_FUNCTION(RegisterEffects, RegisterEffects_Done)
-
-#endif
diff --git a/qcsrc/common/gamemodes/all.inc b/qcsrc/common/gamemodes/all.inc
new file mode 100644 (file)
index 0000000..4c24beb
--- /dev/null
@@ -0,0 +1 @@
+#include "gamemode/nexball/nexball.qc"
diff --git a/qcsrc/common/gamemodes/all.qc b/qcsrc/common/gamemodes/all.qc
new file mode 100644 (file)
index 0000000..f0fc719
--- /dev/null
@@ -0,0 +1,5 @@
+#include "all.qh"
+
+#define IMPLEMENTATION
+#include "all.inc"
+#undef IMPLEMENTATION
diff --git a/qcsrc/common/gamemodes/all.qh b/qcsrc/common/gamemodes/all.qh
new file mode 100644 (file)
index 0000000..62ba616
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef GAMEMODES_ALL_H
+#define GAMEMODES_ALL_H
+
+#include "all.inc"
+
+#endif
diff --git a/qcsrc/common/gamemodes/gamemode/nexball/nexball.qc b/qcsrc/common/gamemodes/gamemode/nexball/nexball.qc
new file mode 100644 (file)
index 0000000..7958d66
--- /dev/null
@@ -0,0 +1,1051 @@
+#include "nexball.qh"
+
+#ifdef IMPLEMENTATION
+#ifdef SVQC
+float autocvar_g_nexball_basketball_bouncefactor;
+float autocvar_g_nexball_basketball_bouncestop;
+float autocvar_g_nexball_basketball_carrier_highspeed;
+bool autocvar_g_nexball_basketball_meter;
+float autocvar_g_nexball_basketball_meter_maxpower;
+float autocvar_g_nexball_basketball_meter_minpower;
+float autocvar_g_nexball_delay_collect;
+float autocvar_g_nexball_delay_goal;
+float autocvar_g_nexball_delay_start;
+float autocvar_g_nexball_football_bouncefactor;
+float autocvar_g_nexball_football_bouncestop;
+bool autocvar_g_nexball_radar_showallplayers;
+bool autocvar_g_nexball_sound_bounce;
+int autocvar_g_nexball_trail_color;
+
+float autocvar_g_nexball_safepass_turnrate;
+float autocvar_g_nexball_safepass_maxdist;
+float autocvar_g_nexball_safepass_holdtime;
+float autocvar_g_nexball_viewmodel_scale;
+float autocvar_g_nexball_tackling;
+vector autocvar_g_nexball_viewmodel_offset;
+
+void basketball_touch();
+void football_touch();
+void ResetBall();
+const int NBM_NONE = 0;
+const int NBM_FOOTBALL = 2;
+const int NBM_BASKETBALL = 4;
+float nexball_mode;
+
+float OtherTeam(float t)  //works only if there are two teams on the map!
+{
+       entity e;
+       e = find(world, classname, "nexball_team");
+       if(e.team == t)
+               e = find(e, classname, "nexball_team");
+       return e.team;
+}
+
+const float ST_NEXBALL_GOALS = 1;
+const float SP_NEXBALL_GOALS = 4;
+const float SP_NEXBALL_FAULTS = 5;
+void nb_ScoreRules(float teams)
+{
+       ScoreRules_basics(teams, 0, 0, true);
+       ScoreInfo_SetLabel_TeamScore(   ST_NEXBALL_GOALS,  "goals", SFL_SORT_PRIO_PRIMARY);
+       ScoreInfo_SetLabel_PlayerScore( SP_NEXBALL_GOALS,  "goals", SFL_SORT_PRIO_PRIMARY);
+       ScoreInfo_SetLabel_PlayerScore(SP_NEXBALL_FAULTS, "faults", SFL_SORT_PRIO_SECONDARY | SFL_LOWER_IS_BETTER);
+       ScoreRules_basics_end();
+}
+
+void LogNB(string mode, entity actor)
+{
+       string s;
+       if(!autocvar_sv_eventlog)
+               return;
+       s = strcat(":nexball:", mode);
+       if(actor != world)
+               s = strcat(s, ":", ftos(actor.playerid));
+       GameLogEcho(s);
+}
+
+void ball_restart(void)
+{SELFPARAM();
+       if(self.owner)
+               DropBall(self, self.owner.origin, '0 0 0');
+       ResetBall();
+}
+
+void nexball_setstatus(void)
+{SELFPARAM();
+       self.items &= ~IT_KEY1;
+       if(self.ballcarried)
+       {
+               if(self.ballcarried.teamtime && (self.ballcarried.teamtime < time))
+               {
+                       bprint("The ", Team_ColoredFullName(self.team), " held the ball for too long.\n");
+                       setself(self.ballcarried);
+                       DropBall(self, self.owner.origin, '0 0 0');
+                       ResetBall();
+                       setself(this);
+               }
+               else
+                       self.items |= IT_KEY1;
+       }
+}
+
+void relocate_nexball(void)
+{SELFPARAM();
+       tracebox(self.origin, BALL_MINS, BALL_MAXS, self.origin, true, self);
+       if(trace_startsolid)
+       {
+               vector o;
+               o = self.origin;
+               if(!move_out_of_solid(self))
+                       objerror("could not get out of solid at all!");
+               LOG_INFO("^1NOTE: this map needs FIXING. ", self.classname, " at ", vtos(o - '0 0 1'));
+               LOG_INFO(" needs to be moved out of solid, e.g. by '", ftos(self.origin.x - o.x));
+               LOG_INFO(" ", ftos(self.origin.y - o.y));
+               LOG_INFO(" ", ftos(self.origin.z - o.z), "'\n");
+               self.origin = o;
+       }
+}
+
+void DropOwner(void)
+{SELFPARAM();
+       entity ownr;
+       ownr = self.owner;
+       DropBall(self, ownr.origin, ownr.velocity);
+       makevectors(ownr.v_angle.y * '0 1 0');
+       ownr.velocity += ('0 0 0.75' - v_forward) * 1000;
+       ownr.flags &= ~FL_ONGROUND;
+}
+
+void GiveBall(entity plyr, entity ball)
+{SELFPARAM();
+       entity ownr;
+
+       if((ownr = ball.owner))
+       {
+               ownr.effects &= ~autocvar_g_nexball_basketball_effects_default;
+               ownr.ballcarried = world;
+               if(ownr.metertime)
+               {
+                       ownr.metertime = 0;
+                       ownr.weaponentity.state = WS_READY;
+               }
+               WaypointSprite_Kill(ownr.waypointsprite_attachedforcarrier);
+       }
+       else
+       {
+               WaypointSprite_Kill(ball.waypointsprite_attachedforcarrier);
+       }
+
+       //setattachment(ball, plyr, "");
+       setorigin(ball, plyr.origin + plyr.view_ofs);
+
+       if(ball.team != plyr.team)
+               ball.teamtime = time + autocvar_g_nexball_basketball_delay_hold_forteam;
+
+       ball.owner = ball.pusher = plyr; //"owner" is set to the player carrying, "pusher" to the last player who touched it
+       ball.team = plyr.team;
+       plyr.ballcarried = ball;
+       ball.nb_dropper = plyr;
+
+       plyr.effects |= autocvar_g_nexball_basketball_effects_default;
+       ball.effects &= ~autocvar_g_nexball_basketball_effects_default;
+
+       ball.velocity = '0 0 0';
+       ball.movetype = MOVETYPE_NONE;
+       ball.touch = func_null;
+       ball.effects |= EF_NOSHADOW;
+       ball.scale = 1; // scale down.
+
+       WaypointSprite_AttachCarrier(WP_NbBall, plyr, RADARICON_FLAGCARRIER);
+       WaypointSprite_UpdateRule(plyr.waypointsprite_attachedforcarrier, 0, SPRITERULE_DEFAULT);
+
+       if(autocvar_g_nexball_basketball_delay_hold)
+       {
+               ball.think = DropOwner;
+               ball.nextthink = time + autocvar_g_nexball_basketball_delay_hold;
+       }
+
+       plyr.weaponentity.weapons = plyr.weapons;
+       plyr.weaponentity.switchweapon = plyr.weapon;
+       plyr.weapons = WEPSET(NEXBALL);
+       setself(plyr);
+       Weapon w = WEP_NEXBALL;
+       w.wr_resetplayer(w);
+       plyr.switchweapon = WEP_NEXBALL.m_id;
+       W_SwitchWeapon(WEP_NEXBALL.m_id);
+       setself(this);
+}
+
+void DropBall(entity ball, vector org, vector vel)
+{
+       ball.effects |= autocvar_g_nexball_basketball_effects_default;
+       ball.effects &= ~EF_NOSHADOW;
+       ball.owner.effects &= ~autocvar_g_nexball_basketball_effects_default;
+
+       setattachment(ball, world, "");
+       setorigin(ball, org);
+       ball.movetype = MOVETYPE_BOUNCE;
+       ball.flags &= ~FL_ONGROUND;
+       ball.scale = ball_scale;
+       ball.velocity = vel;
+       ball.nb_droptime = time;
+       ball.touch = basketball_touch;
+       ball.think = ResetBall;
+       ball.nextthink = min(time + autocvar_g_nexball_delay_idle, ball.teamtime);
+
+       if(ball.owner.metertime)
+       {
+               ball.owner.metertime = 0;
+               ball.owner.weaponentity.state = WS_READY;
+       }
+
+       WaypointSprite_Kill(ball.owner.waypointsprite_attachedforcarrier);
+       WaypointSprite_Spawn(WP_NbBall, 0, 0, ball, '0 0 64', world, ball.team, ball, waypointsprite_attachedforcarrier, false, RADARICON_FLAGCARRIER); // no health bar please
+       WaypointSprite_UpdateRule(ball.waypointsprite_attachedforcarrier, 0, SPRITERULE_DEFAULT);
+
+       ball.owner.ballcarried = world;
+       ball.owner = world;
+}
+
+void InitBall(void)
+{SELFPARAM();
+       if(gameover) return;
+       self.flags &= ~FL_ONGROUND;
+       self.movetype = MOVETYPE_BOUNCE;
+       if(self.classname == "nexball_basketball")
+               self.touch = basketball_touch;
+       else if(self.classname == "nexball_football")
+               self.touch = football_touch;
+       self.cnt = 0;
+       self.think = ResetBall;
+       self.nextthink = time + autocvar_g_nexball_delay_idle + 3;
+       self.teamtime = 0;
+       self.pusher = world;
+       self.team = false;
+       _sound(self, CH_TRIGGER, self.noise1, VOL_BASE, ATTEN_NORM);
+       WaypointSprite_Ping(self.waypointsprite_attachedforcarrier);
+       LogNB("init", world);
+}
+
+void ResetBall(void)
+{SELFPARAM();
+       if(self.cnt < 2)        // step 1
+       {
+               if(time == self.teamtime)
+                       bprint("The ", Team_ColoredFullName(self.team), " held the ball for too long.\n");
+
+               self.touch = func_null;
+               self.movetype = MOVETYPE_NOCLIP;
+               self.velocity = '0 0 0'; // just in case?
+               if(!self.cnt)
+                       LogNB("resetidle", world);
+               self.cnt = 2;
+               self.nextthink = time;
+       }
+       else if(self.cnt < 4)     // step 2 and 3
+       {
+//             dprint("Step ", ftos(self.cnt), ": Calculated velocity: ", vtos(self.spawnorigin - self.origin), ", time: ", ftos(time), "\n");
+               self.velocity = (self.spawnorigin - self.origin) * (self.cnt - 1); // 1 or 0.5 second movement
+               self.nextthink = time + 0.5;
+               self.cnt += 1;
+       }
+       else     // step 4
+       {
+//             dprint("Step 4: time: ", ftos(time), "\n");
+               if(vlen(self.origin - self.spawnorigin) > 10)  // should not happen anymore
+                       LOG_TRACE("The ball moved too far away from its spawn origin.\nOffset: ",
+                                  vtos(self.origin - self.spawnorigin), " Velocity: ", vtos(self.velocity), "\n");
+               self.velocity = '0 0 0';
+               setorigin(self, self.spawnorigin); // make sure it's positioned correctly anyway
+               self.movetype = MOVETYPE_NONE;
+               self.think = InitBall;
+               self.nextthink = max(time, game_starttime) + autocvar_g_nexball_delay_start;
+       }
+}
+
+void football_touch(void)
+{SELFPARAM();
+       if(other.solid == SOLID_BSP)
+       {
+               if(time > self.lastground + 0.1)
+               {
+                       _sound(self, CH_TRIGGER, self.noise, VOL_BASE, ATTEN_NORM);
+                       self.lastground = time;
+               }
+               if(vlen(self.velocity) && !self.cnt)
+                       self.nextthink = time + autocvar_g_nexball_delay_idle;
+               return;
+       }
+       if (!IS_PLAYER(other))
+               return;
+       if(other.health < 1)
+               return;
+       if(!self.cnt)
+               self.nextthink = time + autocvar_g_nexball_delay_idle;
+
+       self.pusher = other;
+       self.team = other.team;
+
+       if(autocvar_g_nexball_football_physics == -1)   // MrBougo try 1, before decompiling Rev's original
+       {
+               if(vlen(other.velocity))
+                       self.velocity = other.velocity * 1.5 + '0 0 1' * autocvar_g_nexball_football_boost_up;
+       }
+       else if(autocvar_g_nexball_football_physics == 1)         // MrBougo's modded Rev style: partially independant of the height of the aiming point
+       {
+               makevectors(other.v_angle);
+               self.velocity = other.velocity + v_forward * autocvar_g_nexball_football_boost_forward + '0 0 1' * autocvar_g_nexball_football_boost_up;
+       }
+       else if(autocvar_g_nexball_football_physics == 2)         // 2nd mod try: totally independant. Really playable!
+       {
+               makevectors(other.v_angle.y * '0 1 0');
+               self.velocity = other.velocity + v_forward * autocvar_g_nexball_football_boost_forward + v_up * autocvar_g_nexball_football_boost_up;
+       }
+       else     // Revenant's original style (from the original mod's disassembly, acknowledged by Revenant)
+       {
+               makevectors(other.v_angle);
+               self.velocity = other.velocity + v_forward * autocvar_g_nexball_football_boost_forward + v_up * autocvar_g_nexball_football_boost_up;
+       }
+       self.avelocity = -250 * v_forward;  // maybe there is a way to make it look better?
+}
+
+void basketball_touch(void)
+{SELFPARAM();
+       if(other.ballcarried)
+       {
+               football_touch();
+               return;
+       }
+       if(!self.cnt && IS_PLAYER(other) && !other.frozen && !other.deadflag && (other != self.nb_dropper || time > self.nb_droptime + autocvar_g_nexball_delay_collect))
+       {
+               if(other.health <= 0)
+                       return;
+               LogNB("caught", other);
+               GiveBall(other, self);
+       }
+       else if(other.solid == SOLID_BSP)
+       {
+               _sound(self, CH_TRIGGER, self.noise, VOL_BASE, ATTEN_NORM);
+               if(vlen(self.velocity) && !self.cnt)
+                       self.nextthink = min(time + autocvar_g_nexball_delay_idle, self.teamtime);
+       }
+}
+
+void GoalTouch(void)
+{SELFPARAM();
+       entity ball;
+       float isclient, pscore, otherteam;
+       string pname;
+
+       if(gameover) return;
+       if((self.spawnflags & GOAL_TOUCHPLAYER) && other.ballcarried)
+               ball = other.ballcarried;
+       else
+               ball = other;
+       if(ball.classname != "nexball_basketball")
+               if(ball.classname != "nexball_football")
+                       return;
+       if((!ball.pusher && self.team != GOAL_OUT) || ball.cnt)
+               return;
+       EXACTTRIGGER_TOUCH;
+
+
+       if(nb_teams == 2)
+               otherteam = OtherTeam(ball.team);
+       else
+               otherteam = 0;
+
+       if((isclient = IS_CLIENT(ball.pusher)))
+               pname = ball.pusher.netname;
+       else
+               pname = "Someone (?)";
+
+       if(ball.team == self.team)               //owngoal (regular goals)
+       {
+               LogNB("owngoal", ball.pusher);
+               bprint("Boo! ", pname, "^7 scored a goal against their own team!\n");
+               pscore = -1;
+       }
+       else if(self.team == GOAL_FAULT)
+       {
+               LogNB("fault", ball.pusher);
+               if(nb_teams == 2)
+                       bprint(Team_ColoredFullName(otherteam), " gets a point due to ", pname, "^7's silliness.\n");
+               else
+                       bprint(Team_ColoredFullName(ball.team), " loses a point due to ", pname, "^7's silliness.\n");
+               pscore = -1;
+       }
+       else if(self.team == GOAL_OUT)
+       {
+               LogNB("out", ball.pusher);
+               if((self.spawnflags & GOAL_TOUCHPLAYER) && ball.owner)
+                       bprint(pname, "^7 went out of bounds.\n");
+               else
+                       bprint("The ball was returned.\n");
+               pscore = 0;
+       }
+       else                                                       //score
+       {
+               LogNB(strcat("goal:", ftos(self.team)), ball.pusher);
+               bprint("Goaaaaal! ", pname, "^7 scored a point for the ", Team_ColoredFullName(ball.team), ".\n");
+               pscore = 1;
+       }
+
+       _sound(ball, CH_TRIGGER, self.noise, VOL_BASE, ATTEN_NONE);
+
+       if(ball.team && pscore)
+       {
+               if(nb_teams == 2 && pscore < 0)
+                       TeamScore_AddToTeam(otherteam, ST_NEXBALL_GOALS, -pscore);
+               else
+                       TeamScore_AddToTeam(ball.team, ST_NEXBALL_GOALS, pscore);
+       }
+       if(isclient)
+       {
+               if(pscore > 0)
+                       PlayerScore_Add(ball.pusher, SP_NEXBALL_GOALS, pscore);
+               else if(pscore < 0)
+                       PlayerScore_Add(ball.pusher, SP_NEXBALL_FAULTS, -pscore);
+       }
+
+       if(ball.owner)  // Happens on spawnflag GOAL_TOUCHPLAYER
+               DropBall(ball, ball.owner.origin, ball.owner.velocity);
+
+       WaypointSprite_Ping(ball.waypointsprite_attachedforcarrier);
+
+       ball.cnt = 1;
+       ball.think = ResetBall;
+       if(ball.classname == "nexball_basketball")
+               ball.touch = football_touch; // better than func_null: football control until the ball gets reset
+       ball.nextthink = time + autocvar_g_nexball_delay_goal * (self.team != GOAL_OUT);
+}
+
+//=======================//
+//        team ents       //
+//=======================//
+spawnfunc(nexball_team)
+{
+       if(!g_nexball)
+       {
+               remove(self);
+               return;
+       }
+       self.team = self.cnt + 1;
+}
+
+void nb_spawnteam(string teamname, float teamcolor)
+{
+       LOG_TRACE("^2spawned team ", teamname, "\n");
+       entity e;
+       e = spawn();
+       e.classname = "nexball_team";
+       e.netname = teamname;
+       e.cnt = teamcolor;
+       e.team = e.cnt + 1;
+       nb_teams += 1;
+}
+
+void nb_spawnteams(void)
+{
+       bool t_red = false, t_blue = false, t_yellow = false, t_pink = false;
+       entity e;
+       for(e = world; (e = find(e, classname, "nexball_goal"));)
+       {
+               switch(e.team)
+               {
+               case NUM_TEAM_1:
+                       if(!t_red)
+                       {
+                               nb_spawnteam("Red", e.team-1)   ;
+                               t_red = true;
+                       }
+                       break;
+               case NUM_TEAM_2:
+                       if(!t_blue)
+                       {
+                               nb_spawnteam("Blue", e.team-1)  ;
+                               t_blue = true;
+                       }
+                       break;
+               case NUM_TEAM_3:
+                       if(!t_yellow)
+                       {
+                               nb_spawnteam("Yellow", e.team-1);
+                               t_yellow = true;
+                       }
+                       break;
+               case NUM_TEAM_4:
+                       if(!t_pink)
+                       {
+                               nb_spawnteam("Pink", e.team-1)  ;
+                               t_pink = true;
+                       }
+                       break;
+               }
+       }
+}
+
+void nb_delayedinit(void)
+{
+       if(find(world, classname, "nexball_team") == world)
+               nb_spawnteams();
+       nb_ScoreRules(nb_teams);
+}
+
+
+//=======================//
+//       spawnfuncs       //
+//=======================//
+
+void SpawnBall(void)
+{SELFPARAM();
+       if(!g_nexball) { remove(self); return; }
+
+//     balls += 4; // using the remaining bits to count balls will leave more than the max edict count, so it's fine
+
+       if(self.model == "")
+       {
+               self.model = "models/nexball/ball.md3";
+               self.scale = 1.3;
+       }
+
+       precache_model(self.model);
+       _setmodel(self, self.model);
+       setsize(self, BALL_MINS, BALL_MAXS);
+       ball_scale = self.scale;
+
+       relocate_nexball();
+       self.spawnorigin = self.origin;
+
+       self.effects = self.effects | EF_LOWPRECISION;
+
+       if(cvar(strcat("g_", self.classname, "_trail")))  //nexball_basketball :p
+       {
+               self.glow_color = autocvar_g_nexball_trail_color;
+               self.glow_trail = true;
+       }
+
+       self.movetype = MOVETYPE_FLY;
+
+       if(!autocvar_g_nexball_sound_bounce)
+               self.noise = "";
+       else if(self.noise == "")
+               self.noise = SND(NB_BOUNCE);
+       //bounce sound placeholder (FIXME)
+       if(self.noise1 == "")
+               self.noise1 = SND(NB_DROP);
+       //ball drop sound placeholder (FIXME)
+       if(self.noise2 == "")
+               self.noise2 = SND(NB_STEAL);
+       //stealing sound placeholder (FIXME)
+       if(self.noise) precache_sound(self.noise);
+       precache_sound(self.noise1);
+       precache_sound(self.noise2);
+
+       WaypointSprite_AttachCarrier(WP_NbBall, self, RADARICON_FLAGCARRIER); // the ball's team is not set yet, no rule update needed
+
+       self.reset = ball_restart;
+       self.think = InitBall;
+       self.nextthink = game_starttime + autocvar_g_nexball_delay_start;
+}
+
+spawnfunc(nexball_basketball)
+{
+       nexball_mode |= NBM_BASKETBALL;
+       self.classname = "nexball_basketball";
+       if (!(balls & BALL_BASKET))
+       {
+               /*
+               CVTOV(g_nexball_basketball_effects_default);
+               CVTOV(g_nexball_basketball_delay_hold);
+               CVTOV(g_nexball_basketball_delay_hold_forteam);
+               CVTOV(g_nexball_basketball_teamsteal);
+               */
+               autocvar_g_nexball_basketball_effects_default = autocvar_g_nexball_basketball_effects_default & BALL_EFFECTMASK;
+       }
+       if(!self.effects)
+               self.effects = autocvar_g_nexball_basketball_effects_default;
+       self.solid = SOLID_TRIGGER;
+       balls |= BALL_BASKET;
+       self.bouncefactor = autocvar_g_nexball_basketball_bouncefactor;
+       self.bouncestop = autocvar_g_nexball_basketball_bouncestop;
+       SpawnBall();
+}
+
+spawnfunc(nexball_football)
+{
+       nexball_mode |= NBM_FOOTBALL;
+       self.classname = "nexball_football";
+       self.solid = SOLID_TRIGGER;
+       balls |= BALL_FOOT;
+       self.bouncefactor = autocvar_g_nexball_football_bouncefactor;
+       self.bouncestop = autocvar_g_nexball_football_bouncestop;
+       SpawnBall();
+}
+
+float nb_Goal_Customize()
+{SELFPARAM();
+       entity e, wp_owner;
+       e = WaypointSprite_getviewentity(other);
+       wp_owner = self.owner;
+       if(SAME_TEAM(e, wp_owner)) { return false; }
+
+       return true;
+}
+
+void SpawnGoal(void)
+{SELFPARAM();
+       if(!g_nexball) { remove(self); return; }
+
+       EXACTTRIGGER_INIT;
+
+       if(self.team != GOAL_OUT && Team_TeamToNumber(self.team) != -1)
+       {
+               entity wp = WaypointSprite_SpawnFixed(WP_NbGoal, (self.absmin + self.absmax) * 0.5, self, sprite, RADARICON_NONE);
+               wp.colormod = ((self.team) ? Team_ColorRGB(self.team) : '1 0.5 0');
+               self.sprite.customizeentityforclient = nb_Goal_Customize;
+       }
+
+       self.classname = "nexball_goal";
+       if(self.noise == "")
+               self.noise = "ctf/respawn.wav";
+       precache_sound(self.noise);
+       self.touch = GoalTouch;
+}
+
+spawnfunc(nexball_redgoal)
+{
+       self.team = NUM_TEAM_1;
+       SpawnGoal();
+}
+spawnfunc(nexball_bluegoal)
+{
+       self.team = NUM_TEAM_2;
+       SpawnGoal();
+}
+spawnfunc(nexball_yellowgoal)
+{
+       self.team = NUM_TEAM_3;
+       SpawnGoal();
+}
+spawnfunc(nexball_pinkgoal)
+{
+       self.team = NUM_TEAM_4;
+       SpawnGoal();
+}
+
+spawnfunc(nexball_fault)
+{
+       self.team = GOAL_FAULT;
+       if(self.noise == "")
+               self.noise = SND(TYPEHIT);
+       SpawnGoal();
+}
+
+spawnfunc(nexball_out)
+{
+       self.team = GOAL_OUT;
+       if(self.noise == "")
+               self.noise = SND(TYPEHIT);
+       SpawnGoal();
+}
+
+//
+//Spawnfuncs preserved for compatibility
+//
+
+spawnfunc(ball)
+{
+       spawnfunc_nexball_football(this);
+}
+spawnfunc(ball_football)
+{
+       spawnfunc_nexball_football(this);
+}
+spawnfunc(ball_basketball)
+{
+       spawnfunc_nexball_basketball(this);
+}
+// The "red goal" is defended by blue team. A ball in there counts as a point for red.
+spawnfunc(ball_redgoal)
+{
+       spawnfunc_nexball_bluegoal(this);       // I blame Revenant
+}
+spawnfunc(ball_bluegoal)
+{
+       spawnfunc_nexball_redgoal(this);        // but he didn't mean to cause trouble :p
+}
+spawnfunc(ball_fault)
+{
+       spawnfunc_nexball_fault(this);
+}
+spawnfunc(ball_bound)
+{
+       spawnfunc_nexball_out(this);
+}
+
+//=======================//
+//       Weapon code     //
+//=======================//
+
+
+void W_Nexball_Think()
+{SELFPARAM();
+       //dprint("W_Nexball_Think\n");
+       //vector new_dir = steerlib_arrive(self.enemy.origin, 2500);
+       vector new_dir = normalize(self.enemy.origin + '0 0 50' - self.origin);
+       vector old_dir = normalize(self.velocity);
+       float _speed = vlen(self.velocity);
+       vector new_vel = normalize(old_dir + (new_dir * autocvar_g_nexball_safepass_turnrate)) * _speed;
+       //vector new_vel = (new_dir * autocvar_g_nexball_safepass_turnrate
+
+       self.velocity = new_vel;
+
+       self.nextthink = time;
+}
+
+void W_Nexball_Touch(void)
+{SELFPARAM();
+       entity ball, attacker;
+       attacker = self.owner;
+       //self.think = func_null;
+       //self.enemy = world;
+
+       PROJECTILE_TOUCH;
+       if(attacker.team != other.team || autocvar_g_nexball_basketball_teamsteal)
+               if((ball = other.ballcarried) && !other.frozen && !other.deadflag && (IS_PLAYER(attacker)))
+               {
+                       other.velocity = other.velocity + normalize(self.velocity) * other.damageforcescale * autocvar_g_balance_nexball_secondary_force;
+                       other.flags &= ~FL_ONGROUND;
+                       if(!attacker.ballcarried)
+                       {
+                               LogNB("stole", attacker);
+                               _sound(other, CH_TRIGGER, ball.noise2, VOL_BASE, ATTEN_NORM);
+
+                               if(SAME_TEAM(attacker, other) && time > attacker.teamkill_complain)
+                               {
+                                       attacker.teamkill_complain = time + 5;
+                                       attacker.teamkill_soundtime = time + 0.4;
+                                       attacker.teamkill_soundsource = other;
+                               }
+
+                               GiveBall(attacker, other.ballcarried);
+                       }
+               }
+       remove(self);
+}
+
+void W_Nexball_Attack(float t)
+{SELFPARAM();
+       entity ball;
+       float mul, mi, ma;
+       if(!(ball = self.ballcarried))
+               return;
+
+       W_SetupShot(self, false, 4, SND(NB_SHOOT1), CH_WEAPON_A, 0);
+       tracebox(w_shotorg, BALL_MINS, BALL_MAXS, w_shotorg, MOVE_WORLDONLY, world);
+       if(trace_startsolid)
+       {
+               if(self.metertime)
+                       self.metertime = 0; // Shot failed, hide the power meter
+               return;
+       }
+
+       //Calculate multiplier
+       if(t < 0)
+               mul = 1;
+       else
+       {
+               mi = autocvar_g_nexball_basketball_meter_minpower;
+               ma = max(mi, autocvar_g_nexball_basketball_meter_maxpower); // avoid confusion
+               //One triangle wave period with 1 as max
+               mul = 2 * (t % g_nexball_meter_period) / g_nexball_meter_period;
+               if(mul > 1)
+                       mul = 2 - mul;
+               mul = mi + (ma - mi) * mul; // range from the minimal power to the maximal power
+       }
+
+       DropBall(ball, w_shotorg, W_CalculateProjectileVelocity(self.velocity, w_shotdir * autocvar_g_balance_nexball_primary_speed * mul, false));
+
+
+       //TODO: use the speed_up cvar too ??
+}
+
+vector trigger_push_calculatevelocity(vector org, entity tgt, float ht);
+
+void W_Nexball_Attack2(void)
+{SELFPARAM();
+       if(self.ballcarried.enemy)
+       {
+               entity _ball = self.ballcarried;
+               W_SetupShot(self, false, 4, SND(NB_SHOOT1), CH_WEAPON_A, 0);
+               DropBall(_ball, w_shotorg, trigger_push_calculatevelocity(_ball.origin, _ball.enemy, 32));
+               _ball.think = W_Nexball_Think;
+               _ball.nextthink = time;
+               return;
+       }
+
+       if(!autocvar_g_nexball_tackling)
+               return;
+
+       W_SetupShot(self, false, 2, SND(NB_SHOOT2), CH_WEAPON_A, 0);
+       entity missile = spawn();
+
+       missile.owner = self;
+       missile.classname = "ballstealer";
+
+       missile.movetype = MOVETYPE_FLY;
+       PROJECTILE_MAKETRIGGER(missile);
+
+       //setmodel(missile, "models/elaser.mdl");  // precision set below
+       setsize(missile, '0 0 0', '0 0 0');
+       setorigin(missile, w_shotorg);
+
+       W_SetupProjVelocity_Basic(missile, autocvar_g_balance_nexball_secondary_speed, 0);
+       missile.angles = vectoangles(missile.velocity);
+       missile.touch = W_Nexball_Touch;
+       missile.think = SUB_Remove;
+       missile.nextthink = time + autocvar_g_balance_nexball_secondary_lifetime; //FIXME: use a distance instead?
+
+       missile.effects = EF_BRIGHTFIELD | EF_LOWPRECISION;
+       missile.flags = FL_PROJECTILE;
+
+       CSQCProjectile(missile, true, PROJECTILE_ELECTRO, true);
+}
+
+float ball_customize()
+{SELFPARAM();
+       if(!self.owner)
+       {
+               self.effects &= ~EF_FLAME;
+               self.scale = 1;
+               self.customizeentityforclient = func_null;
+               return true;
+       }
+
+       if(other == self.owner)
+       {
+               self.scale = autocvar_g_nexball_viewmodel_scale;
+               if(self.enemy)
+                       self.effects |= EF_FLAME;
+               else
+                       self.effects &= ~EF_FLAME;
+       }
+       else
+       {
+               self.effects &= ~EF_FLAME;
+               self.scale = 1;
+       }
+
+       return true;
+}
+
+       METHOD(BallStealer, wr_think, void(BallStealer thiswep, entity actor, bool fire1, bool fire2))
+       {
+               if(fire1)
+                       if(weapon_prepareattack(thiswep, actor, false, autocvar_g_balance_nexball_primary_refire))
+                               if(autocvar_g_nexball_basketball_meter)
+                               {
+                                       if(self.ballcarried && !self.metertime)
+                                               self.metertime = time;
+                                       else
+                                               weapon_thinkf(actor, WFRAME_FIRE1, autocvar_g_balance_nexball_primary_animtime, w_ready);
+                               }
+                               else
+                               {
+                                       W_Nexball_Attack(-1);
+                                       weapon_thinkf(actor, WFRAME_FIRE1, autocvar_g_balance_nexball_primary_animtime, w_ready);
+                               }
+               if(fire2)
+                       if(weapon_prepareattack(thiswep, actor, true, autocvar_g_balance_nexball_secondary_refire))
+                       {
+                               W_Nexball_Attack2();
+                               weapon_thinkf(actor, WFRAME_FIRE2, autocvar_g_balance_nexball_secondary_animtime, w_ready);
+                       }
+
+               if(!fire1 && self.metertime && self.ballcarried)
+               {
+                       W_Nexball_Attack(time - self.metertime);
+                       // DropBall or stealing will set metertime back to 0
+                       weapon_thinkf(actor, WFRAME_FIRE1, autocvar_g_balance_nexball_primary_animtime, w_ready);
+               }
+       }
+       METHOD(BallStealer, wr_setup, void(BallStealer thiswep))
+       {
+               //weapon_setup(WEP_PORTO.m_id);
+       }
+       METHOD(BallStealer, wr_checkammo1, bool(BallStealer thiswep))
+       {
+               return true;
+       }
+       METHOD(BallStealer, wr_checkammo2, bool(BallStealer thiswep))
+       {
+               return true;
+       }
+
+MUTATOR_HOOKFUNCTION(nexball_BallDrop)
+{SELFPARAM();
+       if(self.ballcarried && g_nexball)
+               DropBall(self.ballcarried, self.origin, self.velocity);
+
+       return 0;
+}
+
+MUTATOR_HOOKFUNCTION(nexball_PlayerPreThink)
+{SELFPARAM();
+       makevectors(self.v_angle);
+       if(nexball_mode & NBM_BASKETBALL)
+       {
+               if(self.ballcarried)
+               {
+                       // 'view ball'
+                       self.ballcarried.velocity = self.velocity;
+                       self.ballcarried.customizeentityforclient = ball_customize;
+
+                       setorigin(self.ballcarried, self.origin + self.view_ofs +
+                                         v_forward * autocvar_g_nexball_viewmodel_offset.x +
+                                         v_right * autocvar_g_nexball_viewmodel_offset.y +
+                                         v_up * autocvar_g_nexball_viewmodel_offset.z);
+
+                       // 'safe passing'
+                       if(autocvar_g_nexball_safepass_maxdist)
+                       {
+                               if(self.ballcarried.wait < time && self.ballcarried.enemy)
+                               {
+                                       //centerprint(self, sprintf("Lost lock on %s", self.ballcarried.enemy.netname));
+                                       self.ballcarried.enemy = world;
+                               }
+
+
+                               //tracebox(self.origin + self.view_ofs, '-2 -2 -2', '2 2 2', self.origin + self.view_ofs + v_forward * autocvar_g_nexball_safepass_maxdist);
+                               crosshair_trace(self);
+                               if( trace_ent &&
+                                       IS_CLIENT(trace_ent) &&
+                                       trace_ent.deadflag == DEAD_NO &&
+                                       trace_ent.team == self.team &&
+                                       vlen(trace_ent.origin - self.origin) <= autocvar_g_nexball_safepass_maxdist )
+                               {
+
+                                       //if(self.ballcarried.enemy != trace_ent)
+                                       //      centerprint(self, sprintf("Locked to %s", trace_ent.netname));
+                                       self.ballcarried.enemy = trace_ent;
+                                       self.ballcarried.wait = time + autocvar_g_nexball_safepass_holdtime;
+
+
+                               }
+                       }
+               }
+               else
+               {
+                       if(self.weaponentity.weapons)
+                       {
+                               self.weapons = self.weaponentity.weapons;
+                               Weapon w = WEP_NEXBALL;
+                               w.wr_resetplayer(w);
+                               self.switchweapon = self.weaponentity.switchweapon;
+                               W_SwitchWeapon(self.switchweapon);
+
+               self.weaponentity.weapons = '0 0 0';
+                       }
+               }
+
+       }
+
+       nexball_setstatus();
+
+       return false;
+}
+
+MUTATOR_HOOKFUNCTION(nexball_PlayerSpawn)
+{SELFPARAM();
+       self.weaponentity.weapons = '0 0 0';
+
+       if(nexball_mode & NBM_BASKETBALL)
+               self.weapons |= WEPSET(NEXBALL);
+       else
+               self.weapons = '0 0 0';
+
+       return false;
+}
+
+.float stat_sv_airspeedlimit_nonqw;
+.float stat_sv_maxspeed;
+
+MUTATOR_HOOKFUNCTION(nexball_PlayerPhysics)
+{SELFPARAM();
+       if(self.ballcarried)
+       {
+               self.stat_sv_airspeedlimit_nonqw *= autocvar_g_nexball_basketball_carrier_highspeed;
+               self.stat_sv_maxspeed *= autocvar_g_nexball_basketball_carrier_highspeed;
+       }
+       return false;
+}
+
+MUTATOR_HOOKFUNCTION(nexball_ForbidThrowing)
+{SELFPARAM();
+       if(self.weapon == WEP_NEXBALL.m_id)
+               return true;
+
+       return false;
+}
+
+MUTATOR_HOOKFUNCTION(nexball_FilterItem)
+{SELFPARAM();
+       if(self.classname == "droppedweapon")
+       if(self.weapon == WEP_NEXBALL.m_id)
+               return true;
+
+       return false;
+}
+
+MUTATOR_DEFINITION(gamemode_nexball)
+{
+       MUTATOR_HOOK(PlayerDies, nexball_BallDrop, CBC_ORDER_ANY);
+       MUTATOR_HOOK(MakePlayerObserver, nexball_BallDrop, CBC_ORDER_ANY);
+       MUTATOR_HOOK(ClientDisconnect, nexball_BallDrop, CBC_ORDER_ANY);
+       MUTATOR_HOOK(PlayerSpawn, nexball_PlayerSpawn, CBC_ORDER_ANY);
+       MUTATOR_HOOK(PlayerPreThink, nexball_PlayerPreThink, CBC_ORDER_ANY);
+       MUTATOR_HOOK(PlayerPhysics, nexball_PlayerPhysics, CBC_ORDER_ANY);
+       MUTATOR_HOOK(ForbidThrowCurrentWeapon, nexball_ForbidThrowing, CBC_ORDER_ANY);
+       MUTATOR_HOOK(FilterItem, nexball_FilterItem, CBC_ORDER_ANY);
+
+       MUTATOR_ONADD
+       {
+               g_nexball_meter_period = autocvar_g_nexball_meter_period;
+               if(g_nexball_meter_period <= 0)
+                       g_nexball_meter_period = 2; // avoid division by zero etc. due to silly users
+               g_nexball_meter_period = rint(g_nexball_meter_period * 32) / 32; //Round to 1/32ths to send as a byte multiplied by 32
+               addstat(STAT_NB_METERSTART, AS_FLOAT, metertime);
+
+               // General settings
+               /*
+               CVTOV(g_nexball_football_boost_forward);   //100
+               CVTOV(g_nexball_football_boost_up);             //200
+               CVTOV(g_nexball_delay_idle);                       //10
+               CVTOV(g_nexball_football_physics);               //0
+               */
+               radar_showennemies = autocvar_g_nexball_radar_showallplayers;
+
+               InitializeEntity(world, nb_delayedinit, INITPRIO_GAMETYPE);
+               WEP_NEXBALL.spawnflags &= ~WEP_FLAG_MUTATORBLOCKED;
+       }
+
+       MUTATOR_ONROLLBACK_OR_REMOVE
+       {
+               WEP_NEXBALL.spawnflags |= WEP_FLAG_MUTATORBLOCKED;
+               // we actually cannot roll back nb_delayedinit here
+               // BUT: we don't need to! If this gets called, adding always
+               // succeeds.
+       }
+
+       MUTATOR_ONREMOVE
+       {
+               LOG_INFO("This is a game type and it cannot be removed at runtime.");
+               return -1;
+       }
+
+       return 0;
+}
+
+#endif
+#endif
diff --git a/qcsrc/common/gamemodes/gamemode/nexball/nexball.qh b/qcsrc/common/gamemodes/gamemode/nexball/nexball.qh
new file mode 100644 (file)
index 0000000..7d19c50
--- /dev/null
@@ -0,0 +1,42 @@
+#ifndef GAMEMODE_NEXBALL_H
+#define GAMEMODE_NEXBALL_H
+
+#include "weapon.qc"
+
+#ifdef SVQC
+MUTATOR_DECLARATION(gamemode_nexball);
+
+//EF_BRIGHTFIELD|EF_BRIGHTLIGHT|EF_DIMLIGHT|EF_BLUE|EF_RED|EF_FLAME
+const float BALL_EFFECTMASK = 1229;
+const vector BALL_MINS = '-16 -16 -16'; // The model is 24*24*24
+const vector BALL_MAXS = '16 16 16';
+const vector BALL_ATTACHORG = '3 0 16';
+const float BALL_FOOT = 1;
+const float BALL_BASKET = 2;
+//spawnflags
+const float GOAL_TOUCHPLAYER = 1;
+//goal types
+const float GOAL_FAULT = -1;
+const float GOAL_OUT = -2;
+
+void DropBall(entity ball, vector org, vector vel);
+float autocvar_g_nexball_football_boost_forward;
+float autocvar_g_nexball_football_boost_up;
+float autocvar_g_nexball_football_physics;
+float autocvar_g_nexball_delay_idle;
+float autocvar_g_nexball_basketball_delay_hold;
+float autocvar_g_nexball_basketball_delay_hold_forteam;
+float autocvar_g_nexball_basketball_effects_default;
+float autocvar_g_nexball_basketball_teamsteal;
+float autocvar_g_nexball_meter_period;
+
+float balls;
+float ball_scale;
+float nb_teams;
+
+.entity nb_dropper;
+.float nb_droptime;
+
+.float teamtime;
+#endif
+#endif
diff --git a/qcsrc/common/gamemodes/gamemode/nexball/weapon.qc b/qcsrc/common/gamemodes/gamemode/nexball/weapon.qc
new file mode 100644 (file)
index 0000000..ae882bb
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef GAMEMODE_NEXBALL_WEAPON_H
+#define GAMEMODE_NEXBALL_WEAPON_H
+
+CLASS(BallStealer, PortoLaunch)
+/* flags     */ ATTRIB(BallStealer, spawnflags, int, WEP_TYPE_OTHER | WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
+/* impulse   */ ATTRIB(BallStealer, impulse, int, 0);
+/* refname   */ ATTRIB(BallStealer, netname, string, "ballstealer");
+/* wepname   */ ATTRIB(BallStealer, message, string, _("Ball Stealer"));
+ENDCLASS(BallStealer)
+REGISTER_WEAPON(NEXBALL, NEW(BallStealer));
+
+#endif
index d322db4b7991e21162974526aef6e1175c155780..48b92bee6b88ed1762ccb6ab3ef0c7b67042304d 100644 (file)
@@ -5,4 +5,3 @@
 #include "item/jetpack.qc"
 #include "item/pickup.qc"
 #include "item/powerup.qc"
-#include "../../server/mutators/mutator_instagib_items.qc"
index 672ed707cd0c3bf271d98fd713ba3f44177ae32a..a825b4ed16fbfb58a8718ce4ca5cd86d2e9c97cb 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef ITEMS_ALL_H
 #define ITEMS_ALL_H
 
+#include "../command/all.qh"
+
 #include "item.qh"
 
 REGISTRY(Items, BIT(5))
@@ -8,8 +10,25 @@ REGISTER_REGISTRY(RegisterItems)
 /** If you register a new item, make sure to add it to all.inc */
 #define REGISTER_ITEM(id, class) REGISTER(RegisterItems, ITEM, Items, id, m_id, NEW(class))
 
+REGISTRY_SORT(Items, m_name, 0)
+STATIC_INIT(Items) { FOREACH(Items, true, LAMBDA(it.m_id = i)); }
+
 void Dump_Items();
 
+GENERIC_COMMAND(dumpitems, "Dump all items to the console") {
+    switch (request) {
+        case CMD_REQUEST_COMMAND: {
+            Dump_Items();
+            return;
+        }
+        default:
+        case CMD_REQUEST_USAGE: {
+            LOG_INFOF("\nUsage:^3 %s dumpitems", GetProgramCommandPrefix());
+            return;
+        }
+    }
+}
+
 #ifndef MENUQC
 string Item_Model(string item_mdl);
 #endif
index ceb9a0aa4df1192c904706a711d0922f92d463b5..7a12b305006754776fd9ff90af756c916032d594 100644 (file)
@@ -1,5 +1,46 @@
 #ifndef GAMEITEM_H
 #define GAMEITEM_H
+
+const int IT_UNLIMITED_WEAPON_AMMO             =       1; // when this bit is set, using a weapon does not reduce ammo. Checkpoints can give this powerup.
+const int IT_UNLIMITED_SUPERWEAPONS            =       2; // when this bit is set, superweapons don't expire. Checkpoints can give this powerup.
+const int IT_CTF_SHIELDED                      =       4; // set for the flag shield
+const int IT_USING_JETPACK                     =       8; // confirmation that button is pressed
+const int IT_JETPACK                           =      16; // actual item
+const int IT_FUEL_REGEN                        =      32; // fuel regeneration trigger
+// where is 64... ?
+const int IT_FUEL                                      =     128;
+// -Wdouble-declaration
+#define IT_SHELLS                                        256
+// -Wdouble-declaration
+#define IT_NAILS                                         512
+// -Wdouble-declaration
+#define IT_ROCKETS                                      1024
+// -Wdouble-declaration
+#define IT_CELLS                                        2048
+const int IT_SUPERWEAPON                               =    4096;
+const int IT_STRENGTH                                  =    8192;
+const int IT_INVINCIBLE                                =   16384;
+const int IT_HEALTH                                    =   32768;
+const int IT_PLASMA                                    =   65536;
+
+// shared value space (union):
+       // for items:
+       // -Wdouble-declaration
+       #define IT_KEY1                                                 131072
+       // -Wdouble-declaration
+       #define IT_KEY2                                                 262144
+// end
+
+const int IT_5HP                               =  524288;
+const int IT_25HP                              = 1048576;
+const int IT_ARMOR_SHARD                       = 2097152;
+const int IT_ARMOR                             = 4194304;
+
+// item masks
+const int IT_AMMO                              =    3968; // IT_FUEL | IT_SHELLS | IT_NAILS | IT_ROCKETS | IT_CELLS | IT_PLASMA;
+const int IT_PICKUPMASK                        =      51; // IT_FUEL_REGEN | IT_JETPACK | IT_UNLIMITED_AMMO; // strength and invincible are handled separately
+const int IT_UNLIMITED_AMMO                    =       3; // IT_UNLIMITED_SUPERWEAPONS | IT_UNLIMITED_WEAPON_AMMO;
+
 #define ITEM_HANDLE(signal, ...) __Item_Send_##signal(__VA_ARGS__)
 /** If you register a new item, make sure to add it to all.inc */
 CLASS(GameItem, Object)
index f411d748a8d5eaeb891ec8eace2d2dd76725695e..a1b2f14037fcc7394325624c56beb7406f5d5041 100644 (file)
@@ -1,5 +1,4 @@
 #include "powerup.qh"
-#include "../../../server/t_items.qh"
 
 #ifndef SVQC
 .int m_itemid;
index ba21ff43d9cac6da7b25050680d06f4baf5fe3df..1daf862b6dec7e0b5aae6e6d30bdc0a60dc6fb67 100644 (file)
@@ -1,5 +1,4 @@
 #if defined(CSQC)
-       #include "../dpdefs/csprogsdefs.qh"
     #include "../client/defs.qh"
     #include "util.qh"
     #include "buffs/all.qh"
@@ -7,8 +6,6 @@
     #include "mapinfo.qh"
 #elif defined(MENUQC)
 #elif defined(SVQC)
-       #include "../dpdefs/progsdefs.qh"
-    #include "../dpdefs/dpextensions.qh"
     #include "util.qh"
     #include "buffs/all.qh"
     #include "monsters/all.qh"
index a073af89757a3562c63a20e7b97196e3a07dd1cc..016e8a3edf1932665942c13930653246934556a9 100644 (file)
@@ -1,8 +1,6 @@
 #ifndef CL_MINIGAMES_H
 #define CL_MINIGAMES_H
 
-#include "../../dpdefs/keycodes.qh"
-
 // Get a square in the center of the avaliable area
 // \note macro to pass by reference pos and mySize
 #define minigame_hud_fitsqare(pos, mySize) \
index 2a0b0362051f95426b7c2afd9d2dcc006278b9b1..f1ee4f675caf8341e9521cf0ebf8380a442e4081 100644 (file)
@@ -1,5 +1,5 @@
+#include "cl_minigames_hud.qh"
 #include "minigames.qh"
-#include "../../client/mapvoting.qh"
 
 // whether the mouse is over the given panel
 bool HUD_mouse_over(entity somepanel)
diff --git a/qcsrc/common/minigames/cl_minigames_hud.qh b/qcsrc/common/minigames/cl_minigames_hud.qh
new file mode 100644 (file)
index 0000000..f170c59
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef CL_MINIGAMES_HUD_H
+#define CL_MINIGAMES_HUD_H
+
+float HUD_Minigame_InputEvent(float bInputType, float nPrimary, float nSecondary);
+void HUD_Minigame_Mouse();
+
+#endif
index 98020972a742ee5a59e4eef24e69a7a483f6e69c..a7ba05068ac85e929d607a43e7d0028c4385edac 100644 (file)
@@ -3,7 +3,6 @@ REGISTER_MINIGAME(c4, "Connect Four");
 const float C4_TURN_PLACE = 0x0100; // player has to place a piece on the board
 const float C4_TURN_WIN   = 0x0200; // player has won
 const float C4_TURN_DRAW  = 0x0400; // no moves are possible
-const float C4_TURN_TYPE  = 0x0f00; // turn type mask
 
 const float C4_TURN_TEAM1 = 0x0001;
 const float C4_TURN_TEAM2 = 0x0002;
index efce0e66b6be5030a96beb0446cdd2c3378a4b66..3ef2124dcac1b72aa7a27a84e6a21bcea136c115 100644 (file)
@@ -17,6 +17,8 @@ const int PP_NUM_CNT = 7;
 
 const int PP_TILE_SIZE = 7;
 
+.int cnt;
+
 .int pp_team1_score;
 .int pp_team2_score;
 
index bef26caaa53cbc8ad2489b5604081470e47a384b..cbb13420fb1573ad76e31e2b7eb6a1057e0fa51c 100644 (file)
@@ -1,10 +1,12 @@
-REGISTER_MINIGAME(snake, "Snake");
+REGISTER_MINIGAME(snake, "Snake"); // SNAAAAKE
 
 const float SNAKE_TURN_MOVE  = 0x0100; // the snake is moving, player must control it
-const float SNAKE_TURN_LOSS  = 0x0200; // they did it?!
-const float SNAKE_TURN_WAIT  = 0x0400; // the snake is waiting for the player to make their first move and begin the game
+const float SNAKE_TURN_WIN   = 0x0200; // multiplayer victory
+const float SNAKE_TURN_LOSS  = 0x0400; // they did it?!
 const float SNAKE_TURN_TYPE  = 0x0f00; // turn type mask
 
+const int SNAKE_TURN_TEAM  = 0x000f; // turn team mask
+
 const int SNAKE_SF_PLAYERSCORE = MINIG_SF_CUSTOM;
 
 const int SNAKE_LET_CNT = 15;
@@ -12,18 +14,38 @@ const int SNAKE_NUM_CNT = 15;
 
 const int SNAKE_TILE_SIZE = 15;
 
+const int SNAKE_TEAMS = 6;
+
 bool autocvar_sv_minigames_snake_wrap = false;
 float autocvar_sv_minigames_snake_delay_initial = 0.7;
 float autocvar_sv_minigames_snake_delay_multiplier = 50;
 float autocvar_sv_minigames_snake_delay_min = 0.1;
+int autocvar_sv_minigames_snake_lives = 3;
 
 .int snake_score;
-.entity snake_head;
 
 .float snake_delay;
-.float snake_nextmove;
 .vector snake_dir;
 
+.entity snake_next, snake_last, snake_prev;
+
+.bool snake_tail;
+
+.int snake_lives[SNAKE_TEAMS + 1];
+
+.int snake_lost_teams;
+
+bool snake_alone(entity minig)
+{
+       int headcount = 0;
+       entity e = world;
+       while ( ( e = findentity(e,owner,minig) ) )
+               if ( e.classname == "minigame_board_piece" && e.cnt == 1 )
+                       ++headcount;
+
+       return headcount <= 1;
+}
+
 // find same game piece given its tile name
 entity snake_find_piece(entity minig, string tile)
 {
@@ -35,11 +57,11 @@ entity snake_find_piece(entity minig, string tile)
 }
 
 // find same game piece given its cnt
-entity snake_find_cnt(entity minig, int tile)
+entity snake_find_cnt(entity minig, int steam, int tile)
 {
        entity e = world;
        while ( ( e = findentity(e,owner,minig) ) )
-               if ( e.classname == "minigame_board_piece" && e.cnt == tile )
+               if ( e.classname == "minigame_board_piece" && e.cnt == tile && e.team == steam )
                        return e;
        return world;
 }
@@ -54,6 +76,15 @@ bool snake_valid_tile(string tile)
        return 0 <= number && number < SNAKE_NUM_CNT && 0 <= letter && letter < SNAKE_LET_CNT;
 }
 
+entity snake_find_head(entity minig, int steam)
+{
+       entity e = world;
+       while ( ( e = findentity(e,owner,minig) ) )
+               if ( e.classname == "minigame_board_piece" && e.cnt == 1 && e.team == steam )
+                       return e;
+       return world;
+}
+
 void snake_new_mouse(entity minigame)
 {
        RandomSelection_Init();
@@ -67,184 +98,297 @@ void snake_new_mouse(entity minigame)
        }
 
        entity piece = msle_spawn(minigame,"minigame_board_piece");
-       piece.team = 1;
+       piece.team = 0;
        piece.netname = strzone(RandomSelection_chosen_string);
        minigame_server_sendflags(piece,MINIG_SF_ALL);
 
        minigame_server_sendflags(minigame,MINIG_SF_UPDATE);
 }
 
-void snake_move_head(entity minigame);
+entity snake_get_player(entity minigame, int pteam);
+int snake_winning_team(entity minigame)
+{
+       int winning_team = 0;
+       for(int i = 1; i <= SNAKE_TEAMS; ++i)
+       {
+               entity pl = snake_get_player(minigame, i);
+               if(pl && minigame.snake_lives[i] > 0)
+               {
+                       if(winning_team)
+                               return 0;
+                       winning_team = i;
+               }
+       }
+
+       return winning_team;
+}
+
+void snake_check_winner(entity minigame)
+{
+       if(snake_alone(minigame) && !minigame.snake_lost_teams)
+               return;
+
+       int winner = snake_winning_team(minigame);
+
+       int alivecnt = 0;
+       for(int i = 1; i <= SNAKE_TEAMS; ++i)
+       {
+               entity pl = snake_get_player(minigame, i);
+               if(pl && minigame.snake_lives[i] > 0)
+                       ++alivecnt;
+       }
+
+       if(!alivecnt)
+       {
+               minigame.minigame_flags = SNAKE_TURN_LOSS;
+               minigame_server_sendflags(minigame,MINIG_SF_UPDATE);
+               return;
+       }
+
+       if(winner)
+       {
+               minigame.minigame_flags = SNAKE_TURN_WIN | winner;
+               minigame_server_sendflags(minigame,MINIG_SF_UPDATE);
+       }
+}
+
+void snake_move_head(entity minigame, entity head);
 void snake_head_think()
 {
        entity minigame = self.owner;
 
        if(minigame.minigame_flags & SNAKE_TURN_MOVE)
-               snake_move_head(minigame);
+               snake_move_head(minigame, self);
 
-       self.nextthink = time + minigame.snake_delay;
+       snake_check_winner(minigame);
+
+       self.nextthink = time + self.snake_delay;
 }
 
-void snake_setup_pieces(entity minigame)
+void minigame_setup_snake(entity minigame, int pteam)
 {
-       int targnum = bound(1, floor(random() * SNAKE_NUM_CNT), SNAKE_NUM_CNT - 1);
-       int targlet = bound(1, floor(random() * SNAKE_LET_CNT), SNAKE_LET_CNT - 1);
+       RandomSelection_Init();
+       int i, j;
+       for(i = 1; i < SNAKE_LET_CNT - 1; ++i)
+       for(j = 1; j < SNAKE_NUM_CNT - 1; ++j)
+       {
+               string pos = minigame_tile_buildname(i, j);
+               if(!snake_find_piece(minigame, pos))
+                       RandomSelection_Add(world, 0, pos, 1, 1);
+       }
 
        entity piece = msle_spawn(minigame,"minigame_board_piece");
-       piece.team = 1; // init default team?
-       piece.netname = strzone(minigame_tile_buildname(targlet,targnum));
+       piece.team = pteam;
+       piece.netname = strzone(RandomSelection_chosen_string);
        piece.cnt = 1;
+       piece.snake_next = world;
+       piece.snake_prev = world;
+       piece.snake_last = piece;
        piece.think = snake_head_think;
+       piece.snake_delay = autocvar_sv_minigames_snake_delay_initial;
        piece.nextthink = time + 0.1;
        minigame_server_sendflags(piece,MINIG_SF_ALL);
+}
 
-       minigame.snake_head = piece;
-
+void snake_setup_pieces(entity minigame)
+{
        snake_new_mouse(minigame);
 
        minigame_server_sendflags(minigame,MINIG_SF_UPDATE);
 }
 
-void snake_add_score(entity minigame, int thescore)
+entity snake_get_player(entity minigame, int pteam)
+{
+       entity e;
+#ifdef SVQC
+       for(e = minigame.minigame_players; e; e = e.list_next)
+#elif defined(CSQC)
+       e = world;
+       while( (e = findentity(e,owner,minigame)) )
+               if ( e.classname == "minigame_player" )
+#endif
+       if(e.team == pteam)
+               return e;
+       return world;
+}
+
+void snake_add_score(entity minigame, int pteam, int thescore)
 {
 #ifdef SVQC
        if(!minigame)
                return;
-       if(minigame.minigame_players)
+       entity pl = snake_get_player(minigame, pteam);
+       if(pl)
        {
-               minigame.minigame_players.snake_score += thescore;
-               minigame.minigame_players.SendFlags |= SNAKE_SF_PLAYERSCORE;
+               pl.snake_score += thescore;
+               pl.SendFlags |= SNAKE_SF_PLAYERSCORE;
        }
 #endif
 }
 
-void snake_move_body(entity minigame, bool ate_mouse)
+void snake_move_body(entity minigame, entity head, bool ate_mouse)
 {
-       entity tail = world;
-       string tailpos = string_null;
-       vector taildir = '0 0 0';
-
-       int i, pieces = 0;
-       for(i = (SNAKE_NUM_CNT * SNAKE_LET_CNT); i >= 2; --i)
+       for(entity e = head.snake_last; e; e = e.snake_prev)
        {
-               entity piece = snake_find_cnt(minigame, i);
-               entity nextpiece = snake_find_cnt(minigame, i - 1);
-               if(!piece)
-                       continue;
+               if(!e || e == head) { break; }
 
-               pieces++;
+               entity nextpiece = e.snake_prev; // can be head
 
-               if(!tail)
-               {
-                       tail = piece;
-                       tailpos = piece.netname;
-                       taildir = piece.snake_dir;
-               }
-
-               if(piece.netname) { strunzone(piece.netname); }
-               piece.netname = strzone(nextpiece.netname);
-               piece.snake_dir = nextpiece.snake_dir;
-               minigame_server_sendflags(piece, MINIG_SF_ALL);
+               if(e.netname) { strunzone(e.netname); }
+               e.netname = strzone(nextpiece.netname);
+               e.snake_dir = nextpiece.snake_dir;
+               minigame_server_sendflags(e, MINIG_SF_UPDATE);
        }
 
-       // just a head
-       if(!pieces)
+       if(ate_mouse)
        {
-               tail = minigame.snake_head;
-               tailpos = minigame.snake_head.netname;
-               taildir = minigame.snake_head.snake_dir;
-       }
+               entity tail = head.snake_last;
+
+               tail.snake_tail = false;
 
-       if(tail && ate_mouse)
-       {
                int newcnt = tail.cnt + 1;
-               minigame.snake_delay = max(autocvar_sv_minigames_snake_delay_min, autocvar_sv_minigames_snake_delay_initial - (newcnt / autocvar_sv_minigames_snake_delay_multiplier));
-               snake_add_score(minigame, 1);
+               head.snake_delay = max(autocvar_sv_minigames_snake_delay_min, autocvar_sv_minigames_snake_delay_initial - (newcnt / autocvar_sv_minigames_snake_delay_multiplier));
+               snake_add_score(minigame, head.team, 1);
 
                entity piece = msle_spawn(minigame,"minigame_board_piece");
                piece.cnt = newcnt;
-               piece.team = 1;
-               piece.snake_dir = taildir;
-               piece.netname = strzone(tailpos);
-               minigame_server_sendflags(piece,MINIG_SF_ALL);
+               piece.team = head.team;
+               piece.snake_prev = tail;
+               piece.snake_dir = tail.snake_dir;
+               piece.snake_next = world;
+               piece.snake_tail = true;
+               piece.netname = strzone(tail.netname);
 
-               minigame_server_sendflags(minigame,MINIG_SF_UPDATE);
+               tail.snake_next = piece;
+               head.snake_last = piece;
+
+               minigame_server_sendflags(piece,MINIG_SF_UPDATE);
+
+               //minigame_server_sendflags(minigame,MINIG_SF_UPDATE);
        }
 }
 
-void snake_move_head(entity minigame)
+void snake_eat_team(entity minigame, int pteam)
 {
-       entity head = minigame.snake_head;
+       entity head = snake_find_head(minigame, pteam);
+       if(!head) { return; }
+
+       minigame.snake_lives[pteam] -= 1;
+
+       entity pl = snake_get_player(minigame, pteam);
+#ifdef SVQC
+       pl.SendFlags |= SNAKE_SF_PLAYERSCORE;
+#endif
+
+       head.nextthink = time + 1; // make sure they don't to eat us somehow
+
+       entity e = world;
+       while ( ( e = findentity(e,owner,minigame) ) )
+               if ( e.classname == "minigame_board_piece" && e.cnt && e.team == pteam )
+               {
+                       if(e.netname) { strunzone(e.netname); }
+                       remove(e);
+               }
+
+       if(minigame.snake_lives[pteam] <= 0)
+               minigame.snake_lost_teams |= BIT(pteam);
+
+       if(pl && minigame.snake_lives[pteam] > 0)
+               minigame_setup_snake(minigame, pteam);  
+}
+
+void snake_move_head(entity minigame, entity head)
+{
+       if(!head.snake_dir_x && !head.snake_dir_y)
+               return; // nope!
+
        string newpos;
 
        if(autocvar_sv_minigames_snake_wrap)
-               newpos = minigame_relative_tile(head.netname, minigame.snake_dir_x, minigame.snake_dir_y, SNAKE_NUM_CNT, SNAKE_LET_CNT);
+               newpos = minigame_relative_tile(head.netname, head.snake_dir_x, head.snake_dir_y, SNAKE_NUM_CNT, SNAKE_LET_CNT);
        else
        {
                int myx = minigame_tile_letter(head.netname);
                int myy = minigame_tile_number(head.netname);
 
-               myx += minigame.snake_dir_x;
-               myy += minigame.snake_dir_y;
+               myx += head.snake_dir_x;
+               myy += head.snake_dir_y;
 
                newpos = minigame_tile_buildname(myx, myy);
        }
 
-       if(!snake_valid_tile(newpos) || (snake_find_piece(minigame, newpos)).cnt)
+       entity hit = snake_find_piece(minigame, newpos);
+
+       if(!snake_valid_tile(newpos) || (hit && hit.cnt && hit.team == head.team))
        {
-               minigame.minigame_flags = SNAKE_TURN_LOSS;
-               minigame_server_sendflags(minigame,MINIG_SF_UPDATE);
+               if(snake_alone(minigame))
+               {
+                       minigame.minigame_flags = SNAKE_TURN_LOSS;
+                       minigame_server_sendflags(minigame,MINIG_SF_UPDATE);
+               }
+               else
+               {
+                       snake_add_score(minigame, head.team, -1);
+                       snake_eat_team(minigame, head.team);
+               }
+
                return;
        }
 
-       bool ate_mouse = false;
-       entity piece = snake_find_piece(minigame, newpos);
-       if(piece && !piece.cnt)
-               ate_mouse = true;
+       bool ate_mouse = (hit && !hit.cnt);
 
        // move the body first, then set the new head position?
-       snake_move_body(minigame, ate_mouse);
+       snake_move_body(minigame, head, ate_mouse);
+
+       if(head.netname) { strunzone(head.netname); }
+       head.netname = strzone(newpos);
+       minigame_server_sendflags(head,MINIG_SF_UPDATE);
+
+       // above check makes sure it's not our team
+       if(hit.cnt)
+       {
+               snake_eat_team(minigame, hit.team);
+               snake_add_score(minigame, head.team, 1);
+       }
 
        if(ate_mouse)
        {
-               if(piece.netname) { strunzone(piece.netname); }
-               remove(piece);
+               if(hit.netname) { strunzone(hit.netname); }
+               remove(hit);
 
                snake_new_mouse(minigame);
        }
-
-       if(head.netname) { strunzone(head.netname); }
-       head.netname = strzone(newpos);
-       minigame_server_sendflags(head,MINIG_SF_ALL);
 }
 
 // make a move
 void snake_move(entity minigame, entity player, string dxs, string dys )
 {
-       if ( (minigame.minigame_flags & SNAKE_TURN_MOVE) || (minigame.minigame_flags & SNAKE_TURN_WAIT) )
+       if ( minigame.minigame_flags & SNAKE_TURN_MOVE )
        if ( dxs || dys )
        {
                //if ( snake_valid_tile(pos) )
                //if ( snake_find_piece(minigame, pos) )
                {
+                       entity head = snake_find_head(minigame, player.team);
+                       if(!head)
+                               return; // their head is already dead
+
                        int dx = ((dxs) ? bound(-1, stof(dxs), 1) : 0);
                        int dy = ((dys) ? bound(-1, stof(dys), 1) : 0);
 
-                       int myl = minigame_tile_letter(minigame.snake_head.netname);
-                       int myn = minigame_tile_number(minigame.snake_head.netname);
+                       int myl = minigame_tile_letter(head.netname);
+                       int myn = minigame_tile_number(head.netname);
 
-                       entity head = snake_find_piece(minigame, minigame_tile_buildname(myl + dx, myn + dy));
-                       if(head && head.cnt == 2)
+                       entity check_piece = snake_find_piece(minigame, minigame_tile_buildname(myl + dx, myn + dy));
+                       if(check_piece && check_piece.cnt == 2)
                                return; // nope!
 
-                       if(minigame.minigame_flags & SNAKE_TURN_WAIT)
-                               minigame.snake_nextmove = time;
-                       minigame.minigame_flags = SNAKE_TURN_MOVE;
-                       minigame.snake_dir_x = dx;
-                       minigame.snake_dir_y = dy;
-                       minigame.snake_dir_z = 0;
-                       minigame.snake_head.snake_dir = minigame.snake_dir;
-                       minigame_server_sendflags(minigame.snake_head,MINIG_SF_UPDATE);
+                       if(head.snake_dir == '0 0 0')
+                               head.nextthink = time; // TODO: make sure this can't be exploited!
+                       head.snake_dir_x = dx;
+                       head.snake_dir_y = dy;
+                       head.snake_dir_z = 0;
+                       minigame_server_sendflags(head,MINIG_SF_UPDATE);
                        minigame_server_sendflags(minigame,MINIG_SF_UPDATE);
                }
        }
@@ -261,8 +405,17 @@ int snake_server_event(entity minigame, string event, ...)
                case "start":
                {
                        snake_setup_pieces(minigame);
-                       minigame.snake_delay = autocvar_sv_minigames_snake_delay_initial;
-                       minigame.minigame_flags = SNAKE_TURN_WAIT;
+                       minigame.minigame_flags = SNAKE_TURN_MOVE;
+                       minigame.snake_lost_teams = 0;
+
+                       if(SNAKE_TEAMS > 1)
+                       {
+                               for(int i = 1; i <= SNAKE_TEAMS; ++i)
+                                       minigame.snake_lives[i] = autocvar_sv_minigames_snake_lives;
+                       }
+                       else
+                               minigame.snake_lives[1] = 1;
+                       
                        return true;
                }
                case "end":
@@ -274,19 +427,39 @@ int snake_server_event(entity minigame, string event, ...)
                                if(e.netname) { strunzone(e.netname); }
                                remove(e);
                        }
-                       minigame.snake_head = world;
                        return false;
                }
                case "join":
                {
                        int pl_num = minigame_count_players(minigame);
 
-                       // Don't allow more than 1 player
-                       // not sure if this should be a multiplayer game (might get crazy)
-                       if(pl_num >= 1) { return false; }
+                       if(pl_num >= SNAKE_TEAMS) { return false; }
 
-                       // Team 1 by default
-                       return 1;
+                       int t = 1; // Team 1 by default
+
+                       for(int i = 1; i <= SNAKE_TEAMS; ++i)
+                       {
+                               entity e = snake_get_player(minigame, i);
+                               if(!e)
+                               {
+                                       t = i;
+                                       break;
+                               }
+                       }
+
+                       if(!snake_find_head(minigame, t) && !(minigame.snake_lost_teams & BIT(t)))
+                       {
+                               entity pl = ...(1,entity);
+                               if(pl)
+                               {
+                                       //pl.snake_lives = ((SNAKE_TEAMS > 1) ? autocvar_sv_minigames_snake_lives : 1);
+                                       // send score anyway, lives are set
+                                       pl.SendFlags |= SNAKE_SF_PLAYERSCORE;
+                               }
+                               minigame_setup_snake(minigame, t);
+                       }
+
+                       return t;
                }
                case "cmd":
                {
@@ -305,13 +478,26 @@ int snake_server_event(entity minigame, string event, ...)
                        int sf = ...(1,int);
                        if ( sent.classname == "minigame_board_piece" && (sf & MINIG_SF_UPDATE) )
                        {
+                               int letter = minigame_tile_letter(sent.netname);
+                               int number = minigame_tile_number(sent.netname);
+
+                               WriteByte(MSG_ENTITY,letter);
+                               WriteByte(MSG_ENTITY,number);
+
                                WriteByte(MSG_ENTITY,sent.cnt);
-                               WriteCoord(MSG_ENTITY,sent.snake_dir_x);
-                               WriteCoord(MSG_ENTITY,sent.snake_dir_y);
+                               WriteByte(MSG_ENTITY,sent.snake_tail);
+
+                               int dx = sent.snake_dir_x;
+                               int dy = sent.snake_dir_y;
+                               if(dx == -1) dx = 2;
+                               if(dy == -1) dy = 2;
+                               WriteByte(MSG_ENTITY,dx);
+                               WriteByte(MSG_ENTITY,dy);
                        }
                        else if ( sent.classname == "minigame_player" && (sf & SNAKE_SF_PLAYERSCORE ) )
                        {
                                WriteLong(MSG_ENTITY,sent.snake_score);
+                               WriteByte(MSG_ENTITY,max(0, minigame.snake_lives[sent.team]));
                        }
                        else if ( sent.classname == "minigame" && (sf & MINIG_SF_UPDATE ) )
                        {
@@ -332,6 +518,21 @@ vector snake_boardsize;// HUD board size
 
 bool snake_wrap;
 
+vector snake_teamcolor(int steam)
+{
+       switch(steam)
+       {
+               case 1: return '1 0 0';
+               case 2: return '0 0 1';
+               case 3: return '1 1 0';
+               case 4: return '1 0 1';
+               case 5: return '0 1 0';
+               case 6: return '0 1 1';
+       }
+
+       return '1 1 1';
+}
+
 // Required function, draw the game board
 void snake_hud_board(vector pos, vector mySize)
 {
@@ -344,18 +545,6 @@ void snake_hud_board(vector pos, vector mySize)
        vector tile_size = minigame_hud_denormalize_size('1 1 0' / SNAKE_TILE_SIZE,pos,mySize);
        vector tile_pos;
 
-       entity tail = world;
-       int i;
-       for(i = (SNAKE_NUM_CNT * SNAKE_LET_CNT); i >= 2; --i)
-       {
-               entity piece = snake_find_cnt(active_minigame, i);
-               if(piece)
-               {
-                       tail = piece;
-                       break;
-               }
-       }
-
        entity e;
        FOREACH_MINIGAME_ENTITY(e)
        {
@@ -363,10 +552,13 @@ void snake_hud_board(vector pos, vector mySize)
                {
                        tile_pos = minigame_tile_pos(e.netname,SNAKE_NUM_CNT,SNAKE_LET_CNT);
                        tile_pos = minigame_hud_denormalize(tile_pos,pos,mySize);
+
+                       vector tile_color = snake_teamcolor(e.team);
+
                        string thepiece = "snake/mouse";
                        if(e.cnt)
                                thepiece = "snake/body";
-                       if(tail && e.cnt == tail.cnt)
+                       if(e.snake_tail)
                                thepiece = "snake/tail";
                        if(e.cnt == 1)
                        {
@@ -374,7 +566,7 @@ void snake_hud_board(vector pos, vector mySize)
                                int dy = minigame_tile_number(e.netname) + e.snake_dir_y * 2;
                                entity mouse = snake_find_piece(active_minigame, minigame_tile_buildname(dx, dy));
                                thepiece = "snake/head";
-                               if(mouse && !mouse.cnt)
+                               if(mouse && mouse.team != e.team)
                                {
                                        float myang = 0;
                                        int myx = minigame_tile_letter(e.netname);
@@ -394,20 +586,20 @@ void snake_hud_board(vector pos, vector mySize)
                                        my_pos = minigame_hud_denormalize(my_pos,pos,mySize);
 
                                        drawrotpic(my_pos, myang, minigame_texture("snake/tongue"),
-                                                       tile_size, tile_size/2, '1 1 1',
+                                                       tile_size, tile_size/2, tile_color,
                                                        panel_fg_alpha, DRAWFLAG_NORMAL );
                                }
                        }
 
-                       if(e.cnt == 1 || e.cnt == tail.cnt)
+                       if(e.cnt == 1 || e.snake_tail)
                        {
                                vector thedir = e.snake_dir;
                                float theang = 0;
-                               if(e.cnt == tail.cnt)
+                               if(e.snake_tail)
                                {
                                        int thex = minigame_tile_letter(e.netname);
                                        int they = minigame_tile_number(e.netname);
-                                       entity t = snake_find_cnt(active_minigame, e.cnt - 1);
+                                       entity t = snake_find_cnt(active_minigame, e.team, e.cnt - 1);
                                        int tx = minigame_tile_letter(t.netname);
                                        int ty = minigame_tile_number(t.netname);
 
@@ -436,39 +628,43 @@ void snake_hud_board(vector pos, vector mySize)
                                        theang = M_PI*3/2;
 
                                drawrotpic(tile_pos, theang, minigame_texture(thepiece),
-                                                       tile_size, tile_size/2, '1 1 1',
+                                                       tile_size, tile_size/2, tile_color,
                                                        panel_fg_alpha, DRAWFLAG_NORMAL );
                        }
                        else
                        {
                                minigame_drawpic_centered( tile_pos,  
                                                minigame_texture(thepiece),
-                                               tile_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL );
+                                               tile_size, tile_color, panel_fg_alpha, DRAWFLAG_NORMAL );
                        }
                }
        }
 
-       if ( active_minigame.minigame_flags & SNAKE_TURN_LOSS )
+       if ( (active_minigame.minigame_flags & SNAKE_TURN_LOSS) || (active_minigame.minigame_flags & SNAKE_TURN_WIN) || (active_minigame.snake_lives[minigame_self.team] <= 0) )
        {
-               int scores = 0;
-               FOREACH_MINIGAME_ENTITY(e)
-                       if(e.classname == "minigame_player")
-                               scores = e.snake_score;
+               int scores = minigame_self.snake_score;
 
                vector winfs = hud_fontsize*2;
-               string scores_text;
+               string scores_text, victory_text;
+               victory_text = "Game over!";
                scores_text = strcat("Score: ", ftos(scores));
+
+               if(active_minigame.minigame_flags & SNAKE_TURN_WIN)
+               if((active_minigame.minigame_flags & SNAKE_TURN_TEAM) == minigame_self.team)
+                       victory_text = "You win!";
+               if(active_minigame.snake_lives[minigame_self.team] <= 0)
+                       victory_text = "You ran out of lives!";
                
                vector win_pos = pos+eY*(mySize_y-winfs_y)/2;
                vector win_sz;
                win_sz = minigame_drawcolorcodedstring_wrapped(mySize_x,win_pos,
-                       sprintf("Game over! %s", scores_text), 
+                       sprintf("%s %s", victory_text, scores_text), 
                        winfs, 0, DRAWFLAG_NORMAL, 0.5);
                
                drawfill(win_pos-eY*hud_fontsize_y,win_sz+2*eY*hud_fontsize_y,'0.3 0.3 1',0.8,DRAWFLAG_ADDITIVE);
                
                minigame_drawcolorcodedstring_wrapped(mySize_x,win_pos,
-                       sprintf("Game over! %s", scores_text), 
+                       sprintf("%s %s", victory_text, scores_text), 
                        winfs, panel_fg_alpha, DRAWFLAG_NORMAL, 0.5);
        }
 }
@@ -481,17 +677,19 @@ void snake_hud_status(vector pos, vector mySize)
        vector ts;
        ts = minigame_drawstring_wrapped(mySize_x,pos,active_minigame.descriptor.message,
                hud_fontsize * 2, '0.25 0.47 0.72', panel_fg_alpha, DRAWFLAG_NORMAL,0.5);
-       
+
        pos_y += ts_y;
        mySize_y -= ts_y;
-       
+
        vector player_fontsize = hud_fontsize * 1.75;
-       ts_y = ( mySize_y - 2*player_fontsize_y ) / 2;
+       ts_y = ( mySize_y - 2*player_fontsize_y ) / SNAKE_TEAMS;
        ts_x = mySize_x;
        vector mypos;
        vector tile_size = '48 48 0';
 
        mypos = pos;
+       if ( minigame_self.team > 1 )
+               mypos_y  += player_fontsize_y + (ts_y * (minigame_self.team - 1));
        drawfill(mypos,eX*mySize_x+eY*player_fontsize_y,'1 1 1',0.5,DRAWFLAG_ADDITIVE);
        mypos_y += player_fontsize_y;
        drawfill(mypos,eX*mySize_x+eY*tile_size_y,'1 1 1',0.25,DRAWFLAG_ADDITIVE);
@@ -502,19 +700,28 @@ void snake_hud_status(vector pos, vector mySize)
                if ( e.classname == "minigame_player" )
                {
                        mypos = pos;
+                       if ( e.team > 1 )
+                               mypos_y  += player_fontsize_y + (ts_y * (e.team - 1));
                        minigame_drawcolorcodedstring_trunc(mySize_x,mypos,
                                GetPlayerName(e.minigame_playerslot-1),
                                player_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
-                       
+
+                       vector tile_color = snake_teamcolor(e.team);
+
                        mypos_y += player_fontsize_y;
-                       //drawpic( mypos,  
-                       //              minigame_texture("snake/piece"),
-                       //              tile_size, '1 0 0', panel_fg_alpha, DRAWFLAG_NORMAL );
-                       
-                       //mypos_x += tile_size_x;
+                       drawpic( mypos,
+                                       minigame_texture("snake/head"),
+                                       tile_size * 0.7, tile_color, panel_fg_alpha, DRAWFLAG_NORMAL );
+
+                       mypos_x += tile_size_x;
 
                        drawstring(mypos,ftos(e.snake_score),tile_size,
                                           '0.7 0.84 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+
+                       mypos_x += tile_size_x;
+
+                       drawstring(mypos,strcat("1UP: ", ftos(active_minigame.snake_lives[e.team])),tile_size * 0.6,
+                                                        '0.7 0.84 1', panel_fg_alpha, DRAWFLAG_NORMAL);
                }
        }
 }
@@ -524,8 +731,18 @@ string snake_turn_to_string(int turnflags)
 {
        if ( turnflags & SNAKE_TURN_LOSS )
                return _("Game over!");
+
+       if ( turnflags & SNAKE_TURN_WIN )
+       {
+               if ( (turnflags&SNAKE_TURN_TEAM) != minigame_self.team )
+                       return _("You ran out of lives!");
+               return _("You win!");
+       }
+
+       if(active_minigame.snake_lives[minigame_self.team] <= 0)
+               return _("You ran out of lives!");
        
-       if ( turnflags & SNAKE_TURN_WAIT )
+       if ( (snake_find_head(active_minigame, minigame_self.team)).snake_dir == '0 0 0' )
                return _("Press an arrow key to begin the game");
 
        if ( turnflags & SNAKE_TURN_MOVE )
@@ -601,17 +818,29 @@ int snake_client_event(entity minigame, string event, ...)
                        {
                                if(sf & MINIG_SF_UPDATE)
                                {
+                                       int letter = ReadByte();
+                                       int number = ReadByte();
+                                       if(sent.netname) { strunzone(sent.netname); }
+                                       sent.netname = strzone(minigame_tile_buildname(letter, number));
+
                                        sent.cnt = ReadByte();
-                                       sent.snake_dir_x = ReadCoord();
-                                       sent.snake_dir_y = ReadCoord();
+                                       sent.snake_tail = ReadByte();
+
+                                       int dx = ReadByte();
+                                       int dy = ReadByte();
+
+                                       if(dx == 2) dx = -1;
+                                       if(dy == 2) dy = -1;
+
+                                       sent.snake_dir_x = dx;
+                                       sent.snake_dir_y = dy;
                                        sent.snake_dir_z = 0;
-                                       if(sent.cnt == 1)
-                                               minigame.snake_head = sent; // hax
                                }
                        }
                        else if ( sent.classname == "minigame_player" && (sf & SNAKE_SF_PLAYERSCORE ) )
                        {
                                sent.snake_score = ReadLong();
+                               minigame.snake_lives[sent.team] = ReadByte();
                        }
 
                        return false;
index 0f02e2b5819407d14f3b705df99a8aa2f86d8704..56d0ece1a2a3c944812642e0c0f9dc889b276ab0 100644 (file)
@@ -131,12 +131,11 @@ int minigame_addplayer(entity minigame_session, entity player)
                        return 0;
                minigame_rmplayer(player.active_minigame,player);
        }
-
-       int mgteam = minigame_session.minigame_event(minigame_session,"join",player);
+       entity player_pointer = spawn();
+       int mgteam = minigame_session.minigame_event(minigame_session,"join",player,player_pointer);
 
        if ( mgteam )
        {
-               entity player_pointer = spawn();
                player_pointer.classname = "minigame_player";
                player_pointer.owner = minigame_session;
                player_pointer.minigame_players = player;
@@ -157,6 +156,7 @@ int minigame_addplayer(entity minigame_session, entity player)
 
                minigame_resend(minigame_session);
        }
+       else { remove(player_pointer); }
        GameLogEcho(strcat(":minigame:join",(mgteam?"":"fail"),":",minigame_session.netname,":",
                ftos(num_for_edict(player)),":",player.netname));
 
index 38c533449847ec6105d3d6fc9277f12e7564c062..a7ab9088079f8914e35f12d8bddb7be67a9b6d0b 100644 (file)
@@ -1,30 +1,11 @@
 #ifndef MODELS_ALL_H
 #define MODELS_ALL_H
 
-#define setmodel(e, m) _setmodel((e), (m).model_str())
+#include "model.qh"
 
 REGISTRY(Models, BIT(9))
 REGISTER_REGISTRY(RegisterModels)
 
-CLASS(Model, Object)
-    ATTRIB(Model, m_id, int, 0)
-    ATTRIB(Model, model_str, string(), func_null)
-    CONSTRUCTOR(Model, string() path)
-    {
-        CONSTRUCT(Model);
-        this.model_str = path;
-    }
-    METHOD(Model, model_precache, void(entity this)) {
-        string s = this.model_str();
-        if (s != "" && s != "null" && !fexists(s)) {
-            LOG_WARNINGF("Missing model: \"%s\"\n", s);
-            return;
-        }
-        LOG_TRACEF("precache_model(\"%s\")\n", s);
-        precache_model(s);
-    }
-ENDCLASS(Model)
-
 #define MODEL(name, path) \
     string MDL_##name##_get() { return path; } \
     REGISTER(RegisterModels, MDL, Models, name, m_id, NEW(Model, MDL_##name##_get))
diff --git a/qcsrc/common/models/model.qh b/qcsrc/common/models/model.qh
new file mode 100644 (file)
index 0000000..b4005b7
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef MODEL_H
+#define MODEL_H
+
+#define setmodel(e, m) _setmodel((e), (m).model_str())
+
+CLASS(Model, Object)
+    ATTRIB(Model, m_id, int, 0)
+    ATTRIB(Model, model_str, string(), func_null)
+    CONSTRUCTOR(Model, string() path)
+    {
+        CONSTRUCT(Model);
+        this.model_str = path;
+    }
+    METHOD(Model, model_precache, void(entity this)) {
+        string s = this.model_str();
+        if (s != "" && s != "null" && !fexists(s)) {
+            LOG_WARNINGF("Missing model: \"%s\"\n", s);
+            return;
+        }
+        LOG_TRACEF("precache_model(\"%s\")\n", s);
+        precache_model(s);
+    }
+ENDCLASS(Model)
+
+#endif
index 0a78b7772292bbb884b9fce938b6a5b384375c0c..b4559269d71a004247b1b5b4fb20d6dce75d195b 100644 (file)
@@ -1,6 +1,17 @@
 #ifndef MONSTER_H
 #define MONSTER_H
 
+#ifdef SVQC
+#include "sv_monsters.qh"
+#include "../../server/g_damage.qh"
+#include "../../server/bot/bot.qh"
+#include "../../server/weapons/common.qh"
+#include "../../server/weapons/tracing.qh"
+#include "../../server/weapons/weaponsystem.qh"
+#include "../mutators/mutator/waypoints/waypointsprites.qh"
+#include "../../lib/warpzone/server.qh"
+#endif
+
 // special spawn flags
 const int MONSTER_RESPAWN_DEATHPOINT = 16; // re-spawn where we died
 const int MONSTER_TYPE_FLY = 32;
index 356b47dbc41bf5b815f741386d43d7a81c38a4fc..7388ee66f5bce70ddc448466967f302ce79b488c 100644 (file)
@@ -23,6 +23,7 @@ REGISTER_MONSTER(MAGE, NEW(Mage)) {
 }
 
 #include "../../weapons/all.qh"
+#include "../../items/all.qc"
 
 CLASS(MageSpike, PortoLaunch)
 /* flags     */ ATTRIB(MageSpike, spawnflags, int, WEP_TYPE_OTHER | WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
@@ -162,6 +163,8 @@ void M_Mage_Attack_Spike_Touch()
        M_Mage_Attack_Spike_Explode();
 }
 
+.float wait;
+
 // copied from W_Seeker_Think
 void M_Mage_Attack_Spike_Think()
 {SELFPARAM();
@@ -460,6 +463,8 @@ spawnfunc(monster_mage) { Monster_Spawn(MON_MAGE.monsterid); }
                }
                #endif
                #ifdef SVQC
+               .float speed;
+               spawnfunc(item_health_large);
                METHOD(Mage, mr_setup, bool(Monster thismon))
                {
                        SELFPARAM();
index 8a84eeec39e721141a5da3969d8d32bba477d43b..203b597cc0da2b7ee99d19ce40536f753e84506b 100644 (file)
@@ -82,6 +82,8 @@ void M_Shambler_Attack_Swing()
        }
 }
 
+#include "../../../server/csqceffects.qh"
+
 void M_Shambler_Attack_Lightning_Explode()
 {SELFPARAM();
        entity head;
@@ -179,6 +181,8 @@ void M_Shambler_Attack_Lightning()
        CSQCProjectile(gren, true, PROJECTILE_SHAMBLER_LIGHTNING, true);
 }
 
+.int state;
+
 float M_Shambler_Attack(float attack_type, entity targ)
 {SELFPARAM();
        switch(attack_type)
@@ -263,6 +267,8 @@ spawnfunc(monster_shambler) { Monster_Spawn(MON_SHAMBLER.monsterid); }
                }
                #endif
                #ifdef SVQC
+               spawnfunc(item_health_mega);
+               .float animstate_endtime;
                METHOD(Shambler, mr_setup, bool(Shambler thismon))
                {
                        SELFPARAM();
index c8daa037e9b2ccd7e7642189dbfc7644d1a2910f..208ae107993480edc0c4c2d3c90d2e4d13323955 100644 (file)
@@ -113,6 +113,8 @@ void M_Spider_Attack_Web_Touch()
        M_Spider_Attack_Web_Explode();
 }
 
+void adaptor_think2use_hittype_splash();
+
 void M_Spider_Attack_Web()
 {SELFPARAM();
        monster_makevectors(self.enemy);
@@ -206,6 +208,7 @@ spawnfunc(monster_spider) { Monster_Spawn(MON_SPIDER.monsterid); }
                }
                #endif
                #ifdef SVQC
+               spawnfunc(item_health_medium);
                METHOD(Spider, mr_setup, bool(Spider thismon))
                {
                        SELFPARAM();
index d709e4514e9645fd79a165faa79fcf7a2205cab6..ac9f32205dae432e9104065d29957df55dd7debd 100644 (file)
@@ -177,6 +177,7 @@ spawnfunc(monster_wyvern) { Monster_Spawn(MON_WYVERN.monsterid); }
                }
                #endif
                #ifdef SVQC
+               spawnfunc(item_cells);
                METHOD(Wyvern, mr_setup, bool(Wyvern thismon))
                {
                        SELFPARAM();
index ef9aa06cb009df05b57891b7c7c49c129353484a..e68b7ff5424334b8c979f2c8b6141e2321cda032 100644 (file)
@@ -73,6 +73,8 @@ const float zombie_anim_runforwardright               = 29;
 const float zombie_anim_spawn                          = 30;
 */
 
+.vector moveto;
+
 void M_Zombie_Attack_Leap_Touch()
 {SELFPARAM();
        if (self.health <= 0)
index cf23639e015b5276ee781229f98e0af1674c9d8a..f7e2e292fbf669f6fed88a2e5677288c4af04fbc 100644 (file)
@@ -1,7 +1,6 @@
 #if defined(CSQC)
 #elif defined(MENUQC)
 #elif defined(SVQC)
-       #include "../../dpdefs/progsdefs.qh"
     #include "../util.qh"
     #include "all.qh"
     #include "sv_monsters.qh"
index 940b30f008cc407034af45d70c44108d42f1d4e0..1155c6427108eb51320c3c382e3789d3e2b52683 100644 (file)
@@ -1,9 +1,7 @@
 #if defined(CSQC)
 #elif defined(MENUQC)
 #elif defined(SVQC)
-       #include "../../dpdefs/progsdefs.qh"
-    #include "../../dpdefs/dpextensions.qh"
-    #include "../../warpzonelib/common.qh"
+    #include "../../lib/warpzone/common.qh"
     #include "../constants.qh"
     #include "../teams.qh"
     #include "../util.qh"
@@ -22,7 +20,7 @@
     #include "../../server/command/common.qh"
     #include "../../server/command/cmd.qh"
        #include "../triggers/triggers.qh"
-    #include "../../csqcmodellib/sv_model.qh"
+    #include "../../lib/csqcmodel/sv_model.qh"
     #include "../../server/round_handler.qh"
 #endif
 
index d1d224363d314dc52e59199c3f794c7e34b60830..acf94eb7d78ad9f35b80ed1d9777cc0292889439 100644 (file)
@@ -94,6 +94,9 @@ void monster_makevectors(entity e);
 
 void Monster_Sound(.string samplefield, float sound_delay, float delaytoo, float chan);
 
+/** number of monsters spawned with mobspawn command */
+int totalspawned;
+
 // monster sounds
 .float msound_delay; // temporary antilag system
 #define ALLMONSTERSOUNDS \
index cfa6346dc44178904f2003208d28e4a63198bb1e..8c96174f2316c7ff0955f47bb217c022e4cf2cb8 100644 (file)
@@ -2,12 +2,11 @@
 #include "../physics.qh"
 
 #if defined(CSQC)
-       #include "../../dpdefs/csprogsdefs.qh"
        #include "../../client/defs.qh"
        #include "../stats.qh"
        #include "../util.qh"
        #include "movetypes.qh"
-       #include "../../csqcmodellib/common.qh"
+       #include "../../lib/csqcmodel/common.qh"
        #include "../../server/t_items.qh"
 #elif defined(MENUQC)
 #elif defined(SVQC)
index 1d02fc371e912663710b97887f500119365a0bfd..6b19a0bc6eb2043ab937335f731b675f8c91e24d 100644 (file)
@@ -1,4 +1,5 @@
 #include "mutator/casings.qc"
 #include "mutator/damagetext.qc"
+#include "mutator/instagib/instagib.qc"
 #include "mutator/itemstime.qc"
 #include "mutator/waypoints/waypointsprites.qc"
index 14530a3c5ef99aa0054ee93aacf421f6bd0e4a70..f0fc7195a84b244c691a67a2830b093d9a374618 100644 (file)
@@ -1 +1,5 @@
+#include "all.qh"
+
+#define IMPLEMENTATION
 #include "all.inc"
+#undef IMPLEMENTATION
diff --git a/qcsrc/common/mutators/all.qh b/qcsrc/common/mutators/all.qh
new file mode 100644 (file)
index 0000000..ceb4b51
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef MUTATORS_ALL_H
+#define MUTATORS_ALL_H
+
+#include "all.inc"
+
+#endif
index 9a535a2960a35703cc16d7517114db24de675ce2..f6fa534d6164a36c6fab9b8897e8ce4693104140 100644 (file)
@@ -155,7 +155,7 @@ CLASS(Mutator, Object)
     }
 ENDCLASS(Mutator)
 
-const int MAX_MUTATORS = 20;
+const int MAX_MUTATORS = 30;
 Mutator loaded_mutators[MAX_MUTATORS];
 
 bool Mutator_Add(Mutator mut)
@@ -265,7 +265,7 @@ STATIC_INIT_LATE(Mutators) {
 #define MUTATOR_HOOK(cb, func, order) do {                              \
     MUTATOR_ONADD {                                                     \
         if (!CallbackChain_Add(HOOK_##cb, CALLBACK_##func, order)) {    \
-            LOG_INFO("HOOK FAILED: ", #cb, ":", #func, "\n");              \
+            LOG_INFO("HOOK FAILED: ", #cb, ":", #func, "\n");           \
             return true;                                                \
         }                                                               \
     }                                                                   \
index 9ed5fefa7ac5b85b6eaeea351324e44acc7648a2..fe945c9ea050ba3131bdfa5058f18089a2242739 100644 (file)
@@ -1,3 +1,5 @@
+#ifdef IMPLEMENTATION
+
 #include "../../util.qh"
 
 #ifdef CSQC
@@ -175,3 +177,4 @@ MUTATOR_HOOKFUNCTION(casings, CSQC_Parse_TempEntity)
 }
 
 #endif
+#endif
index e4e4be5e8792eaafacd152d1db9546c99c4b0115..d1f513a4b839b12ef86f4c3330185b396208db66 100644 (file)
@@ -1,3 +1,13 @@
+#ifndef MUTATOR_DAMAGETEXT_H
+#define MUTATOR_DAMAGETEXT_H
+
+#ifdef MENUQC
+#include "../../../menu/xonotic/tab.qc"
+#endif
+
+#endif
+
+#ifdef IMPLEMENTATION
 REGISTER_MUTATOR(damagetext, true);
 
 #if defined(CSQC) || defined(MENUQC)
@@ -111,7 +121,6 @@ MUTATOR_HOOKFUNCTION(damagetext, CSQC_Parse_TempEntity) {
 #endif
 
 #ifdef MENUQC
-#include "../../../menu/xonotic/tab.qc"
 CLASS(XonoticDamageTextSettings, XonoticTab)
     #include "../../../menu/gamesettings.qh"
     REGISTER_SETTINGS(damagetext, NEW(XonoticDamageTextSettings));
@@ -140,3 +149,4 @@ CLASS(XonoticDamageTextSettings, XonoticTab)
     }
 ENDCLASS(XonoticDamageTextSettings)
 #endif
+#endif
diff --git a/qcsrc/common/mutators/mutator/instagib/instagib.qc b/qcsrc/common/mutators/mutator/instagib/instagib.qc
new file mode 100644 (file)
index 0000000..2acb183
--- /dev/null
@@ -0,0 +1,480 @@
+#ifndef MUTATOR_INSTAGIB_H
+#define MUTATOR_INSTAGIB_H
+
+#include "items.qc"
+
+#endif
+
+#ifdef IMPLEMENTATION
+#ifdef SVQC
+
+#include "../../../../server/cl_client.qh"
+#include "../../../buffs/all.qh"
+
+#include "../../../items/all.qc"
+
+REGISTER_MUTATOR(mutator_instagib, cvar("g_instagib") && !g_nexball);
+
+spawnfunc(item_minst_cells)
+{
+       if (!g_instagib) { remove(self); return; }
+       if (!self.ammo_cells) self.ammo_cells = autocvar_g_instagib_ammo_drop;
+       StartItemA(ITEM_VaporizerCells);
+}
+
+void instagib_invisibility()
+{SELFPARAM();
+       self.strength_finished = autocvar_g_balance_powerup_strength_time;
+       StartItemA(ITEM_Invisibility);
+}
+
+void instagib_extralife()
+{SELFPARAM();
+       self.max_health = 1;
+       StartItemA(ITEM_ExtraLife);
+}
+
+void instagib_speed()
+{SELFPARAM();
+       self.invincible_finished = autocvar_g_balance_powerup_invincible_time;
+       StartItemA(ITEM_Speed);
+}
+
+.float instagib_nextthink;
+.float instagib_needammo;
+void instagib_stop_countdown(entity e)
+{
+       if (!e.instagib_needammo)
+               return;
+       Kill_Notification(NOTIF_ONE_ONLY, e, MSG_CENTER_CPID, CPID_INSTAGIB_FINDAMMO);
+       e.instagib_needammo = false;
+}
+void instagib_ammocheck()
+{SELFPARAM();
+       if(time < self.instagib_nextthink)
+               return;
+       if(!IS_PLAYER(self))
+               return; // not a player
+
+       if(self.deadflag || gameover)
+               instagib_stop_countdown(self);
+       else if (self.ammo_cells > 0 || (self.items & IT_UNLIMITED_WEAPON_AMMO) || (self.flags & FL_GODMODE))
+               instagib_stop_countdown(self);
+       else if(autocvar_g_rm && autocvar_g_rm_laser)
+       {
+               if(!self.instagib_needammo)
+               {
+                       Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_INSTAGIB_DOWNGRADE);
+                       self.instagib_needammo = true;
+               }
+       }
+       else
+       {
+               self.instagib_needammo = true;
+               if (self.health <= 5)
+               {
+                       Damage(self, self, self, 5, DEATH_NOAMMO.m_id, self.origin, '0 0 0');
+                       Send_Notification(NOTIF_ONE, self, MSG_ANNCE, ANNCE_INSTAGIB_TERMINATED);
+               }
+               else if (self.health <= 10)
+               {
+                       Damage(self, self, self, 5, DEATH_NOAMMO.m_id, self.origin, '0 0 0');
+                       Send_Notification(NOTIF_ONE, self, MSG_ANNCE, ANNCE_NUM_1);
+               }
+               else if (self.health <= 20)
+               {
+                       Damage(self, self, self, 10, DEATH_NOAMMO.m_id, self.origin, '0 0 0');
+                       Send_Notification(NOTIF_ONE, self, MSG_ANNCE, ANNCE_NUM_2);
+               }
+               else if (self.health <= 30)
+               {
+                       Damage(self, self, self, 10, DEATH_NOAMMO.m_id, self.origin, '0 0 0');
+                       Send_Notification(NOTIF_ONE, self, MSG_ANNCE, ANNCE_NUM_3);
+               }
+               else if (self.health <= 40)
+               {
+                       Damage(self, self, self, 10, DEATH_NOAMMO.m_id, self.origin, '0 0 0');
+                       Send_Notification(NOTIF_ONE, self, MSG_ANNCE, ANNCE_NUM_4);
+               }
+               else if (self.health <= 50)
+               {
+                       Damage(self, self, self, 10, DEATH_NOAMMO.m_id, self.origin, '0 0 0');
+                       Send_Notification(NOTIF_ONE, self, MSG_ANNCE, ANNCE_NUM_5);
+               }
+               else if (self.health <= 60)
+               {
+                       Damage(self, self, self, 10, DEATH_NOAMMO.m_id, self.origin, '0 0 0');
+                       Send_Notification(NOTIF_ONE, self, MSG_ANNCE, ANNCE_NUM_6);
+               }
+               else if (self.health <= 70)
+               {
+                       Damage(self, self, self, 10, DEATH_NOAMMO.m_id, self.origin, '0 0 0');
+                       Send_Notification(NOTIF_ONE, self, MSG_ANNCE, ANNCE_NUM_7);
+               }
+               else if (self.health <= 80)
+               {
+                       Damage(self, self, self, 10, DEATH_NOAMMO.m_id, self.origin, '0 0 0');
+                       Send_Notification(NOTIF_ONE, self, MSG_ANNCE, ANNCE_NUM_8);
+               }
+               else if (self.health <= 90)
+               {
+                       Send_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER, CENTER_INSTAGIB_FINDAMMO);
+                       Damage(self, self, self, 10, DEATH_NOAMMO.m_id, self.origin, '0 0 0');
+                       Send_Notification(NOTIF_ONE, self, MSG_ANNCE, ANNCE_NUM_9);
+               }
+               else
+               {
+                       Send_Notification(NOTIF_ONE_ONLY, self, MSG_MULTI, MULTI_INSTAGIB_FINDAMMO);
+                       Damage(self, self, self, 10, DEATH_NOAMMO.m_id, self.origin, '0 0 0');
+               }
+       }
+       self.instagib_nextthink = time + 1;
+}
+
+MUTATOR_HOOKFUNCTION(mutator_instagib, MatchEnd)
+{
+       entity head;
+       FOR_EACH_PLAYER(head)
+               instagib_stop_countdown(head);
+
+       return false;
+}
+
+MUTATOR_HOOKFUNCTION(mutator_instagib, MonsterDropItem)
+{
+       other.monster_loot = spawnfunc_item_minst_cells;
+
+       return false;
+}
+
+MUTATOR_HOOKFUNCTION(mutator_instagib, MonsterSpawn)
+{SELFPARAM();
+       // always refill ammo
+       if(self.monsterid == MON_MAGE.monsterid)
+               self.skin = 1;
+
+       return false;
+}
+
+MUTATOR_HOOKFUNCTION(mutator_instagib, BotShouldAttack)
+{
+       if (checkentity.items & ITEM_Invisibility.m_itemid)
+               return true;
+
+       return false;
+}
+
+MUTATOR_HOOKFUNCTION(mutator_instagib, MakePlayerObserver)
+{SELFPARAM();
+       instagib_stop_countdown(self);
+       return false;
+}
+
+MUTATOR_HOOKFUNCTION(mutator_instagib, PlayerSpawn)
+{SELFPARAM();
+       self.effects |= EF_FULLBRIGHT;
+       return false;
+}
+
+MUTATOR_HOOKFUNCTION(mutator_instagib, PlayerPreThink)
+{
+       instagib_ammocheck();
+       return false;
+}
+
+MUTATOR_HOOKFUNCTION(mutator_instagib, PlayerRegen)
+{
+       // no regeneration in instagib
+       return true;
+}
+
+MUTATOR_HOOKFUNCTION(mutator_instagib, PlayerPowerups)
+{SELFPARAM();
+       if (!(self.effects & EF_FULLBRIGHT))
+               self.effects |= EF_FULLBRIGHT;
+
+       if (self.items & ITEM_Invisibility.m_itemid)
+       {
+               play_countdown(self.strength_finished, SND(POWEROFF));
+               if (time > self.strength_finished)
+               {
+                       self.alpha = default_player_alpha;
+                       self.exteriorweaponentity.alpha = default_weapon_alpha;
+                       self.items &= ~ITEM_Invisibility.m_itemid;
+                       Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_POWERDOWN_INVISIBILITY);
+               }
+       }
+       else
+       {
+               if (time < self.strength_finished)
+               {
+                       self.alpha = autocvar_g_instagib_invis_alpha;
+                       self.exteriorweaponentity.alpha = autocvar_g_instagib_invis_alpha;
+                       self.items |= ITEM_Invisibility.m_itemid;
+                       Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_POWERUP_INVISIBILITY, self.netname);
+                       Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_POWERUP_INVISIBILITY);
+               }
+       }
+
+       if (self.items & ITEM_Speed.m_itemid)
+       {
+               play_countdown(self.invincible_finished, SND(POWEROFF));
+               if (time > self.invincible_finished)
+               {
+                       self.items &= ~ITEM_Speed.m_itemid;
+                       Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_POWERDOWN_SPEED);
+               }
+       }
+       else
+       {
+               if (time < self.invincible_finished)
+               {
+                       self.items |= ITEM_Speed.m_itemid;
+                       Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_POWERUP_SPEED, self.netname);
+                       Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_POWERUP_SPEED);
+               }
+       }
+       return false;
+}
+
+.float stat_sv_maxspeed;
+
+MUTATOR_HOOKFUNCTION(mutator_instagib, PlayerPhysics)
+{SELFPARAM();
+       if(self.items & ITEM_Speed.m_itemid)
+               self.stat_sv_maxspeed = self.stat_sv_maxspeed * autocvar_g_instagib_speed_highspeed;
+
+       return false;
+}
+
+MUTATOR_HOOKFUNCTION(mutator_instagib, PlayerDamage_SplitHealthArmor)
+{
+       damage_save = 0;
+       damage_take = frag_damage;
+
+       return false;
+}
+
+MUTATOR_HOOKFUNCTION(mutator_instagib, ForbidThrowCurrentWeapon)
+{
+       // weapon dropping on death handled by FilterItem
+
+       return true;
+}
+
+MUTATOR_HOOKFUNCTION(mutator_instagib, PlayerDamage_Calculate)
+{
+       if(autocvar_g_friendlyfire == 0 && SAME_TEAM(frag_target, frag_attacker) && IS_PLAYER(frag_target) && IS_PLAYER(frag_attacker))
+               frag_damage = 0;
+
+       if(IS_PLAYER(frag_target))
+       {
+               if(frag_deathtype == DEATH_FALL.m_id)
+                       frag_damage = 0; // never count fall damage
+
+               if(!autocvar_g_instagib_damagedbycontents)
+               switch(DEATH_ENT(frag_deathtype))
+               {
+                       case DEATH_DROWN:
+                       case DEATH_SLIME:
+                       case DEATH_LAVA:
+                               frag_damage = 0;
+                               break;
+               }
+
+               if(IS_PLAYER(frag_attacker))
+               if(DEATH_ISWEAPON(frag_deathtype, WEP_VAPORIZER))
+               {
+                       if(frag_target.armorvalue)
+                       {
+                               frag_target.armorvalue -= 1;
+                               frag_damage = 0;
+                               frag_target.damage_dealt += 1;
+                               frag_attacker.damage_dealt += 1; // TODO: change this to a specific hitsound for armor hit
+                               Send_Notification(NOTIF_ONE, frag_target, MSG_CENTER, CENTER_INSTAGIB_LIVES_REMAINING, frag_target.armorvalue);
+                       }
+               }
+
+               if(IS_PLAYER(frag_attacker) && DEATH_ISWEAPON(frag_deathtype, WEP_BLASTER))
+               {
+                       if(frag_deathtype & HITTYPE_SECONDARY)
+                       {
+                               if(!autocvar_g_instagib_blaster_keepdamage)
+                                       frag_damage = frag_mirrordamage = 0;
+
+                               if(frag_target != frag_attacker)
+                               {
+                                       if(frag_damage <= 0 && frag_target.health > 0) { Send_Notification(NOTIF_ONE, frag_attacker, MSG_CENTER, CENTER_SECONDARY_NODAMAGE); }
+                                       if(!autocvar_g_instagib_blaster_keepforce)
+                                               frag_force = '0 0 0';
+                               }
+                       }
+               }
+       }
+
+       if(IS_PLAYER(frag_attacker))
+       if(frag_mirrordamage > 0)
+       {
+               // just lose extra LIVES, don't kill the player for mirror damage
+               if(frag_attacker.armorvalue > 0)
+               {
+                       frag_attacker.armorvalue -= 1;
+                       Send_Notification(NOTIF_ONE, frag_attacker, MSG_CENTER, CENTER_INSTAGIB_LIVES_REMAINING, frag_attacker.armorvalue);
+                       frag_attacker.damage_dealt += frag_mirrordamage;
+               }
+               frag_mirrordamage = 0;
+       }
+
+       if((frag_target.buffs & BUFF_INVISIBLE.m_itemid) || (frag_target.items & ITEM_Invisibility.m_itemid))
+               yoda = 1;
+
+       return false;
+}
+
+MUTATOR_HOOKFUNCTION(mutator_instagib, SetStartItems)
+{
+       start_health       = warmup_start_health       = 100;
+       start_armorvalue   = warmup_start_armorvalue   = 0;
+
+       start_ammo_shells  = warmup_start_ammo_shells  = 0;
+       start_ammo_nails   = warmup_start_ammo_nails   = 0;
+       start_ammo_cells   = warmup_start_ammo_cells   = cvar("g_instagib_ammo_start");
+       start_ammo_plasma  = warmup_start_ammo_plasma  = 0;
+       start_ammo_rockets = warmup_start_ammo_rockets = 0;
+       start_ammo_fuel    = warmup_start_ammo_fuel    = 0;
+
+       start_weapons = warmup_start_weapons = WEPSET(VAPORIZER);
+       start_items |= IT_UNLIMITED_SUPERWEAPONS;
+
+       return false;
+}
+
+MUTATOR_HOOKFUNCTION(mutator_instagib, FilterItem)
+{SELFPARAM();
+       if(self.classname == "item_cells")
+               return true; // no normal cells?
+
+       if(self.weapon == WEP_VAPORIZER.m_id && self.classname == "droppedweapon")
+       {
+               self.ammo_cells = autocvar_g_instagib_ammo_drop;
+               return false;
+       }
+
+       if(self.weapon == WEP_DEVASTATOR.m_id || self.weapon == WEP_VORTEX.m_id)
+       {
+               entity e = spawn();
+               setorigin(e, self.origin);
+               e.noalign = self.noalign;
+        e.cnt = self.cnt;
+        e.team = self.team;
+               WITH(entity, self, e, spawnfunc_item_minst_cells(e));
+               return true;
+       }
+
+       if(self.flags & FL_POWERUP)
+               return false;
+
+       if(self.ammo_cells > autocvar_g_instagib_ammo_drop && self.classname != "item_minst_cells")
+               self.ammo_cells = autocvar_g_instagib_ammo_drop;
+
+       if(self.ammo_cells && !self.weapon)
+               return false;
+
+       return true;
+}
+
+MUTATOR_HOOKFUNCTION(mutator_instagib, CustomizeWaypoint)
+{SELFPARAM();
+       entity e = WaypointSprite_getviewentity(other);
+
+       // if you have the invisibility powerup, sprites ALWAYS are restricted to your team
+       // but only apply this to real players, not to spectators
+       if((self.owner.flags & FL_CLIENT) && (self.owner.items & ITEM_Invisibility.m_itemid) && (e == other))
+       if(DIFF_TEAM(self.owner, e))
+               return true;
+
+       return false;
+}
+
+MUTATOR_HOOKFUNCTION(mutator_instagib, PlayerDies)
+{
+       if(DEATH_ISWEAPON(frag_deathtype, WEP_VAPORIZER))
+               frag_damage = 1000; // always gib if it was a vaporizer death
+
+       return FALSE;
+}
+
+MUTATOR_HOOKFUNCTION(mutator_instagib, ItemTouch)
+{SELFPARAM();
+       if(self.ammo_cells)
+       {
+               // play some cool sounds ;)
+               if (IS_CLIENT(other))
+               {
+                       if(other.health <= 5)
+                               Send_Notification(NOTIF_ONE, other, MSG_ANNCE, ANNCE_INSTAGIB_LASTSECOND);
+                       else if(other.health < 50)
+                               Send_Notification(NOTIF_ONE, other, MSG_ANNCE, ANNCE_INSTAGIB_NARROWLY);
+               }
+
+               if(other.health < 100)
+                       other.health = 100;
+
+               return MUT_ITEMTOUCH_CONTINUE;
+       }
+
+       if(self.max_health)
+       {
+               other.armorvalue = bound(other.armorvalue, 999, other.armorvalue + autocvar_g_instagib_extralives);
+               Send_Notification(NOTIF_ONE, other, MSG_CENTER, CENTER_EXTRALIVES);
+               return MUT_ITEMTOUCH_PICKUP;
+       }
+
+       return MUT_ITEMTOUCH_CONTINUE;
+}
+
+MUTATOR_HOOKFUNCTION(mutator_instagib, OnEntityPreSpawn)
+{SELFPARAM();
+       if (!autocvar_g_powerups) { return false; }
+       // Can't use .itemdef here
+       if (!(self.classname == "item_strength" || self.classname == "item_invincible" || self.classname == "item_health_mega"))
+               return false;
+
+       entity e = spawn();
+
+       float r = random();
+       if (r < 0.3)
+               e.think = instagib_invisibility;
+       else if (r < 0.6)
+               e.think = instagib_extralife;
+       else
+               e.think = instagib_speed;
+
+       e.nextthink = time + 0.1;
+       e.spawnflags = self.spawnflags;
+       e.noalign = self.noalign;
+       setorigin(e, self.origin);
+
+       return true;
+}
+
+MUTATOR_HOOKFUNCTION(mutator_instagib, BuildMutatorsString)
+{
+       ret_string = strcat(ret_string, ":instagib");
+       return false;
+}
+
+MUTATOR_HOOKFUNCTION(mutator_instagib, BuildMutatorsPrettyString)
+{
+       ret_string = strcat(ret_string, ", instagib");
+       return false;
+}
+
+MUTATOR_HOOKFUNCTION(mutator_instagib, SetModname)
+{
+       modname = "instagib";
+       return true;
+}
+
+#endif
+#endif
diff --git a/qcsrc/common/mutators/mutator/instagib/items.qc b/qcsrc/common/mutators/mutator/instagib/items.qc
new file mode 100644 (file)
index 0000000..2d804f7
--- /dev/null
@@ -0,0 +1,78 @@
+#include "../../../items/all.qh"
+#include "../../../items/item/ammo.qh"
+#include "../../../items/item/powerup.qh"
+
+float instagib_respawntime_ammo = 45;
+float instagib_respawntimejitter_ammo = 0;
+GETTER(float, instagib_respawntime_ammo)
+GETTER(float, instagib_respawntimejitter_ammo)
+
+#ifndef MENUQC
+MODEL(VaporizerCells_ITEM, Item_Model("a_cells.md3"));
+#endif
+
+REGISTER_ITEM(VaporizerCells, Ammo) {
+#ifndef MENUQC
+    this.m_model                =   MDL_VaporizerCells_ITEM;
+#endif
+    this.m_sound                =   "misc/itempickup.wav";
+    this.m_name                 =   "Vaporizer Ammo";
+    this.m_icon                 =   "ammo_supercells";
+#ifdef SVQC
+    this.m_botvalue             =   100;
+    this.m_itemid               =   IT_CELLS;
+    this.m_respawntime          =   GET(instagib_respawntime_ammo);
+    this.m_respawntimejitter    =   GET(instagib_respawntimejitter_ammo);
+#endif
+}
+
+#ifndef MENUQC
+MODEL(ExtraLife_ITEM, Item_Model("g_h100.md3"));
+#endif
+
+REGISTER_ITEM(ExtraLife, Powerup) {
+#ifndef MENUQC
+    this.m_model                =   MDL_ExtraLife_ITEM;
+#endif
+    this.m_sound                =   "misc/megahealth.wav";
+    this.m_name                 =   "Extra life";
+    this.m_icon                 =   "item_mega_health";
+    this.m_color                =   '1 0 0';
+    this.m_waypoint             =   _("Extra life");
+    this.m_waypointblink        =   2;
+    this.m_itemid               =   IT_NAILS;
+}
+
+#ifndef MENUQC
+MODEL(Invisibility_ITEM, Item_Model("g_strength.md3"));
+#endif
+
+REGISTER_ITEM(Invisibility, Powerup) {
+#ifndef MENUQC
+    this.m_model            =   MDL_Invisibility_ITEM;
+#endif
+    this.m_sound            =   "misc/powerup.wav";
+    this.m_name             =   "Invisibility";
+    this.m_icon             =   "strength";
+    this.m_color            =   '0 0 1';
+    this.m_waypoint         =   _("Invisibility");
+    this.m_waypointblink    =   2;
+    this.m_itemid           =   IT_STRENGTH;
+}
+
+#ifndef MENUQC
+MODEL(Speed_ITEM, Item_Model("g_invincible.md3"));
+#endif
+
+REGISTER_ITEM(Speed, Powerup) {
+#ifndef MENUQC
+    this.m_model            =   MDL_Speed_ITEM;
+#endif
+    this.m_sound            =   "misc/powerup_shield.wav";
+    this.m_name             =   "Speed";
+    this.m_icon             =   "shield";
+    this.m_color            =   '1 0 1';
+    this.m_waypoint         =   _("Speed");
+    this.m_waypointblink    =   2;
+    this.m_itemid           =   IT_INVINCIBLE;
+}
index 1d615b7c0607623312b7f4ad95978cb27f53f6cb..170862ad306f1bf5e20634e00a4f5b1d9560373d 100644 (file)
@@ -1,3 +1,4 @@
+#ifdef IMPLEMENTATION
 REGISTER_MUTATOR(itemstime, true);
 
 #ifdef SVQC
@@ -388,3 +389,4 @@ void HUD_ItemsTime()
 }
 
 #endif
+#endif
index 053b66fea0aa92de427222613c55faaad29c7c9d..b83c96a61679cf413e902ded6fc46182802be533 100644 (file)
@@ -1,5 +1,7 @@
 #include "waypointsprites.qh"
 
+#ifdef IMPLEMENTATION
+
 REGISTER_MUTATOR(waypointsprites, true);
 
 #ifdef SVQC
@@ -1148,3 +1150,4 @@ void WaypointSprite_PlayerGone()
     WaypointSprite_DetachCarrier(self);
 }
 #endif
+#endif
index 90d7ca3ced875e35cc5ba0c1279bd1c4e46f593f..30ad1782f25e56b2ab9f22cca76bce7685ae3bb6 100644 (file)
@@ -1,14 +1,12 @@
 #if defined(CSQC)
-       #include "../../dpdefs/csprogsdefs.qh"
        #include "../../client/defs.qh"
        #include "all.qh"
        #include "../buffs/all.qh"
        #include "../movetypes/movetypes.qh"
        #include "../../client/main.qh"
-       #include "../../csqcmodellib/cl_model.qh"
+       #include "../../lib/csqcmodel/cl_model.qh"
 #elif defined(MENUQC)
 #elif defined(SVQC)
-       #include "../../dpdefs/progsdefs.qh"
     #include "../constants.qh"
     #include "../../server/constants.qh"
        #include "../turrets/sv_turrets.qh"
index 13097a425f01b65388324e75f4d73a796a6f3d0f..600ddaa1b3237301833480c7ef92cb901333b1a0 100644 (file)
@@ -1,8 +1,6 @@
 #if defined(CSQC)
 #elif defined(MENUQC)
 #elif defined(SVQC)
-       #include "../dpdefs/progsdefs.qh"
-    #include "../dpdefs/dpextensions.qh"
     #include "constants.qh"
     #include "teams.qh"
     #include "../server/autocvars.qh"
index e5e43100427743853e1817ff0751aaf1d367d728..6c6aa0f8248ea959c06bd97e970e69e574dfee4a 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef NOTIFICATIONS_H
 #define NOTIFICATIONS_H
 
+#include "command/all.qh"
+
 #include "constants.qh"
 #include "teams.qh"
 #include "util.qh"
@@ -83,6 +85,57 @@ void Create_Notification_Entity(
 
 void Dump_Notifications(float fh, float alsoprint);
 
+
+GENERIC_COMMAND(dumpnotifs, "Dump all notifications into notifications_dump.txt")
+{
+       switch(request)
+       {
+               case CMD_REQUEST_COMMAND:
+               {
+                       #ifndef MENUQC
+                       float fh, alsoprint = false;
+                       string filename = argv(1);
+
+                       if(filename == "")
+                       {
+                               filename = "notifications_dump.cfg";
+                               alsoprint = false;
+                       }
+                       else if(filename == "-")
+                       {
+                               filename = "notifications_dump.cfg";
+                               alsoprint = true;
+                       }
+                       fh = fopen(filename, FILE_WRITE);
+
+                       if(fh >= 0)
+                       {
+                               Dump_Notifications(fh, alsoprint);
+                               LOG_INFOF("Dumping notifications... File located in ^2data/data/%s^7.\n", filename);
+                               fclose(fh);
+                       }
+                       else
+                       {
+                               LOG_INFOF("^1Error: ^7Could not open file '%s'!\n", filename);
+                       }
+                       #else
+                       LOG_INFO(_("Notification dump command only works with cl_cmd and sv_cmd.\n"));
+                       #endif
+                       return;
+               }
+
+               default:
+               case CMD_REQUEST_USAGE:
+               {
+                       LOG_INFO(strcat("\nUsage:^3 ", GetProgramCommandPrefix(), " dumpnotifs [filename]"));
+                       LOG_INFO("  Where 'filename' is the file to write (default is notifications_dump.cfg),\n");
+                       LOG_INFO("  if supplied with '-' output to console as well as default,\n");
+                       LOG_INFO("  if left blank, it will only write to default.\n");
+                       return;
+               }
+       }
+}
+
 #ifdef NOTIFICATIONS_DEBUG
 void Debug_Notification(string input);
 #endif
index 1a799c8de79c903edef70a5db80115bc103d657b..54a7002056f9b681e4a741034ec24656911a6742 100644 (file)
@@ -1,6 +1,5 @@
 #include "physics.qh"
-#include "triggers/trigger/swamp.qh"
-#include "triggers/trigger/jumppads.qh"
+#include "triggers/include.qh"
 #include "viewloc.qh"
 
 #ifdef SVQC
 // client side physics
 bool Physics_Valid(string thecvar)
 {
-       if(!autocvar_g_physics_clientselect) { return false; }
-
-       string l = strcat(" ", autocvar_g_physics_clientselect_options, " ");
-
-       if(strstrofs(l, strcat(" ", thecvar, " "), 0) >= 0)
-               return true;
-
-       return false;
+       return autocvar_g_physics_clientselect && strhasword(autocvar_g_physics_clientselect_options, thecvar);
 }
 
 float Physics_ClientOption(entity pl, string option)
@@ -78,7 +70,8 @@ void Physics_AddStats()
        addstat(STAT_JETPACK_MAXSPEED_SIDE, AS_FLOAT, stat_jetpack_maxspeed_side);
 
        // hack to fix track_canjump
-       addstat(STAT_MOVEVARS_TRACK_CANJUMP, AS_INT, cvar_cl_movement_track_canjump);
+       addstat(STAT_MOVEVARS_CL_TRACK_CANJUMP, AS_INT, cvar_cl_movement_track_canjump);
+       addstat(STAT_MOVEVARS_TRACK_CANJUMP, AS_INT, stat_sv_track_canjump);
 
        // double jump
        addstat(STAT_DOUBLEJUMP, AS_INT, stat_doublejump);
@@ -175,6 +168,8 @@ void Physics_UpdateStats(float maxspd_mod)
        self.stat_sv_airstopaccelerate = Physics_ClientOption(self, "airstopaccelerate");
        self.stat_sv_jumpvelocity = Physics_ClientOption(self, "jumpvelocity");
 
+       self.stat_sv_track_canjump = Physics_ClientOption(self, "track_canjump");
+
        self.stat_gameplayfix_upvelocityclearsonground = UPWARD_VELOCITY_CLEARS_ONGROUND;
 }
 #endif
@@ -591,7 +586,11 @@ bool PlayerJump (void)
                if (!IS_ONGROUND(self))
                        return IS_JUMP_HELD(self);
 
-       if (PHYS_TRACK_CANJUMP(self))
+       bool track_jump = PHYS_CL_TRACK_CANJUMP(self);
+       if(PHYS_TRACK_CANJUMP(self))
+               track_jump = true;
+
+       if (track_jump)
                if (IS_JUMP_HELD(self))
                        return true;
 
index a249b238d7bf197650833c3e3d1badad89135478..d1f82991cd3308f4e5f45c70043e3f2ad076b0a9 100644 (file)
@@ -123,6 +123,7 @@ bool IsFlying(entity a);
        #define PHYS_JUMPSPEEDCAP_MAX                           cvar_string("cl_jumpspeedcap_max")
        #define PHYS_JUMPSPEEDCAP_DISABLE_ONRAMPS       getstati(STAT_MOVEVARS_JUMPSPEEDCAP_DISABLE_ONRAMPS)
 
+       #define PHYS_CL_TRACK_CANJUMP(s)                        getstati(STAT_MOVEVARS_CL_TRACK_CANJUMP)
        #define PHYS_TRACK_CANJUMP(s)                           getstati(STAT_MOVEVARS_TRACK_CANJUMP)
        #define PHYS_ACCELERATE                                         getstatf(STAT_MOVEVARS_ACCELERATE)
        #define PHYS_AIRACCEL_QW(s)                                     getstatf(STAT_MOVEVARS_AIRACCEL_QW)
@@ -247,6 +248,8 @@ bool IsFlying(entity a);
        .float stat_nostep;
        .float stat_jumpstep;
 
+       .bool stat_sv_track_canjump;
+
        #define PHYS_INPUT_ANGLES(s)                            s.v_angle
        #define PHYS_WORLD_ANGLES(s)                            s.angles
 
@@ -323,7 +326,8 @@ bool IsFlying(entity a);
        #define PHYS_JUMPSPEEDCAP_MAX                           autocvar_sv_jumpspeedcap_max
        #define PHYS_JUMPSPEEDCAP_DISABLE_ONRAMPS       autocvar_sv_jumpspeedcap_max_disable_on_ramps
 
-       #define PHYS_TRACK_CANJUMP(s)                           s.cvar_cl_movement_track_canjump
+       #define PHYS_CL_TRACK_CANJUMP(s)                        s.cvar_cl_movement_track_canjump
+       #define PHYS_TRACK_CANJUMP(s)                           s.stat_sv_track_canjump
        #define PHYS_ACCELERATE                                         self.stat_sv_accelerate
        #define PHYS_AIRACCEL_QW(s)                                     s.stat_sv_airaccel_qw
        #define PHYS_AIRACCEL_QW_STRETCHFACTOR(s)       self.stat_sv_airaccel_qw_stretchfactor
index 3a44d71905ec36f071f671f789364f4cfd270c74..0fcbd4259ad82071ad8f198724116ea5d7bcb4f4 100644 (file)
@@ -1,8 +1,6 @@
 #if defined(CSQC)
 #elif defined(MENUQC)
 #elif defined(SVQC)
-       #include "../dpdefs/progsdefs.qh"
-    #include "../dpdefs/dpextensions.qh"
     #include "constants.qh"
     #include "util.qh"
     #include "weapons/all.qh"
index 0e5bd7ffb3ca717bee4ea9ac26881bd1b3f71535..8a7dbbca37fafc2c155ba5b0fb2d40a3bc7b7456 100644 (file)
@@ -1,6 +1,7 @@
 // Global list of sounds
 // TODO: remove uses of _sound
 
+#include "../teams.qh"
 string W_Sound(string w_snd);
 
 SOUND(ARC_FIRE, W_Sound("arc_fire"));
index 90858f39d7841cf5f2c2f73d0c59fc37a637546f..d39c701d7f0a2887295f557a01747bbb4c8bf18a 100644 (file)
@@ -1,49 +1,18 @@
 #ifndef SOUNDS_ALL_H
 #define SOUNDS_ALL_H
 
-#include "../teams.qh"
+#include "sound.qh"
 
-// Play all sounds via sound7, for access to the extra channels.
-// Otherwise, channels 8 to 15 would be blocked for a weird QW feature.
-#ifdef SVQC
-    #define _sound(e, c, s, v, a) do { \
-        entity __e = e; \
-        if (!sound_allowed(MSG_BROADCAST, __e)) break; \
-        sound7(__e, c, s, v, a, 0, 0); \
-    } while (0)
-#else
-    #define _sound(e, c, s, v, a) sound7(e, c, s, v, a, 0, 0)
-#endif
-#define sound(e, c, s, v, a) _sound(e, c, s.sound_str(), v, a)
-// Used in places where a string is required
-#define SND(id) (SND_##id.sound_str())
-
-REGISTRY(Sounds, BIT(8))
+REGISTRY(Sounds, BITS(8))
 REGISTER_REGISTRY(RegisterSounds)
 
-CLASS(Sound, Object)
-    ATTRIB(Sound, m_id, int, 0)
-    ATTRIB(Sound, sound_str, string(), func_null)
-    CONSTRUCTOR(Sound, string() path)
-    {
-        CONSTRUCT(Sound);
-        this.sound_str = path;
-    }
-    METHOD(Sound, sound_precache, void(entity this)) {
-        string s = this.sound_str();
-        if (s && s != "" && !fexists(strcat("sound/", s))) {
-            LOG_WARNINGF("Missing sound: \"%s\"\n", s);
-            return;
-        }
-        LOG_TRACEF("precache_sound(\"%s\")\n", s);
-        precache_sound(s);
-    }
-ENDCLASS(Sound)
-
 #define SOUND(name, path) \
     string SND_##name##_get() { return path; } \
     REGISTER(RegisterSounds, SND, Sounds, name, m_id, NEW(Sound, SND_##name##_get))
 
+// Used in places where a string is required
+#define SND(id) (SND_##id.sound_str())
+
 STATIC_INIT(RegisterSounds_precache) {
     FOREACH(Sounds, true, LAMBDA({
         it.sound_precache(it);
diff --git a/qcsrc/common/sounds/sound.qh b/qcsrc/common/sounds/sound.qh
new file mode 100644 (file)
index 0000000..bc393dd
--- /dev/null
@@ -0,0 +1,36 @@
+#ifndef SOUND_H
+#define SOUND_H
+
+// Play all sounds via sound7, for access to the extra channels.
+// Otherwise, channels 8 to 15 would be blocked for a weird QW feature.
+#ifdef SVQC
+    #define _sound(e, c, s, v, a) do { \
+        entity __e = e; \
+        if (!sound_allowed(MSG_BROADCAST, __e)) break; \
+        sound7(__e, c, s, v, a, 0, 0); \
+    } while (0)
+#else
+    #define _sound(e, c, s, v, a) sound7(e, c, s, v, a, 0, 0)
+#endif
+#define sound(e, c, s, v, a) _sound(e, c, s.sound_str(), v, a)
+
+CLASS(Sound, Object)
+    ATTRIB(Sound, m_id, int, 0)
+    ATTRIB(Sound, sound_str, string(), func_null)
+    CONSTRUCTOR(Sound, string() path)
+    {
+        CONSTRUCT(Sound);
+        this.sound_str = path;
+    }
+    METHOD(Sound, sound_precache, void(entity this)) {
+        string s = this.sound_str();
+        if (s && s != "" && !fexists(strcat("sound/", s))) {
+            LOG_WARNINGF("Missing sound: \"%s\"\n", s);
+            return;
+        }
+        LOG_TRACEF("precache_sound(\"%s\")\n", s);
+        precache_sound(s);
+    }
+ENDCLASS(Sound)
+
+#endif
index eff0eff804ef1f07621f138f78f03266e8096a62..9bdcb5773a5e4bcff57fe8079b53542babfa2bef 100644 (file)
@@ -245,10 +245,10 @@ const int STAT_GAMEPLAYFIX_EASIERWATERJUMP            = 190;
 const int STAT_MOVEVARS_FRICTION_SLICK                = 191;
 const int STAT_MOVEVARS_FRICTION_ONLAND               = 192;
 const int STAT_MOVEVARS_JUMPSPEEDCAP_DISABLE_ONRAMPS  = 193;
-// 194 empty?
+const int STAT_MOVEVARS_TRACK_CANJUMP                 = 194;
 // 195 empty?
 const int STAT_DOUBLEJUMP                             = 196;
-const int STAT_MOVEVARS_TRACK_CANJUMP                 = 197;
+const int STAT_MOVEVARS_CL_TRACK_CANJUMP              = 197;
 const int STAT_MULTIJUMP_ADD                          = 198;
 const int STAT_MULTIJUMP_SPEED                        = 199;
 const int STAT_MULTIJUMP                              = 200;
index 9875dc78ea7134983eda17ec7e5586239bb45d0e..9fda071fd4f005d58870c5d4348361d2c6a278fa 100644 (file)
@@ -1,12 +1,10 @@
 #ifdef SVQC
 
-#include "../../../server/_all.qh"
-
 #include "../../../server/g_subs.qh"
 #include "../../../server/g_damage.qh"
 #include "../../../server/bot/bot.qh"
 #include "../../../common/csqcmodel_settings.qh"
-#include "../../../csqcmodellib/sv_model.qh"
+#include "../../../lib/csqcmodel/sv_model.qh"
 #include "../../../server/weapons/common.qh"
 
 .entity sprite;
index 62af1094637cd4464af60c2763be17699d041dc8..06ca7054352696b92061a23a1ce3aa52ce61acb3 100644 (file)
@@ -1,9 +1,8 @@
 #if defined(CSQC)
-       #include "../../../client/_all.qh"
        #include "../../buffs/all.qh"
-       #include "../../../csqcmodellib/interpolate.qh"
+       #include "../../../lib/csqcmodel/interpolate.qh"
        #include "../../../client/main.qh"
-       #include "../../../csqcmodellib/cl_model.qh"
+       #include "../../../lib/csqcmodel/cl_model.qh"
 #elif defined(MENUQC)
 #elif defined(SVQC)
 #endif
index 98491820f215da9636d2ce8cd72e7bbffc2e7aaa..95cc59904a5017710f4ff9104ddd1de7cd833f41 100644 (file)
@@ -26,6 +26,8 @@
        #define SUB_LTIME               move_ltime
        #define SUB_FLAGS               move_flags
 
+.vector move_origin;
+
        void SUB_SETORIGIN(entity s, vector v)
        {SELFPARAM();
                s.move_origin = v;
index 41edbb718740193adce9252fbdc55666c64c6d6d..257de8be5708c52bf2a11e1410f7173a179fa53a 100644 (file)
@@ -1,7 +1,6 @@
 #if defined(CSQC)
 #elif defined(MENUQC)
 #elif defined(SVQC)
-    #include "../../../server/_all.qh"
     #include "../../constants.qh"
     #include "../../../server/constants.qh"
     #include "../../../server/defs.qh"
index 10fe3c764afb24b3152cd052346cecc2457b7e42..b95837127f3b9b18ecb262643d66ed94d0cce10d 100644 (file)
@@ -1,7 +1,6 @@
 #if defined(CSQC)
 #elif defined(MENUQC)
 #elif defined(SVQC)
-       #include "../../../server/_all.qh"
     #include "../../util.qh"
     #include "../../../server/defs.qh"
 #endif
index 4cfa12ea51a3d35757357f00569b89deb728f452..92575384f710656c6159e44edce1910213540254 100644 (file)
@@ -3,10 +3,9 @@
 #if defined(CSQC)
 #elif defined(MENUQC)
 #elif defined(SVQC)
-       #include "../../server/_all.qh"
-    #include "../../warpzonelib/common.qh"
-    #include "../../warpzonelib/util_server.qh"
-    #include "../../warpzonelib/server.qh"
+    #include "../../lib/warpzone/common.qh"
+    #include "../../lib/warpzone/util_server.qh"
+    #include "../../lib/warpzone/server.qh"
     #include "../constants.qh"
        #include "../triggers/subs.qh"
     #include "../util.qh"
index a5482402891c433fec98f9ebc0f1b2b797af8559..931ff9ceece98d0492268f51316efd4a3c1fe9f1 100644 (file)
@@ -1,6 +1,5 @@
 // TODO: split target_push and put it in the target folder
 #ifdef SVQC
-#include "../../../server/_all.qh"
 #include "jumppads.qh"
 #include "../../movetypes/movetypes.qh"
 
index d16d2773c193442fe04b83943e47b7c9ad8a5652..285ba62a937567c807b57d60f5362ececfcd85c1 100644 (file)
@@ -1,7 +1,6 @@
 #if defined(CSQC)
 #elif defined(MENUQC)
 #elif defined(SVQC)
-       #include "../../../server/_all.qh"
     #include "../../util.qh"
     #include "../../../server/defs.qh"
     #include "secret.qh"
index 5e44c8077ffcd9f75c13f92431c7ffe43ac92b89..a906fcd313d53f21eaac86df915fd429bf418491 100644 (file)
@@ -1,8 +1,7 @@
 #if defined(CSQC)
 #elif defined(MENUQC)
 #elif defined(SVQC)
-       #include "../../../server/_all.qh"
-    #include "../../../warpzonelib/util_server.qh"
+    #include "../../../lib/warpzone/util_server.qh"
     #include "../../weapons/all.qh"
     #include "../../../server/defs.qh"
     #include "../../deathtypes/all.qh"
index 65deb3963d804c6ce7b9e71e2cc7a4cdc659958b..c21fe6b5484b2e935fabe09ebf0d0282bbe9665b 100644 (file)
@@ -1,8 +1,7 @@
 #if defined(CSQC)
 #elif defined(MENUQC)
 #elif defined(SVQC)
-       #include "../../../dpdefs/progsdefs.qh"
-    #include "../../../warpzonelib/util_server.qh"
+    #include "../../../lib/warpzone/util_server.qh"
     #include "../../../server/defs.qh"
 #endif
 
index 2b9a87d421ae67d446f4f0a21758493d1c3c1a02..3f9eba4f37d4e942aac5ccdd160dfb226dee42de 100644 (file)
@@ -1,10 +1,69 @@
 #ifndef TURRETS_ALL_H
 #define TURRETS_ALL_H
 
+#include "../command/all.qh"
+#include "config.qh"
+
 #include "turret.qh"
 
 REGISTRY(Turrets, BIT(5))
 REGISTER_REGISTRY(RegisterTurrets)
+
+
+GENERIC_COMMAND(dumpturrets, "Dump all turrets into turrets_dump.txt")
+{
+    switch(request)
+    {
+        case CMD_REQUEST_COMMAND:
+        {
+            #ifdef SVQC
+            tur_config_file = -1;
+            tur_config_alsoprint = -1;
+            string filename = argv(1);
+
+            if(filename == "")
+            {
+                filename = "turrets_dump.cfg";
+                tur_config_alsoprint = FALSE;
+            }
+            else if(filename == "-")
+            {
+                filename = "turrets_dump.cfg";
+                tur_config_alsoprint = TRUE;
+            }
+            tur_config_file = fopen(filename, FILE_WRITE);
+
+            if(tur_config_file >= 0)
+            {
+                Dump_Turret_Settings();
+                LOG_INFO(sprintf("Dumping turrets... File located in ^2data/data/%s^7.\n", filename));
+                fclose(tur_config_file);
+                tur_config_file = -1;
+                tur_config_alsoprint = -1;
+            }
+            else
+            {
+                LOG_INFO(sprintf("^1Error: ^7Could not open file '%s'!\n", filename));
+            }
+            #else
+            LOG_INFO(_("Turrets dump command only works with sv_cmd.\n"));
+            #endif
+            return;
+        }
+
+        default:
+        case CMD_REQUEST_USAGE:
+        {
+            LOG_INFO(strcat("\nUsage:^3 ", GetProgramCommandPrefix(), " dumpturrets [filename]"));
+            LOG_INFO("  Where 'filename' is the file to write (default is turrets_dump.cfg),\n");
+            LOG_INFO("  if supplied with '-' output to console as well as default,\n");
+            LOG_INFO("  if left blank, it will only write to default.\n");
+            return;
+        }
+    }
+}
+
+
 const int TUR_FIRST = 1;
 #define TUR_LAST (Turrets_COUNT - 1)
 
diff --git a/qcsrc/common/util-post.qh b/qcsrc/common/util-post.qh
deleted file mode 100644 (file)
index f796b6e..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-#ifndef UTIL_POST_H
-#define UTIL_POST_H
-
-[[alias("self")]] entity __self;
-
-// Can't wrap with do-while as block may contain continue or break
-#define WITH(type, name, value, block) { \
-    type __with_save = (name); \
-    name = (value); \
-    LAMBDA(block) \
-    name = __with_save; \
-} do { } while (0)
-
-// Transition from global 'self' to local 'this'
-
-// Step 1: auto oldself
-#if 1
-#define SELFPARAM() noref entity this = __self
-#define setself(s) (__self = s)
-#define self __self
-#endif
-
-// Step 2: check SELFPARAM() is present for functions that use self
-#if 0
-#define SELFPARAM() [[alias("__self")]] noref entity this = __self
-#define setself(s) (__self = s)
-#define self this
-#endif
-
-// Step 3: const self
-#if 0
-#define SELFPARAM() noref const entity this = __self
-entity setself(entity e) { return self = e; }
-entity getself() { return self; }
-#define self getself()
-#endif
-
-// Step 4: enable when possible
-// TODO: Remove SELFPARAM in favor of a parameter
-#if 0
-#define SELFPARAM() noref const entity this = __self
-#define self this
-#endif
-
-#define spawn() new(entity)
-
-#endif
diff --git a/qcsrc/common/util-pre.qh b/qcsrc/common/util-pre.qh
deleted file mode 100644 (file)
index dfb4071..0000000
+++ /dev/null
@@ -1,116 +0,0 @@
-#ifndef UTIL_PRE_H
-#define UTIL_PRE_H
-
-#ifndef NOCOMPAT
-    #define COMPAT_NO_MOD_IS_XONOTIC
-#endif
-
-#ifndef QCC_SUPPORT_ACCUMULATE
-    #ifdef GMQCC
-        #define QCC_SUPPORT_ACCUMULATE
-    #endif
-#endif
-
-#ifndef QCC_SUPPORT_NIL
-    #ifdef GMQCC
-        #define QCC_SUPPORT_NIL 1
-    #endif
-#endif
-
-#ifndef QCC_SUPPORT_INT
-    #define int float
-
-    #define stoi(s) stof(s)
-    #define stob(s) stof(s)
-    #define itos(i) ftos(i)
-#else
-    #define stoi(s) ((int) stof(s))
-    #define stob(s) ((bool) stof(s))
-    #define itos(i) ftos(i)
-#endif
-
-#define FOREACH_ARRAY(arr, start, end, cond, body) do { \
-    for (int i = start; i < end; ++i) {                 \
-        const noref entity it = arr[i];                 \
-        if (cond) { body }                              \
-    }                                                   \
-} while(0)
-
-#define FOREACH_LIST(list, next, cond, body) do {               \
-    noref int i = 0;                                            \
-    for (entity it = list##_first; it; (it = it.next, ++i)) {   \
-        if (cond) { body }                                      \
-    }                                                           \
-} while(0)
-
-#define FOREACH(list, cond, body) FOREACH_LIST(list, enemy, cond, body)
-
-#ifdef GMQCC
-    #define EVAL(...)           __VA_ARGS__
-
-    #define OVERLOAD_(F, ...)   F##_##__VA_COUNT__(__VA_ARGS__)
-    #define OVERLOAD(F, ...)    F##_##__VA_COUNT__(__VA_ARGS__)
-#else
-    #define EMPTY()
-    #define DEFER(id) id EMPTY()
-
-    #define EVAL(...)  EVAL1(EVAL1(EVAL1(__VA_ARGS__)))
-    #define EVAL1(...) EVAL2(EVAL2(EVAL2(__VA_ARGS__)))
-    #define EVAL2(...) EVAL3(EVAL3(EVAL3(__VA_ARGS__)))
-    #define EVAL3(...) EVAL4(EVAL4(EVAL4(__VA_ARGS__)))
-    #define EVAL4(...) EVAL5(EVAL5(EVAL5(__VA_ARGS__)))
-    #define EVAL5(...) __VA_ARGS__
-
-    #define OVERLOAD___(F,_16,_15,_14,_13,_12,_11,_10,_9,_8,_7,_6,_5,_4,_3,_2,_1,n,...) F##_##n
-    #define OVERLOAD__(F, ...)  OVERLOAD___(F,##__VA_ARGS__,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0)
-    #define OVERLOAD_(...)      DEFER(OVERLOAD__(__VA_ARGS__))
-    #define OVERLOAD(F, ...)    OVERLOAD_(F,##__VA_ARGS__)(__VA_ARGS__)
-#endif
-
-#define LAMBDA(...) { __VA_ARGS__ ; }
-
-#define MAP(f, ...) EVAL(OVERLOAD(MAP, f, __VA_ARGS__))
-#define MAP_2(f, it) f(it)
-#define MAP_3(f, it, ...) f(it)MAP_2(f, __VA_ARGS__)
-#define MAP_4(f, it, ...) f(it)MAP_3(f, __VA_ARGS__)
-#define MAP_5(f, it, ...) f(it)MAP_4(f, __VA_ARGS__)
-#define MAP_6(f, it, ...) f(it)MAP_5(f, __VA_ARGS__)
-#define MAP_7(f, it, ...) f(it)MAP_6(f, __VA_ARGS__)
-#define MAP_8(f, it, ...) f(it)MAP_7(f, __VA_ARGS__)
-#define MAP_9(f, it, ...) f(it)MAP_8(f, __VA_ARGS__)
-#define MAP_10(f, it, ...) f(it)MAP_9(f, __VA_ARGS__)
-#define MAP_11(f, it, ...) f(it)MAP_10(f, __VA_ARGS__)
-#define MAP_12(f, it, ...) f(it)MAP_11(f, __VA_ARGS__)
-#define MAP_13(f, it, ...) f(it)MAP_12(f, __VA_ARGS__)
-#define MAP_14(f, it, ...) f(it)MAP_13(f, __VA_ARGS__)
-#define MAP_15(f, it, ...) f(it)MAP_14(f, __VA_ARGS__)
-#define MAP_16(f, it, ...) f(it)MAP_15(f, __VA_ARGS__)
-#define MAP_17(f, it, ...) f(it)MAP_16(f, __VA_ARGS__)
-#define MAP_18(f, it, ...) f(it)MAP_17(f, __VA_ARGS__)
-#define MAP_19(f, it, ...) f(it)MAP_18(f, __VA_ARGS__)
-#define MAP_20(f, it, ...) f(it)MAP_19(f, __VA_ARGS__)
-
-#define IDENTITY(it) it
-
-#define UNWORDS(...) MAP(IDENTITY, __VA_ARGS__)
-
-#define APPLY(f, ...) f(__VA_ARGS__)
-
-#ifdef SVQC
-    #define SV(f, ...) f(__VA_ARGS__)
-#else
-    #define SV(f, ...)
-#endif
-
-#ifdef CSQC
-    #define CL(f, ...) f(__VA_ARGS__)
-#else
-    #define CL(f, ...)
-#endif
-
-#define IF(cond, f, ...) cond(f, __VA_ARGS__)
-
-#define GET(name) name##get
-#define GETTER(type, name) type GET(name)() { return name; }
-
-#endif
index a625ce949a841ea0dd3dbc5ac1566824e0918531..7ac910f998fa7b0c533840dbdc74d90b98aebb6a 100644 (file)
@@ -1,7 +1,6 @@
 #include "util.qh"
 
 #if defined(CSQC)
-       #include "../dpdefs/csprogsdefs.qh"
     #include "../client/defs.qh"
     #include "constants.qh"
        #include "../client/mutators/events.qh"
@@ -10,8 +9,6 @@
     #include "deathtypes/all.qh"
 #elif defined(MENUQC)
 #elif defined(SVQC)
-       #include "../dpdefs/progsdefs.qh"
-    #include "../dpdefs/dpextensions.qh"
     #include "constants.qh"
     #include "../server/autocvars.qh"
     #include "../server/defs.qh"
@@ -177,40 +174,6 @@ string ftos_decimals(float number, float decimals)
        return sprintf("%.*f", decimals, number);
 }
 
-vector colormapPaletteColor(float c, bool isPants)
-{
-       switch (c)
-       {
-               case  0: return '1.000000 1.000000 1.000000';
-               case  1: return '1.000000 0.333333 0.000000';
-               case  2: return '0.000000 1.000000 0.501961';
-               case  3: return '0.000000 1.000000 0.000000';
-               case  4: return '1.000000 0.000000 0.000000';
-               case  5: return '0.000000 0.666667 1.000000';
-               case  6: return '0.000000 1.000000 1.000000';
-               case  7: return '0.501961 1.000000 0.000000';
-               case  8: return '0.501961 0.000000 1.000000';
-               case  9: return '1.000000 0.000000 1.000000';
-               case 10: return '1.000000 0.000000 0.501961';
-               case 11: return '0.000000 0.000000 1.000000';
-               case 12: return '1.000000 1.000000 0.000000';
-               case 13: return '0.000000 0.333333 1.000000';
-               case 14: return '1.000000 0.666667 0.000000';
-               case 15:
-                       if (isPants)
-                               return
-                                         '1 0 0' * (0.502 + 0.498 * sin(time / 2.7182818285 + 0.0000000000))
-                                       + '0 1 0' * (0.502 + 0.498 * sin(time / 2.7182818285 + 2.0943951024))
-                                       + '0 0 1' * (0.502 + 0.498 * sin(time / 2.7182818285 + 4.1887902048));
-                       else
-                               return
-                                         '1 0 0' * (0.502 + 0.498 * sin(time / 3.1415926536 + 5.2359877560))
-                                       + '0 1 0' * (0.502 + 0.498 * sin(time / 3.1415926536 + 3.1415926536))
-                                       + '0 0 1' * (0.502 + 0.498 * sin(time / 3.1415926536 + 1.0471975512));
-               default: return '0.000 0.000 0.000';
-       }
-}
-
 // Databases (hash tables)
 const float DB_BUCKETS = 8192;
 void db_save(float db, string pFilename)
index a2774aa509d1dd1909849f29cb959e95227fe2bd..8bedccf0ae44b38d9935e48686c154de7a362479 100644 (file)
@@ -28,8 +28,6 @@ string ftos_decimals(float number, float decimals);
 
 bool fexists(string f);
 
-vector colormapPaletteColor(float c, float isPants);
-
 // unzone the string, and return it as tempstring. Safe to be called on string_null
 string fstrunzone(string s);
 
index d05a3d769307c3bc17f623ac6a4d4729a013aa40..a00cdcfa343dd4e8b207b2ab3ed06e3370557f36 100644 (file)
@@ -1,5 +1,4 @@
 #include "sv_vehicles.qh"
-#include "../effects/effects.qh"
 
 #if 0
 bool vehicle_send(entity to, int sf)
index d860dba11061533968ee88862480d2ab9d1efa31..8d87fd760312231a9eef74a741c74920393577f7 100644 (file)
@@ -27,7 +27,6 @@ REGISTER_VEHICLE(RACER, NEW(Racer));
 #include "racer_weapon.qc"
 
 #ifdef SVQC
-#include "../../effects/effects.qh"
 #include "../../triggers/trigger/impulse.qh"
 
 bool autocvar_g_vehicle_racer;
index c53002bd4480516a6d7aa5284e3195661b6160c9..69d981beb3e35c0229ebfcfafe54c4043061bef0 100644 (file)
@@ -73,7 +73,7 @@ METHOD(RaptorCannon, wr_think, void(entity thiswep, entity actor, bool fire1, bo
         vehicles_projectile(EFFECT_RAPTOR_MUZZLEFLASH.eent_eff_name, SND(LASERGUN_FIRE),
                                org, normalize(dir + randomvec() * autocvar_g_vehicle_raptor_cannon_spread) * autocvar_g_vehicle_raptor_cannon_speed,
                                autocvar_g_vehicle_raptor_cannon_damage, autocvar_g_vehicle_raptor_cannon_radius, autocvar_g_vehicle_raptor_cannon_force,  0,
-                               DEATH_VH_RAPT_CANNON.m_id, PROJECTILE_RAPTORCANNON, 0, true, true, veh ? veh : player);
+                               DEATH_VH_RAPT_CANNON.m_id, PROJECTILE_RAPTORCANNON, 0, true, true, player);
         weapon_thinkf(player, WFRAME_FIRE1, 0, w_ready);
     }
 }
index ce89bde34e453d392be294d5cf7814db4e622cf4..e992c4ddaa6a2c4b4da2df9900d7ed2182e0a446 100644 (file)
@@ -1,7 +1,6 @@
 #include "util.qh"
 
 #if defined(CSQC)
-       #include "../dpdefs/csprogsdefs.qh"
     #include "../client/defs.qh"
     #include "constants.qh"
 #elif defined(MENUQC)
index 3257215a9fef5b84ef4c073b87774689f496f7c3..fc89a0cd20360dc8f447542253a57c3e886d61d6 100644 (file)
@@ -27,5 +27,3 @@
 #include "weapon/arc.qc"
 #include "weapon/hmg.qc"
 #include "weapon/rpc.qc"
-
-#include "../../server/mutators/gamemode_nexball_weapon.qc"
index 57e46bd5c3e49ad511f37c8104e490038a1c3f9f..e603cb16c195a3ce3c3067e1f4f112979f0724b9 100644 (file)
@@ -4,29 +4,26 @@
 #include "all.qh"
 
 #if defined(CSQC)
-       #include "../../dpdefs/csprogsdefs.qh"
        #include "../../client/defs.qh"
        #include "../constants.qh"
        #include "../stats.qh"
-       #include "../../warpzonelib/anglestransform.qh"
-       #include "../../warpzonelib/common.qh"
-       #include "../../warpzonelib/client.qh"
+       #include "../../lib/warpzone/anglestransform.qh"
+       #include "../../lib/warpzone/common.qh"
+       #include "../../lib/warpzone/client.qh"
        #include "../util.qh"
        #include "../buffs/all.qh"
        #include "../../client/autocvars.qh"
        #include "../deathtypes/all.qh"
-       #include "../../csqcmodellib/interpolate.qh"
+       #include "../../lib/csqcmodel/interpolate.qh"
        #include "../movetypes/movetypes.qh"
        #include "../../client/main.qh"
-       #include "../../csqcmodellib/cl_model.qh"
+       #include "../../lib/csqcmodel/cl_model.qh"
 #elif defined(MENUQC)
 #elif defined(SVQC)
-       #include "../../dpdefs/progsdefs.qh"
-    #include "../../dpdefs/dpextensions.qh"
-    #include "../../warpzonelib/anglestransform.qh"
-    #include "../../warpzonelib/common.qh"
-    #include "../../warpzonelib/util_server.qh"
-    #include "../../warpzonelib/server.qh"
+    #include "../../lib/warpzone/anglestransform.qh"
+    #include "../../lib/warpzone/common.qh"
+    #include "../../lib/warpzone/util_server.qh"
+    #include "../../lib/warpzone/server.qh"
     #include "../constants.qh"
     #include "../stats.qh"
     #include "../teams.qh"
@@ -45,7 +42,7 @@
     #include "../../server/mutators/mutators_include.qh"
     #include "../mapinfo.qh"
     #include "../../server/command/common.qh"
-    #include "../../csqcmodellib/sv_model.qh"
+    #include "../../lib/csqcmodel/sv_model.qh"
     #include "../../server/portals.qh"
     #include "../../server/g_hook.qh"
 #endif
index c96061fe615c00833f0d0524d2f6868bda021d9f..e3f6c7e7ccdaf63aac741030160ee334e68241eb 100644 (file)
@@ -1,6 +1,9 @@
 #ifndef WEAPONS_ALL_H
 #define WEAPONS_ALL_H
 
+#include "../command/all.qh"
+#include "config.qh"
+
 // weapon sets
 typedef vector WepSet;
 #define WEPSET(id) WepSet_FromWeapon(WEP_##id.m_id)
@@ -34,9 +37,63 @@ REGISTRY(Weapons, 72) // Increase as needed. Can be up to 72.
 REGISTER_REGISTRY(RegisterWeapons)
 entity get_weaponinfo(int id);
 
+
+GENERIC_COMMAND(dumpweapons, "Dump all weapons into weapons_dump.txt") // WEAPONTODO: make this work with other progs than just server
+{
+    switch(request)
+    {
+        case CMD_REQUEST_COMMAND:
+        {
+            #ifdef SVQC
+            wep_config_file = -1;
+            wep_config_alsoprint = -1;
+            string filename = argv(1);
+
+            if(filename == "")
+            {
+                filename = "weapons_dump.cfg";
+                wep_config_alsoprint = false;
+            }
+            else if(filename == "-")
+            {
+                filename = "weapons_dump.cfg";
+                wep_config_alsoprint = true;
+            }
+            wep_config_file = fopen(filename, FILE_WRITE);
+
+            if(wep_config_file >= 0)
+            {
+                Dump_Weapon_Settings();
+                LOG_INFO(sprintf("Dumping weapons... File located in ^2data/data/%s^7.\n", filename));
+                fclose(wep_config_file);
+                wep_config_file = -1;
+                wep_config_alsoprint = -1;
+            }
+            else
+            {
+                LOG_INFO(sprintf("^1Error: ^7Could not open file '%s'!\n", filename));
+            }
+            #else
+            LOG_INFO(_("Weapons dump command only works with sv_cmd.\n"));
+            #endif
+            return;
+        }
+
+        default:
+        case CMD_REQUEST_USAGE:
+        {
+            LOG_INFO(strcat("\nUsage:^3 ", GetProgramCommandPrefix(), " dumpweapons [filename]"));
+            LOG_INFO("  Where 'filename' is the file to write (default is weapons_dump.cfg),\n");
+            LOG_INFO("  if supplied with '-' output to console as well as default,\n");
+            LOG_INFO("  if left blank, it will only write to default.\n");
+            return;
+        }
+    }
+}
+
 #define REGISTER_WEAPON(id, inst) \
-       /* WepSet WEPSET_##id; */ \
-       REGISTER(RegisterWeapons, WEP, Weapons, id, m_id, inst)
+    /* WepSet WEPSET_##id; */ \
+    REGISTER(RegisterWeapons, WEP, Weapons, id, m_id, inst)
 
 // create cvars for weapon settings
 #define WEP_ADD_CVAR_NONE(wepname,name) [[last]] float autocvar_g_balance_##wepname##_##name;
@@ -44,15 +101,15 @@ entity get_weaponinfo(int id);
 #define WEP_ADD_CVAR_PRI(wepname,name) WEP_ADD_CVAR_NONE(wepname, primary_##name)
 #define WEP_ADD_CVAR_SEC(wepname,name) WEP_ADD_CVAR_NONE(wepname, secondary_##name)
 #define WEP_ADD_CVAR_BOTH(wepname,name) \
-       WEP_ADD_CVAR_PRI(wepname, name) \
-       WEP_ADD_CVAR_SEC(wepname, name)
+    WEP_ADD_CVAR_PRI(wepname, name) \
+    WEP_ADD_CVAR_SEC(wepname, name)
 
 #define WEP_ADD_CVAR(wepid,wepname,mode,name) WEP_ADD_CVAR_##mode(wepname, name)
 
 // create properties for weapon settings
 #define WEP_ADD_PROP(wepid,wepname,type,prop,name) \
-       .type prop; \
-       [[last]] type autocvar_g_balance_##wepname##_##name;
+    .type prop; \
+    [[last]] type autocvar_g_balance_##wepname##_##name;
 
 // read cvars from weapon settings
 #define WEP_CVAR(wepname,name) autocvar_g_balance_##wepname##_##name
@@ -75,11 +132,11 @@ REGISTER_WEAPON(Null, NEW(Weapon));
 
 entity get_weaponinfo(int id)
 {
-       if (id >= WEP_FIRST && id <= WEP_LAST) {
-               Weapon w = Weapons[id];
-               if (w) return w;
-       }
-       return WEP_Null;
+    if (id >= WEP_FIRST && id <= WEP_LAST) {
+        Weapon w = Weapons[id];
+        if (w) return w;
+    }
+    return WEP_Null;
 }
 
 // TODO: remove after 0.8.2. Retains impulse number compatibility because 0.8.1 clients don't reload the weapons.cfg
@@ -93,28 +150,27 @@ REGISTRY_SORT(Weapons, netname, WEP_HARDCODED_IMPULSES + 1)
 
 STATIC_INIT(register_weapons_done)
 {
-       for (int i = 0; i < Weapons_COUNT; ++i) {
-               Weapon it = Weapons[i];
-               it.m_id = i;
-               WepSet set = WepSet_FromWeapon(it.m_id);
-               WEPSET_ALL |= set;
-               if ((it.spawnflags) & WEP_FLAG_SUPERWEAPON) WEPSET_SUPERWEAPONS |= set;
-               it.weapon = it.m_id;
-               it.weapons = set;
-               #ifdef CSQC
-               it.wr_init(it);
-               #endif
-               int imp = WEP_IMPULSE_BEGIN + it.m_id - 1;
-               if (imp <= WEP_IMPULSE_END)
-                       localcmd(sprintf("alias weapon_%s \"impulse %d\"\n", it.netname, imp));
-               else
-                       LOG_TRACEF(_("Impulse limit exceeded, weapon will not be directly accessible: %s\n"), it.netname);
-       }
-       weaponorder_byid = "";
-       for (int i = Weapons_MAX - 1; i >= 1; --i)
-               if (Weapons[i])
-                       weaponorder_byid = strcat(weaponorder_byid, " ", ftos(i));
-       weaponorder_byid = strzone(substring(weaponorder_byid, 1, strlen(weaponorder_byid) - 1));
+    FOREACH(Weapons, true, LAMBDA(
+        it.m_id = i;
+        WepSet set = WepSet_FromWeapon(it.m_id);
+        WEPSET_ALL |= set;
+        if ((it.spawnflags) & WEP_FLAG_SUPERWEAPON) WEPSET_SUPERWEAPONS |= set;
+        it.weapon = it.m_id;
+        it.weapons = set;
+        int imp = WEP_IMPULSE_BEGIN + it.m_id - 1;
+        if (imp <= WEP_IMPULSE_END)
+            localcmd(sprintf("alias weapon_%s \"impulse %d\"\n", it.netname, imp));
+        else
+            LOG_TRACEF(_("Impulse limit exceeded, weapon will not be directly accessible: %s\n"), it.netname);
+    ));
+    #ifdef CSQC
+    FOREACH(Weapons, true, LAMBDA(it.wr_init(it)));
+    #endif
+    weaponorder_byid = "";
+    for (int i = Weapons_MAX - 1; i >= 1; --i)
+        if (Weapons[i])
+            weaponorder_byid = strcat(weaponorder_byid, " ", ftos(i));
+    weaponorder_byid = strzone(substring(weaponorder_byid, 1, strlen(weaponorder_byid) - 1));
 }
 
 #endif
index d932224e3a8bae0e990604ec19ed47410e05b517..7d1b4e3d262067f491fd6a555f46d1bd1f020769 100644 (file)
@@ -1,8 +1,6 @@
 #if defined(CSQC)
 #elif defined(MENUQC)
 #elif defined(SVQC)
-       #include "../../dpdefs/progsdefs.qh"
-    #include "../../dpdefs/dpextensions.qh"
     #include "../util.qh"
     #include "config.qh"
     #include "all.qh"
index 410dbdfadeb8b1f7fe79e4eeacf63bdf1a7e14d0..c50c1e544041fc2a8960b214371c3df27c1d9a14 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef WEAPONS_CONFIG_H
 #define WEAPONS_CONFIG_H
 
+#ifdef SVQC
 // ==========================
 //  Balance Config Generator
 // ==========================
@@ -47,3 +48,4 @@ string wep_config_queue[MAX_WEP_CONFIG];
 
 #define WEP_CONFIG_WRITE_PROPS(wepid,wepname,type,prop,name) WEP_CONFIG_WRITE_PROPS_##type(wepname,name)
 #endif
+#endif
diff --git a/qcsrc/csqcmodellib/cl_model.qc b/qcsrc/csqcmodellib/cl_model.qc
deleted file mode 100644 (file)
index ab93b01..0000000
+++ /dev/null
@@ -1,291 +0,0 @@
-/*
- * Copyright (c) 2011 Rudolf PolzerCSQCModel_InterpolateAnimation_2To4_PreNote
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
- #if defined(CSQC)
-        #include "../dpdefs/csprogsdefs.qh"
-        #include "../client/defs.qh"
-        #include "../common/util.qh"
-        #include "../common/animdecide.qh"
-        #include "interpolate.qh"
-        #include "../common/csqcmodel_settings.qh"
-        #include "common.qh"
-        #include "cl_model.qh"
-        #include "cl_player.qh"
- #elif defined(MENUQC)
- #elif defined(SVQC)
- #endif
-
-float autocvar_cl_lerpanim_maxdelta_framegroups = 0.1;
-float autocvar_cl_nolerp = 0;
-
-.float csqcmodel_lerpfrac;
-.float csqcmodel_lerpfrac2;
-.float csqcmodel_lerpfractime;
-.float csqcmodel_lerpfrac2time;
-
-void CSQCModel_InterpolateAnimation_2To4_PreNote(int sf)
-{SELFPARAM();
-       if(sf & CSQCMODEL_PROPERTY_FRAME)
-       {
-               self.frame3 = self.frame;
-               self.frame3time = self.frame1time;
-       }
-       if(sf & CSQCMODEL_PROPERTY_FRAME2)
-       {
-               self.frame4 = self.frame2;
-               self.frame4time = self.frame2time;
-       }
-       if(sf & CSQCMODEL_PROPERTY_LERPFRAC)
-       {
-               self.csqcmodel_lerpfrac2 = self.csqcmodel_lerpfrac;
-               self.csqcmodel_lerpfrac2time = self.csqcmodel_lerpfractime;
-               self.lerpfrac = self.csqcmodel_lerpfrac;
-       }
-}
-void CSQCModel_InterpolateAnimation_1To2_PreNote(int sf)
-{SELFPARAM();
-       if(sf & CSQCMODEL_PROPERTY_FRAME)
-       {
-               self.frame2 = self.frame;
-               self.frame2time = self.frame1time;
-       }
-}
-void CSQCModel_InterpolateAnimation_PreNote(int sf)
-{
-#ifdef CSQCMODEL_HAVE_TWO_FRAMES
-       CSQCModel_InterpolateAnimation_2To4_PreNote(sf);
-#else
-       CSQCModel_InterpolateAnimation_1To2_PreNote(sf);
-#endif
-}
-
-void CSQCModel_InterpolateAnimation_2To4_Note(int sf, float set_times)
-{SELFPARAM();
-       if(sf & CSQCMODEL_PROPERTY_FRAME)
-       {
-               if(set_times)
-                       self.frame1time = time;
-       }
-       if(sf & CSQCMODEL_PROPERTY_FRAME2)
-       {
-               if(set_times)
-                       self.frame2time = time;
-       }
-       if(sf & CSQCMODEL_PROPERTY_LERPFRAC)
-       {
-               self.csqcmodel_lerpfrac = self.lerpfrac;
-               if(set_times)
-                       self.csqcmodel_lerpfractime = time;
-       }
-}
-void CSQCModel_InterpolateAnimation_1To2_Note(int sf, float set_times)
-{SELFPARAM();
-       if(sf & CSQCMODEL_PROPERTY_FRAME)
-       {
-               if(set_times)
-                       self.frame1time = time;
-       }
-}
-void CSQCModel_InterpolateAnimation_Note(int sf)
-{
-#ifdef CSQCMODEL_HAVE_TWO_FRAMES
-       CSQCModel_InterpolateAnimation_2To4_Note(sf, true);
-#else
-       CSQCModel_InterpolateAnimation_1To2_Note(sf, true);
-#endif
-}
-
-void CSQCModel_InterpolateAnimation_2To4_Do()
-{SELFPARAM();
-       if(autocvar_cl_nolerp || (autocvar_cl_lerpanim_maxdelta_framegroups == 0))
-       {
-               self.lerpfrac = self.csqcmodel_lerpfrac;
-               self.lerpfrac3 = 0;
-               self.lerpfrac4 = 0;
-       }
-       else
-       {
-               float l13, l24, llf;
-               float l24_13;
-
-               if(self.frame3time == 0) // if frame1/3 were not previously displayed, only frame1 can make sense
-                       l13 = 1;
-               else
-                       l13 = bound(0, (time - self.frame1time) / autocvar_cl_lerpanim_maxdelta_framegroups, 1);
-
-               if(self.frame4time == 0) // if frame2/4 were not previously displayed, only frame2 can make sense
-                       l24 = 1;
-               else
-                       l24 = bound(0, (time - self.frame2time) / autocvar_cl_lerpanim_maxdelta_framegroups, 1);
-
-               if(self.csqcmodel_lerpfrac2time == 0) // if there is no old lerpfrac (newly displayed model), only lerpfrac makes sense
-                       llf = 1;
-               else
-                       llf = bound(0, (time - self.csqcmodel_lerpfractime) / autocvar_cl_lerpanim_maxdelta_framegroups, 1);
-
-               l24_13 = self.csqcmodel_lerpfrac * llf + self.csqcmodel_lerpfrac2 * (1 - llf);
-
-               self.lerpfrac  = l24 * l24_13;
-               self.lerpfrac4 = (1 - l24) * l24_13;
-               self.lerpfrac3 = (1 - l13) * (1 - l24_13);
-
-               if(l24_13 == 0) // if frames 2/4 are not displayed, clear their frametime
-               {
-                       self.frame2time = 0;
-                       self.frame4time = 0;
-               }
-
-               if(l24_13 == 1) // if frames 1/3 are not displayed, clear their frametime
-               {
-                       self.frame1time = 0;
-                       self.frame3time = 0;
-               }
-       }
-}
-void CSQCModel_InterpolateAnimation_1To2_Do()
-{SELFPARAM();
-       if(autocvar_cl_nolerp || (autocvar_cl_lerpanim_maxdelta_framegroups == 0))
-       {
-               self.lerpfrac = 0;
-       }
-       else
-       {
-               if(self.frame2time == 0) // if frame2 was not previously displayed, only frame1 can make sense
-                       self.lerpfrac = 0;
-               else
-                       self.lerpfrac = 1 - bound(0, (time - self.frame1time) / autocvar_cl_lerpanim_maxdelta_framegroups, 1);
-       }
-}
-void CSQCModel_InterpolateAnimation_Do()
-{
-#ifdef CSQCMODEL_HAVE_TWO_FRAMES
-       CSQCModel_InterpolateAnimation_2To4_Do();
-#else
-       CSQCModel_InterpolateAnimation_1To2_Do();
-#endif
-}
-
-void CSQCModel_Draw()
-{SELFPARAM();
-       // some nice flags for CSQCMODEL_IF and the hooks
-       bool isplayer = (self.entnum >= 1 && self.entnum <= maxclients);
-       noref bool islocalplayer = (self.entnum == player_localnum + 1);
-       noref bool isnolocalplayer = (isplayer && (self.entnum != player_localnum + 1));
-
-       // we don't do this for the local player as that one is already handled
-       // by CSQCPlayer_SetCamera()
-       if(!CSQCPlayer_IsLocalPlayer())
-               InterpolateOrigin_Do();
-
-       CSQCModel_InterpolateAnimation_Do();
-
-       { CSQCMODEL_HOOK_PREDRAW }
-
-       // inherit draw flags easily
-       entity root = self;
-       while(root.tag_entity)
-               root = root.tag_entity;
-       if(self != root)
-       {
-               self.renderflags &= ~(RF_EXTERNALMODEL | RF_VIEWMODEL);
-               self.renderflags |= (root.renderflags & (RF_EXTERNALMODEL | RF_VIEWMODEL));
-       }
-
-       // we're drawn, now teleporting is over
-       self.csqcmodel_teleported = 0;
-}
-
-void CSQCModel_Read(bool isnew)
-{SELFPARAM();
-       int sf = ReadInt24_t();
-
-       // some nice flags for CSQCMODEL_IF and the hooks
-       bool isplayer = (self.entnum >= 1 && self.entnum <= maxclients);
-       bool islocalplayer = (self.entnum == player_localnum + 1);
-       noref bool isnolocalplayer = (isplayer && (self.entnum != player_localnum + 1));
-
-       self.classname = "csqcmodel";
-       self.iflags |= IFLAG_ORIGIN; // interpolate origin too
-       self.iflags |= IFLAG_ANGLES; // interpolate angles too
-       self.iflags |= IFLAG_VELOCITY | IFLAG_AUTOVELOCITY; // let's calculate velocity automatically
-
-       { CSQCMODEL_HOOK_PREUPDATE }
-
-       CSQCPlayer_PreUpdate();
-       InterpolateOrigin_Undo();
-       CSQCModel_InterpolateAnimation_PreNote(sf);
-
-#define CSQCMODEL_IF(cond) if(cond) {
-#define CSQCMODEL_ENDIF }
-#define CSQCMODEL_PROPERTY(flag,t,r,w,f) \
-       if(sf & flag) \
-               self.f = r();
-#define CSQCMODEL_PROPERTY_SCALED(flag,t,r,w,f,s,mi,ma) \
-       if(sf & flag) \
-               self.f = (r() + mi) / s;
-       ALLPROPERTIES
-#undef CSQCMODEL_PROPERTY_SCALED
-#undef CSQCMODEL_PROPERTY
-#undef CSQCMODEL_ENDIF
-#undef CSQCMODEL_IF
-
-       if(sf & CSQCMODEL_PROPERTY_MODELINDEX)
-       {
-               vector pmin = self.mins, pmax = self.maxs;
-               setmodelindex(self, self.modelindex); // this retrieves the .model key and sets mins/maxs/absmin/absmax
-               setsize(self, pmin, pmax);
-       }
-
-       if(sf & CSQCMODEL_PROPERTY_TELEPORTED)
-       {
-               self.iflags |= IFLAG_TELEPORTED;
-               self.csqcmodel_teleported = 1;
-       }
-
-       CSQCModel_InterpolateAnimation_Note(sf);
-       InterpolateOrigin_Note();
-       CSQCPlayer_PostUpdate();
-
-       { CSQCMODEL_HOOK_POSTUPDATE }
-
-#ifdef CSQCMODEL_SUPPORT_GETTAGINFO_BEFORE_DRAW
-       InterpolateOrigin_Do();
-       CSQCModel_InterpolateAnimation_Do();
-#endif
-
-       // relink
-       setorigin(self, self.origin);
-
-       // set obvious render flags
-       if(self.entnum == player_localentnum)
-               self.renderflags |= RF_EXTERNALMODEL;
-       else
-               self.renderflags &= ~RF_EXTERNALMODEL;
-
-       // draw it
-       self.drawmask = MASK_NORMAL;
-       self.predraw = CSQCModel_Draw;
-}
-
-entity CSQCModel_server2csqc(float pl)
-{
-       return findfloat(world, entnum, pl); // FIXME optimize this using an array
-}
diff --git a/qcsrc/csqcmodellib/cl_model.qh b/qcsrc/csqcmodellib/cl_model.qh
deleted file mode 100644 (file)
index 98f1da0..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (c) 2011 Rudolf Polzer
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-#ifndef CL_MODEL_H
-#define CL_MODEL_H
-
-#include "common.qh"
-
-void CSQCModel_Read(bool isnew);
-
-#define CSQCMODEL_IF(cond)
-#define CSQCMODEL_ENDIF
-#define CSQCMODEL_PROPERTY(flag,t,r,w,f) \
-       .t f;
-#define CSQCMODEL_PROPERTY_SCALED(flag,t,r,w,f,s,mi,ma) CSQCMODEL_PROPERTY(flag,t,r,w,f)
-       ALLPROPERTIES
-#undef CSQCMODEL_PROPERTY_SCALED
-#undef CSQCMODEL_PROPERTY
-#undef CSQCMODEL_ENDIF
-#undef CSQCMODEL_IF
-
-entity CSQCModel_server2csqc(float pl);
-.float csqcmodel_teleported;
-
-// this is exported for custom frame animation code. Use with care.
-// to update frames, first call this:
-void CSQCModel_InterpolateAnimation_2To4_PreNote(int sf);
-void CSQCModel_InterpolateAnimation_1To2_PreNote(int sf);
-// then update frame, frame1time (and possibly frame2, frame2time, lerpfrac)
-// if set_times is not set, caller is responsible for frame1time, frame2time, csqcmodel_lerpfractime!
-void CSQCModel_InterpolateAnimation_2To4_Note(int sf, float set_times);
-void CSQCModel_InterpolateAnimation_1To2_Note(int sf, float set_times);
-// to retrieve animation state, call this
-void CSQCModel_InterpolateAnimation_2To4_Do();
-void CSQCModel_InterpolateAnimation_1To2_Do();
-// will overwrite lerpfrac, lerpfrac3, lerpfrac4, and possibly clear frame*time if they are undisplayed according to lerpfracs
-#endif
diff --git a/qcsrc/csqcmodellib/cl_player.qc b/qcsrc/csqcmodellib/cl_player.qc
deleted file mode 100644 (file)
index 1a96e23..0000000
+++ /dev/null
@@ -1,367 +0,0 @@
-/*
- * Copyright (c) 2011 Rudolf Polzer
- * Copyright (c) 2015 Micah Talkiewicz
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-#if defined(CSQC)
-       #include "../dpdefs/csprogsdefs.qh"
-       #include "../client/defs.qh"
-       #include "../common/constants.qh"
-       #include "../common/stats.qh"
-       #include "../common/util.qh"
-       #include "interpolate.qh"
-       #include "../client/main.qh"
-       #include "common.qh"
-       #include "cl_model.qh"
-       #include "cl_player.qh"
-       #include "../common/triggers/trigger/viewloc.qh"
-       #include "../common/viewloc.qh"
-#elif defined(MENUQC)
-#elif defined(SVQC)
-#endif
-
-float autocvar_cl_movement_errorcompensation = 0;
-int autocvar_cl_movement = 1;
-
-// engine stuff
-float pmove_onground; // weird engine flag we shouldn't really use but have to for now
-
-vector csqcplayer_origin, csqcplayer_velocity;
-float csqcplayer_sequence;
-int player_pmflags;
-float csqcplayer_moveframe;
-vector csqcplayer_predictionerroro;
-vector csqcplayer_predictionerrorv;
-float csqcplayer_predictionerrortime;
-float csqcplayer_predictionerrorfactor;
-
-vector CSQCPlayer_GetPredictionErrorO()
-{
-       if(time >= csqcplayer_predictionerrortime)
-               return '0 0 0';
-       return csqcplayer_predictionerroro * (csqcplayer_predictionerrortime - time) * csqcplayer_predictionerrorfactor;
-}
-
-vector CSQCPlayer_GetPredictionErrorV()
-{
-       if(time >= csqcplayer_predictionerrortime)
-               return '0 0 0';
-       return csqcplayer_predictionerrorv * (csqcplayer_predictionerrortime - time) * csqcplayer_predictionerrorfactor;
-}
-
-void CSQCPlayer_SetPredictionError(vector o, vector v, float onground_diff)
-{
-       // error too big to compensate, we LIKELY hit a teleport or a
-       // jumppad, or it's a jump time disagreement that'll get fixed
-       // next frame
-
-       // FIXME we sometimes have disagreement in order of jump velocity. Do not act on them!
-       /*
-       // commented out as this one did not help
-       if(onground_diff)
-       {
-               printf("ONGROUND MISMATCH: %d x=%v v=%v\n", onground_diff, o, v);
-               return;
-       }
-       */
-       if(vlen(o) > 32 || vlen(v) > 192)
-       {
-               //printf("TOO BIG: x=%v v=%v\n", o, v);
-               return;
-       }
-
-       if(!autocvar_cl_movement_errorcompensation)
-       {
-               csqcplayer_predictionerrorfactor = 0;
-               return;
-       }
-
-       csqcplayer_predictionerroro = CSQCPlayer_GetPredictionErrorO() + o;
-       csqcplayer_predictionerrorv = CSQCPlayer_GetPredictionErrorV() + v;
-       csqcplayer_predictionerrorfactor = autocvar_cl_movement_errorcompensation / ticrate;
-       csqcplayer_predictionerrortime = time + 1.0 / csqcplayer_predictionerrorfactor;
-}
-
-void CSQCPlayer_Unpredict()
-{SELFPARAM();
-       if(csqcplayer_status == CSQCPLAYERSTATUS_UNPREDICTED)
-               return;
-       if(csqcplayer_status != CSQCPLAYERSTATUS_PREDICTED)
-               error("Cannot unpredict in current status");
-       self.origin = csqcplayer_origin;
-       self.velocity = csqcplayer_velocity;
-       csqcplayer_moveframe = csqcplayer_sequence+1; //+1 because the recieved frame has the move already done (server side)
-       self.flags = player_pmflags;
-}
-
-void CSQCPlayer_SetMinsMaxs()
-{SELFPARAM();
-       if(self.flags & FL_DUCKED)
-       {
-               self.mins = PL_CROUCH_MIN;
-               self.maxs = PL_CROUCH_MAX;
-               self.view_ofs = PL_CROUCH_VIEW_OFS;
-       }
-       else
-       {
-               self.mins = PL_MIN;
-               self.maxs = PL_MAX;
-               self.view_ofs = PL_VIEW_OFS;
-       }
-}
-
-void CSQCPlayer_SavePrediction()
-{SELFPARAM();
-       player_pmflags = self.flags;
-       csqcplayer_origin = self.origin;
-       csqcplayer_velocity = self.velocity;
-       csqcplayer_sequence = servercommandframe;
-       csqcplayer_status = CSQCPLAYERSTATUS_PREDICTED;
-}
-
-void CSQC_ClientMovement_PlayerMove_Frame();
-
-void PM_Movement_Move()
-{SELFPARAM();
-       runstandardplayerphysics(self);
-#ifdef CSQC
-       self.flags =
-                       ((self.pmove_flags & PMF_DUCKED) ? FL_DUCKED : 0) |
-                       (!(self.pmove_flags & PMF_JUMP_HELD) ? FL_JUMPRELEASED : 0) |
-                       ((self.pmove_flags & PMF_ONGROUND) ? FL_ONGROUND : 0);
-#endif
-}
-
-void CSQCPlayer_Physics(void)
-{
-       switch(autocvar_cl_movement)
-       {
-               case 1: CSQC_ClientMovement_PlayerMove_Frame(); break;
-               case 2: PM_Movement_Move(); break;
-       }
-}
-
-void CSQCPlayer_PredictTo(float endframe, float apply_error)
-{SELFPARAM();
-       CSQCPlayer_Unpredict();
-       if(apply_error)
-       {
-               self.origin += CSQCPlayer_GetPredictionErrorO();
-               self.velocity += CSQCPlayer_GetPredictionErrorV();
-       }
-       CSQCPlayer_SetMinsMaxs();
-
-       csqcplayer_status = CSQCPLAYERSTATUS_PREDICTED;
-
-#if 0
-       // we don't need this
-       // darkplaces makes servercommandframe == 0 in these cases anyway
-       if (getstatf(STAT_HEALTH) <= 0)
-       {
-               csqcplayer_moveframe = clientcommandframe;
-               getinputstate(csqcplayer_moveframe-1);
-               LOG_INFO("the Weird code path got hit\n");
-               return;
-       }
-#endif
-
-       if(csqcplayer_moveframe >= endframe)
-       {
-               getinputstate(csqcplayer_moveframe - 1);
-       }
-       else
-       {
-               do
-               {
-                       if (!getinputstate(csqcplayer_moveframe))
-                               break;
-                       CSQCPlayer_Physics();
-                       CSQCPlayer_SetMinsMaxs();
-                       csqcplayer_moveframe++;
-               }
-               while(csqcplayer_moveframe < endframe);
-       }
-
-       //add in anything that was applied after (for low packet rate protocols)
-       input_angles = view_angles;
-}
-
-bool CSQCPlayer_IsLocalPlayer()
-{SELFPARAM();
-       return (self == csqcplayer);
-}
-
-void CSQCPlayer_SetViewLocation()
-{
-       viewloc_SetViewLocation();
-}
-
-void CSQCPlayer_SetCamera()
-{SELFPARAM();
-       vector v0;
-       v0 = pmove_vel; // TRICK: pmove_vel is set by the engine when we get here. No need to network velocity
-
-       if(csqcplayer)
-       {
-               setself(csqcplayer);
-
-               if(servercommandframe == 0 || clientcommandframe == 0)
-               {
-                       InterpolateOrigin_Do();
-                       self.view_ofs = '0 0 1' * getstati(STAT_VIEWHEIGHT);
-
-                       // get crouch state from the server
-                       if(getstati(STAT_VIEWHEIGHT) == PL_VIEW_OFS.z)
-                               self.flags &= ~FL_DUCKED;
-                       else if(getstati(STAT_VIEWHEIGHT) == PL_CROUCH_VIEW_OFS.z)
-                               self.flags |= FL_DUCKED;
-
-                       // get onground state from the server
-                       if(pmove_onground)
-                               self.flags |= FL_ONGROUND;
-                       else
-                               self.flags &= ~FL_ONGROUND;
-
-                       CSQCPlayer_SetMinsMaxs();
-
-                       // override it back just in case
-                       self.view_ofs = '0 0 1' * getstati(STAT_VIEWHEIGHT);
-
-                       // set velocity
-                       self.velocity = v0;
-               }
-               else
-               {
-                       float flg = self.iflags;
-                       self.iflags &= ~(IFLAG_ORIGIN | IFLAG_ANGLES);
-                       InterpolateOrigin_Do();
-                       self.iflags = flg;
-
-                       if(csqcplayer_status == CSQCPLAYERSTATUS_FROMSERVER)
-                       {
-                               vector o, v;
-                               o = self.origin;
-                               v = v0;
-                               csqcplayer_status = CSQCPLAYERSTATUS_PREDICTED;
-                               CSQCPlayer_PredictTo(servercommandframe + 1, false);
-                               CSQCPlayer_SetPredictionError(self.origin - o, self.velocity - v, pmove_onground - !!(self.flags & FL_ONGROUND));
-                               self.origin = o;
-                               self.velocity = v;
-
-                               // get crouch state from the server
-                               if(getstati(STAT_VIEWHEIGHT) == PL_VIEW_OFS.z)
-                                       self.flags &= ~FL_DUCKED;
-                               else if(getstati(STAT_VIEWHEIGHT) == PL_CROUCH_VIEW_OFS.z)
-                                       self.flags |= FL_DUCKED;
-
-                               // get onground state from the server
-                               if(pmove_onground)
-                                       self.flags |= FL_ONGROUND;
-                               else
-                                       self.flags &= ~FL_ONGROUND;
-
-                               CSQCPlayer_SavePrediction();
-                       }
-                       CSQCPlayer_PredictTo(clientcommandframe + 1, true);
-
-#ifdef CSQCMODEL_SERVERSIDE_CROUCH
-                       // get crouch state from the server (LAG)
-                       if(getstati(STAT_VIEWHEIGHT) == PL_VIEW_OFS.z)
-                               self.flags &= ~FL_DUCKED;
-                       else if(getstati(STAT_VIEWHEIGHT) == PL_CROUCH_VIEW_OFS.z)
-                               self.flags |= FL_DUCKED;
-#endif
-
-                       CSQCPlayer_SetMinsMaxs();
-
-                       self.angles_y = input_angles.y;
-               }
-
-               // relink
-               setorigin(self, self.origin);
-
-               setself(this);
-       }
-
-       entity view = CSQCModel_server2csqc(player_localentnum);
-
-       if(view && view != csqcplayer)
-       {
-               WITH(entity, self, view, InterpolateOrigin_Do());
-               view.view_ofs = '0 0 1' * getstati(STAT_VIEWHEIGHT);
-       }
-
-       if(view)
-       {
-               int refdefflags = 0;
-
-               if(view.csqcmodel_teleported)
-                       refdefflags |= REFDEFFLAG_TELEPORTED;
-
-               if(input_buttons & 4)
-                       refdefflags |= REFDEFFLAG_JUMPING;
-
-               // note: these two only work in WIP2, but are harmless in WIP1
-               if(getstati(STAT_HEALTH) <= 0)
-                       refdefflags |= REFDEFFLAG_DEAD;
-
-               if(intermission)
-                       refdefflags |= REFDEFFLAG_INTERMISSION;
-
-               V_CalcRefdef(view, refdefflags);
-       }
-       else
-       {
-               // FIXME by CSQC spec we have to do this:
-               // but it breaks chase cam
-               /*
-               setproperty(VF_ORIGIN, pmove_org + '0 0 1' * getstati(STAT_VIEWHEIGHT));
-               setproperty(VF_ANGLES, view_angles);
-               */
-       }
-
-       { CSQCPLAYER_HOOK_POSTCAMERASETUP }
-}
-
-void CSQCPlayer_Remove()
-{
-       csqcplayer = world;
-       cvar_settemp("cl_movement_replay", "1");
-}
-
-float CSQCPlayer_PreUpdate()
-{SELFPARAM();
-       if(self != csqcplayer)
-               return 0;
-       if(csqcplayer_status != CSQCPLAYERSTATUS_FROMSERVER)
-               CSQCPlayer_Unpredict();
-       return 1;
-}
-
-float CSQCPlayer_PostUpdate()
-{SELFPARAM();
-       if(self.entnum != player_localnum + 1)
-               return 0;
-       csqcplayer = self;
-       csqcplayer_status = CSQCPLAYERSTATUS_FROMSERVER;
-       cvar_settemp("cl_movement_replay", "0");
-       self.entremove = CSQCPlayer_Remove;
-       return 1;
-}
diff --git a/qcsrc/csqcmodellib/cl_player.qh b/qcsrc/csqcmodellib/cl_player.qh
deleted file mode 100644 (file)
index e427e6c..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (c) 2011 Rudolf Polzer
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-#ifndef CL_PLAYER_H
-#define CL_PLAYER_H
-
-entity csqcplayer;
-float csqcplayer_status;
-const int CSQCPLAYERSTATUS_UNPREDICTED = 0;
-const int CSQCPLAYERSTATUS_FROMSERVER = 1;
-const int CSQCPLAYERSTATUS_PREDICTED = 2;
-
-// only ever READ these!
-.int pmove_flags;
-const int PMF_JUMP_HELD = 1;
-//const int PMF_DUCKED = 4;
-//const int PMF_ONGROUND = 8;
-
-const int FL_DUCKED = 524288;
-
-void CSQCPlayer_SetCamera();
-float CSQCPlayer_PreUpdate();
-float CSQCPlayer_PostUpdate();
-float CSQCPlayer_IsLocalPlayer();
-#endif
diff --git a/qcsrc/csqcmodellib/common.qh b/qcsrc/csqcmodellib/common.qh
deleted file mode 100644 (file)
index de02e7a..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (c) 2011 Rudolf Polzer
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-#ifndef CSQCMODELLIB_COMMON_H
-#define CSQCMODELLIB_COMMON_H
-
-#include "../common/csqcmodel_settings.qh"
-
-noref string csqcmodel_license = "\
-Copyright (c) 2011 Rudolf Polzer\
-\
-Permission is hereby granted, free of charge, to any person obtaining a copy\
-of this software and associated documentation files (the \"Software\"), to\
-deal in the Software without restriction, including without limitation the\
-rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\
-sell copies of the Software, and to permit persons to whom the Software is\
-furnished to do so, subject to the following conditions:\
-\
-The above copyright notice and this permission notice shall be included in\
-all copies or substantial portions of the Software.\
-\
-THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\
-FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\
-IN THE SOFTWARE.\
-";
-
-.vector glowmod;
-.vector view_ofs;
-.int frame;
-.float frame1time;
-.int frame2;
-.float frame2time;
-.float lerpfrac;
-
-const int CSQCMODEL_PROPERTY_FRAME = 8388608;
-const int CSQCMODEL_PROPERTY_TELEPORTED = 4194304; // the "teleport bit" cancelling interpolation
-const int CSQCMODEL_PROPERTY_MODELINDEX = 2097152;
-const int CSQCMODEL_PROPERTY_ORIGIN = 1048576;
-const int CSQCMODEL_PROPERTY_YAW = 524288;
-const int CSQCMODEL_PROPERTY_PITCHROLL = 262144;
-const int CSQCMODEL_PROPERTY_FRAME2 = 131072;
-const int CSQCMODEL_PROPERTY_LERPFRAC = 65536;
-const int CSQCMODEL_PROPERTY_SIZE = 32768;
-
-#define ALLPROPERTIES_COMMON \
-       CSQCMODEL_PROPERTY(CSQCMODEL_PROPERTY_FRAME, int, ReadByte, WriteByte, frame) \
-       CSQCMODEL_PROPERTY(CSQCMODEL_PROPERTY_MODELINDEX, int, ReadShort, WriteShort, modelindex) \
-       CSQCMODEL_PROPERTY(CSQCMODEL_PROPERTY_ORIGIN, float, ReadCoord, WriteCoord, origin_x) \
-       CSQCMODEL_PROPERTY(CSQCMODEL_PROPERTY_ORIGIN, float, ReadCoord, WriteCoord, origin_y) \
-       CSQCMODEL_PROPERTY(CSQCMODEL_PROPERTY_ORIGIN, float, ReadCoord, WriteCoord, origin_z) \
-       CSQCMODEL_PROPERTY(CSQCMODEL_PROPERTY_SIZE, float, ReadShort, WriteShort, mins_x) \
-       CSQCMODEL_PROPERTY(CSQCMODEL_PROPERTY_SIZE, float, ReadShort, WriteShort, mins_y) \
-       CSQCMODEL_PROPERTY(CSQCMODEL_PROPERTY_SIZE, float, ReadShort, WriteShort, mins_z) \
-       CSQCMODEL_PROPERTY(CSQCMODEL_PROPERTY_SIZE, float, ReadShort, WriteShort, maxs_x) \
-       CSQCMODEL_PROPERTY(CSQCMODEL_PROPERTY_SIZE, float, ReadShort, WriteShort, maxs_y) \
-       CSQCMODEL_PROPERTY(CSQCMODEL_PROPERTY_SIZE, float, ReadShort, WriteShort, maxs_z) \
-       CSQCMODEL_PROPERTY(CSQCMODEL_PROPERTY_PITCHROLL, float, ReadAngle, WriteAngle, angles_x) \
-       CSQCMODEL_PROPERTY(CSQCMODEL_PROPERTY_YAW, float, ReadAngle, WriteAngle, angles_y) \
-       CSQCMODEL_PROPERTY(CSQCMODEL_PROPERTY_PITCHROLL, float, ReadAngle, WriteAngle, angles_z) \
-       CSQCMODEL_EXTRAPROPERTIES
-
-#ifdef CSQCMODEL_HAVE_TWO_FRAMES
-.float frame3;
-.float frame3time;
-.float lerpfrac3;
-.float frame4;
-.float frame4time;
-.float lerpfrac4;
-#define ALLPROPERTIES ALLPROPERTIES_COMMON \
-       CSQCMODEL_PROPERTY(CSQCMODEL_PROPERTY_FRAME2, int, ReadByte, WriteByte, frame2) \
-       CSQCMODEL_PROPERTY_SCALED(CSQCMODEL_PROPERTY_LERPFRAC, float, ReadByte, WriteByte, lerpfrac, 255, 0, 255)
-#else
-#define ALLPROPERTIES ALLPROPERTIES_COMMON
-#endif
-#endif
diff --git a/qcsrc/csqcmodellib/interpolate.qc b/qcsrc/csqcmodellib/interpolate.qc
deleted file mode 100644 (file)
index 78fb051..0000000
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * Copyright (c) 2011 Rudolf Polzer
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-#if defined(CSQC)
-       #include "../dpdefs/csprogsdefs.qh"
-       #include "../client/defs.qh"
-       #include "../warpzonelib/anglestransform.qh"
-       #include "../client/autocvars.qh"
-       #include "interpolate.qh"
-       #include "cl_model.qh"
-#elif defined(MENUQC)
-#elif defined(SVQC)
-#endif
-
-.vector iorigin1, iorigin2;
-.vector ivelocity1, ivelocity2;
-.vector iforward1, iforward2;
-.vector iup1, iup2;
-.vector ivforward1, ivforward2;
-.vector ivup1, ivup2;
-.float itime1, itime2;
-void InterpolateOrigin_Reset()
-{SELFPARAM();
-       self.iflags &= ~IFLAG_INTERNALMASK;
-       self.itime1 = self.itime2 = 0;
-}
-void InterpolateOrigin_Note()
-{SELFPARAM();
-       float dt;
-       int f0;
-
-       dt = time - self.itime2;
-
-       f0 = self.iflags;
-       if(self.iflags & IFLAG_PREVALID)
-               self.iflags |= IFLAG_VALID;
-       else
-               self.iflags |= IFLAG_PREVALID;
-
-       if(self.iflags & IFLAG_ORIGIN)
-       {
-               self.iorigin1 = self.iorigin2;
-               self.iorigin2 = self.origin;
-       }
-
-       if(self.iflags & IFLAG_AUTOANGLES)
-               if(self.iorigin2 != self.iorigin1)
-                       self.angles = vectoangles(self.iorigin2 - self.iorigin1);
-
-       if(self.iflags & IFLAG_AUTOVELOCITY)
-               if(self.itime2 != self.itime1)
-                       self.velocity = (self.iorigin2 - self.iorigin1) * (1.0 / (self.itime2 - self.itime1));
-
-       if(self.iflags & IFLAG_ANGLES)
-       {
-               fixedmakevectors(self.angles);
-               if(f0 & IFLAG_VALID)
-               {
-                       self.iforward1 = self.iforward2;
-                       self.iup1 = self.iup2;
-               }
-               else
-               {
-                       self.iforward1 = v_forward;
-                       self.iup1 = v_up;
-               }
-               self.iforward2 = v_forward;
-               self.iup2 = v_up;
-       }
-
-       if(self.iflags & IFLAG_V_ANGLE)
-       {
-               fixedmakevectors(self.v_angle);
-               if(f0 & IFLAG_VALID)
-               {
-                       self.ivforward1 = self.ivforward2;
-                       self.ivup1 = self.ivup2;
-               }
-               else
-               {
-                       self.ivforward1 = v_forward;
-                       self.ivup1 = v_up;
-               }
-               self.ivforward2 = v_forward;
-               self.ivup2 = v_up;
-       }
-       else if(self.iflags & IFLAG_V_ANGLE_X)
-       {
-               self.ivforward1_x = self.ivforward2_x;
-               self.ivforward2_x = self.v_angle.x;
-       }
-
-       if(self.iflags & IFLAG_VELOCITY)
-       {
-               self.ivelocity1 = self.ivelocity2;
-               self.ivelocity2 = self.velocity;
-       }
-
-       if(self.iflags & IFLAG_TELEPORTED)
-       {
-               self.iflags &= ~IFLAG_TELEPORTED;
-               self.itime1 = self.itime2 = time; // don't lerp
-       }
-       else if(vlen(self.iorigin2 - self.iorigin1) > 1000)
-       {
-               self.itime1 = self.itime2 = time; // don't lerp
-       }
-       else if((self.iflags & IFLAG_VELOCITY) && (vlen(self.ivelocity2 - self.ivelocity1) > 1000))
-       {
-               self.itime1 = self.itime2 = time; // don't lerp
-       }
-       else if(dt >= 0.2)
-       {
-               self.itime1 = self.itime2 = time;
-       }
-       else
-       {
-               self.itime1 = serverprevtime;
-               self.itime2 = time;
-       }
-}
-void InterpolateOrigin_Do()
-{SELFPARAM();
-       vector forward, up;
-       if(self.itime1 && self.itime2 && self.itime1 != self.itime2)
-       {
-               float f;
-               f = bound(0, (time - self.itime1) / (self.itime2 - self.itime1), 1 + autocvar_cl_lerpexcess);
-               if(self.iflags & IFLAG_ORIGIN)
-                       setorigin(self, (1 - f) * self.iorigin1 + f * self.iorigin2);
-               if(self.iflags & IFLAG_ANGLES)
-               {
-                       forward = (1 - f) * self.iforward1 + f * self.iforward2;
-                       up = (1 - f) * self.iup1 + f * self.iup2;
-                       self.angles = fixedvectoangles2(forward, up);
-               }
-               if(self.iflags & IFLAG_V_ANGLE)
-               {
-                       forward = (1 - f) * self.ivforward1 + f * self.ivforward2;
-                       up = (1 - f) * self.ivup1 + f * self.ivup2;
-                       self.v_angle = fixedvectoangles2(forward, up);
-               }
-               else if(self.iflags & IFLAG_V_ANGLE_X)
-                       self.v_angle_x = (1 - f) * self.ivforward1_x + f * self.ivforward2_x;
-               if(self.iflags & IFLAG_VELOCITY)
-                       self.velocity = (1 - f) * self.ivelocity1 + f * self.ivelocity2;
-       }
-}
-void InterpolateOrigin_Undo()
-{SELFPARAM();
-       if(self.iflags & IFLAG_ORIGIN)
-               setorigin(self, self.iorigin2);
-       if(self.iflags & IFLAG_ANGLES)
-               self.angles = fixedvectoangles2(self.iforward2, self.iup2);
-       if(self.iflags & IFLAG_V_ANGLE)
-               self.v_angle = fixedvectoangles2(self.ivforward2, self.ivup2);
-       else if(self.iflags & IFLAG_V_ANGLE_X)
-               self.v_angle_x = self.ivforward2_x;
-       if(self.iflags & IFLAG_VELOCITY)
-               self.velocity = self.ivelocity2;
-}
-
diff --git a/qcsrc/csqcmodellib/interpolate.qh b/qcsrc/csqcmodellib/interpolate.qh
deleted file mode 100644 (file)
index 5ee5785..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (c) 2011 Rudolf Polzer
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-#ifndef INTERPOLATE_H
-#define INTERPOLATE_H
-
-.int iflags;
-const int IFLAG_VELOCITY = 1;
-const int IFLAG_ANGLES = 2;
-const int IFLAG_AUTOANGLES = 4;
-const int IFLAG_VALID = 8;
-const int IFLAG_PREVALID = 16;
-const int IFLAG_TELEPORTED = 32;
-const int IFLAG_AUTOVELOCITY = 64;
-const int IFLAG_V_ANGLE = 128;
-const int IFLAG_V_ANGLE_X = 256;
-const int IFLAG_ORIGIN = 512;
-#define IFLAG_INTERNALMASK (IFLAG_VALID | IFLAG_PREVALID)
-
-// call this BEFORE reading an entity update
-void InterpolateOrigin_Undo();
-
-// call this AFTER receiving an entity update
-void InterpolateOrigin_Note();
-
-// call this when the entity got teleported, before InterpolateOrigin_Note
-void InterpolateOrigin_Reset();
-
-// call this BEFORE drawing
-void InterpolateOrigin_Do();
-
-// in case we interpolate that:
-.vector v_angle;
-#endif
diff --git a/qcsrc/csqcmodellib/settings.qh b/qcsrc/csqcmodellib/settings.qh
deleted file mode 100644 (file)
index b30d7e9..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-#ifndef CSQCMODELLIB_SETTINGS_H
-#define CSQCMODELLIB_SETTINGS_H
-// define this if svqc code wants to use .frame2 and .lerpfrac
-//#define CSQCMODEL_HAVE_TWO_FRAMES
-
-// don't define this ever
-//#define CSQCMODEL_SUPPORT_GETTAGINFO_BEFORE_DRAW
-
-// add properties you want networked to CSQC here
-#define CSQCMODEL_EXTRAPROPERTIES \
-       /* CSQCMODEL_PROPERTY(1, float, ReadShort, WriteShort, colormap) */ \
-       /* CSQCMODEL_PROPERTY(2, float, ReadInt24_t, WriteInt24_t, effects) */
-
-// add hook function calls here
-#define CSQCMODEL_HOOK_PREUPDATE
-#define CSQCMODEL_HOOK_POSTUPDATE
-#define CSQCMODEL_HOOK_PREDRAW
-#define CSQCPLAYER_HOOK_POSTCAMERASETUP
-
-// force updates of player entities that often even if unchanged
-#define CSQCPLAYER_FORCE_UPDATES 0.25
-
-// mod must define:
-//vector PL_MIN  = ...;
-//vector PL_MAX  = ...;
-//vector PL_VIEW_OFS  = ...;
-//vector PL_CROUCH_MIN  = ...;
-//vector PL_CROUCH_MAX  = ...;
-//vector PL_CROUCH_VIEW_OFS  = ...;
-#endif
diff --git a/qcsrc/csqcmodellib/sv_model.qc b/qcsrc/csqcmodellib/sv_model.qc
deleted file mode 100644 (file)
index ebe0b6e..0000000
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Copyright (c) 2011 Rudolf Polzer
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#if defined(CSQC)
-#elif defined(MENUQC)
-#elif defined(SVQC)
-       #include "../dpdefs/progsdefs.qh"
-       #include "../dpdefs/dpextensions.qh"
-       #include "../common/constants.qh"
-       #include "../common/util.qh"
-       #include "../common/animdecide.qh"
-       #include "../server/constants.qh"
-       #include "../server/defs.qh"
-       #include "common.qh"
-       #include "sv_model.qh"
-#endif
-
-// generic CSQC model code
-
-bool CSQCModel_Send(entity to, int sf)
-{SELFPARAM();
-       // some nice flags for CSQCMODEL_IF
-       float isplayer = (IS_CLIENT(self));
-       float islocalplayer = (self == to);
-       float isnolocalplayer = (isplayer && (self != to));
-
-       unused_float = isplayer;
-       unused_float = islocalplayer;
-       unused_float = isnolocalplayer;
-
-       WriteByte(MSG_ENTITY, ENT_CLIENT_MODEL);
-       WriteInt24_t(MSG_ENTITY, sf);
-
-#define CSQCMODEL_IF(cond) if(cond) {
-#define CSQCMODEL_ENDIF }
-#define CSQCMODEL_PROPERTY(flag,t,r,w,f) \
-       if(sf & flag) \
-       { \
-               w(MSG_ENTITY, self.csqcmodel_##f); \
-       }
-#define CSQCMODEL_PROPERTY_SCALED(flag,t,r,w,f,s,mi,ma) CSQCMODEL_PROPERTY(flag,t,r,w,f)
-       ALLPROPERTIES
-#undef CSQCMODEL_PROPERTY_SCALED
-#undef CSQCMODEL_PROPERTY
-#undef CSQCMODEL_ENDIF
-#undef CSQCMODEL_IF
-
-       return true;
-}
-
-#ifdef CSQCPLAYER_FORCE_UPDATES
-.float csqcmodel_nextforcedupdate;
-#endif
-void CSQCModel_CheckUpdate(entity e)
-{
-       // some nice flags for CSQCMODEL_IF
-       float isplayer = (IS_CLIENT(e));
-       float islocalplayer = isplayer; // we set BOTH to 1 here as we need the sendflags
-       float isnolocalplayer = isplayer; // we set BOTH to 1 here as we need the sendflags
-
-       unused_float = isplayer;
-       unused_float = islocalplayer;
-       unused_float = isnolocalplayer;
-
-#ifdef CSQCPLAYER_FORCE_UPDATES
-       if(isplayer && time > e.csqcmodel_nextforcedupdate)
-       {
-               e.SendFlags |= CSQCMODEL_PROPERTY_ORIGIN;
-               e.csqcmodel_nextforcedupdate = time + CSQCPLAYER_FORCE_UPDATES * (0.5 + random()); // ensure about 4 origin sends per sec
-       }
-#endif
-
-       if(e.effects & EF_RESTARTANIM_BIT)
-       {
-               e.SendFlags |= CSQCMODEL_PROPERTY_FRAME | CSQCMODEL_PROPERTY_FRAME2; // full anim resend please
-               e.effects &= ~EF_RESTARTANIM_BIT;
-       }
-
-       if(e.effects & EF_TELEPORT_BIT)
-       {
-               e.SendFlags |= CSQCMODEL_PROPERTY_TELEPORTED; // no interpolation please
-               e.effects &= ~EF_TELEPORT_BIT;
-       }
-
-#define CSQCMODEL_IF(cond) if(cond) {
-#define CSQCMODEL_ENDIF }
-#define CSQCMODEL_PROPERTY(flag,t,r,w,f) \
-       { \
-               t tmp = e.f; \
-               if(tmp != e.csqcmodel_##f) \
-               { \
-                       e.csqcmodel_##f = tmp; \
-                       e.SendFlags |= flag; \
-               } \
-       }
-#define CSQCMODEL_PROPERTY_SCALED(flag,t,r,w,f,s,mi,ma) \
-       { \
-               t tmp = rint(bound(mi, s * e.f, ma) - mi); \
-               if(tmp != e.csqcmodel_##f) \
-               { \
-                       e.csqcmodel_##f = tmp; \
-                       e.SendFlags |= flag; \
-               } \
-       }
-       ALLPROPERTIES
-#undef CSQCMODEL_PROPERTY_SCALED
-#undef CSQCMODEL_PROPERTY
-#undef CSQCMODEL_ENDIF
-#undef CSQCMODEL_IF
-}
-
-void CSQCModel_LinkEntity(entity e)
-{
-       e.SendEntity = CSQCModel_Send;
-       e.SendFlags = 0xFFFFFF;
-       CSQCModel_CheckUpdate(e);
-}
-
-void CSQCModel_UnlinkEntity(entity e)
-{
-       e.SendEntity = func_null;
-}
diff --git a/qcsrc/csqcmodellib/sv_model.qh b/qcsrc/csqcmodellib/sv_model.qh
deleted file mode 100644 (file)
index 713e8c2..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 2011 Rudolf Polzer
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
- #ifndef SV_MODEL_H
- #define SV_MODEL_H
-
- #include "common.qh"
-
-// generic CSQC model code
-
-void CSQCModel_CheckUpdate(entity e);
-void CSQCModel_LinkEntity(entity e);
-void CSQCModel_UnlinkEntity(entity e);
-
-#define CSQCMODEL_IF(cond)
-#define CSQCMODEL_ENDIF
-#define CSQCMODEL_PROPERTY(flag,t,r,w,f) \
-       .t f; \
-       .t csqcmodel_##f;
-#define CSQCMODEL_PROPERTY_SCALED(flag,t,r,w,f,s,mi,ma) CSQCMODEL_PROPERTY(flag,t,r,w,f)
-       ALLPROPERTIES
-#undef CSQCMODEL_PROPERTY_SCALED
-#undef CSQCMODEL_PROPERTY
-#undef CSQCMODEL_ENDIF
-#undef CSQCMODEL_IF
-#endif
index c00c5a12afff460286089191ddc4912ae06c04ea..49b8ef7798bccac4f833edb868f31cb79c7161fd 100644 (file)
@@ -1,18 +1,49 @@
-#include "bool.qh"
+#ifndef NOCOMPAT
+    #define COMPAT_NO_MOD_IS_XONOTIC
+#endif
+
+#include "compiler.qh"
+
+#ifndef QCC_SUPPORT_INT
+    #define int float
+#endif
+
+#ifndef QCC_SUPPORT_BOOL
+    #define bool float
+#endif
 
-#include "../warpzonelib/mathlib.qc"
+#if defined(CSQC)
+    #include "../dpdefs/csprogsdefs.qh"
+    #include "../dpdefs/keycodes.qh"
+#elif defined(SVQC)
+    #include "../server/sys-pre.qh"
+    #include "../dpdefs/progsdefs.qh"
+    #include "../dpdefs/dpextensions.qh"
+    #include "../server/sys-post.qh"
+#elif defined(MENUQC)
+    #include "../dpdefs/menudefs.qh"
+    #include "../dpdefs/keycodes.qh"
+#endif
+
+#include "warpzone/mathlib.qc"
 
 #include "accumulate.qh"
 #include "bits.qh"
+#include "bool.qh"
+#include "color.qh"
 #include "counting.qh"
 #include "cvar.qh"
 #include "defer.qh"
 #include "draw.qh"
 #include "file.qh"
+#include "functional.qh"
 #include "i18n.qh"
+#include "int.qh"
+#include "iter.qh"
 #include "lazy.qh"
 #include "log.qh"
 #include "math.qh"
+#include "misc.qh"
 #include "net.qh"
 #include "nil.qh"
 #include "noise.qc"
@@ -23,8 +54,9 @@
 #include "random.qc"
 #include "registry.qh"
 #include "replicate.qh"
-#include "sort.qh"
+#include "self.qh"
 #include "sortlist.qc"
+#include "sort.qh"
 #include "spawnfunc.qh"
 #include "static.qh"
 #include "string.qh"
index 26169cd199e61328ca0699c3946938a786e7691e..7a719af409ca1aaa49cc602518ab12529341495f 100644 (file)
@@ -2,8 +2,6 @@
 #define BOOL_H
 
 #ifndef QCC_SUPPORT_BOOL
-    #define bool float
-
     // Boolean Constants
     const int true     = 1;
     const int false = 0;
diff --git a/qcsrc/lib/color.qh b/qcsrc/lib/color.qh
new file mode 100644 (file)
index 0000000..d21dab8
--- /dev/null
@@ -0,0 +1,38 @@
+#ifndef COLOR_H
+#define COLOR_H
+
+#define colormapPaletteColor(c, isPants) colormapPaletteColor_(c, isPants, time)
+vector colormapPaletteColor_(int c, bool isPants, float t)
+{
+    switch (c) {
+        case  0: return '1.000000 1.000000 1.000000';
+        case  1: return '1.000000 0.333333 0.000000';
+        case  2: return '0.000000 1.000000 0.501961';
+        case  3: return '0.000000 1.000000 0.000000';
+        case  4: return '1.000000 0.000000 0.000000';
+        case  5: return '0.000000 0.666667 1.000000';
+        case  6: return '0.000000 1.000000 1.000000';
+        case  7: return '0.501961 1.000000 0.000000';
+        case  8: return '0.501961 0.000000 1.000000';
+        case  9: return '1.000000 0.000000 1.000000';
+        case 10: return '1.000000 0.000000 0.501961';
+        case 11: return '0.000000 0.000000 1.000000';
+        case 12: return '1.000000 1.000000 0.000000';
+        case 13: return '0.000000 0.333333 1.000000';
+        case 14: return '1.000000 0.666667 0.000000';
+        case 15:
+            if (isPants)
+                return
+                      '1 0 0' * (0.502 + 0.498 * sin(t / 2.7182818285 + 0.0000000000))
+                    + '0 1 0' * (0.502 + 0.498 * sin(t / 2.7182818285 + 2.0943951024))
+                    + '0 0 1' * (0.502 + 0.498 * sin(t / 2.7182818285 + 4.1887902048));
+            else
+                return
+                      '1 0 0' * (0.502 + 0.498 * sin(t / 3.1415926536 + 5.2359877560))
+                    + '0 1 0' * (0.502 + 0.498 * sin(t / 3.1415926536 + 3.1415926536))
+                    + '0 0 1' * (0.502 + 0.498 * sin(t / 3.1415926536 + 1.0471975512));
+        default: return '0.000 0.000 0.000';
+    }
+}
+
+#endif
diff --git a/qcsrc/lib/compiler.qh b/qcsrc/lib/compiler.qh
new file mode 100644 (file)
index 0000000..69aad5c
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef COMPILER_H
+#define COMPILER_H
+
+#ifndef QCC_SUPPORT_ACCUMULATE
+    #ifdef GMQCC
+        #define QCC_SUPPORT_ACCUMULATE
+    #endif
+#endif
+
+#ifndef QCC_SUPPORT_NIL
+    #ifdef GMQCC
+        #define QCC_SUPPORT_NIL
+    #endif
+#endif
+
+#endif
diff --git a/qcsrc/lib/csqcmodel/cl_model.qc b/qcsrc/lib/csqcmodel/cl_model.qc
new file mode 100644 (file)
index 0000000..8d3d4ab
--- /dev/null
@@ -0,0 +1,287 @@
+/*
+ * Copyright (c) 2011 Rudolf PolzerCSQCModel_InterpolateAnimation_2To4_PreNote
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+#include "cl_model.qh"
+
+#include "cl_player.qh"
+#include "common.qh"
+#include "interpolate.qh"
+#include "../../client/defs.qh"
+#include "../../common/animdecide.qh"
+#include "../../common/csqcmodel_settings.qh"
+#include "../../common/util.qh"
+
+float autocvar_cl_lerpanim_maxdelta_framegroups = 0.1;
+float autocvar_cl_nolerp = 0;
+
+.float csqcmodel_lerpfrac;
+.float csqcmodel_lerpfrac2;
+.float csqcmodel_lerpfractime;
+.float csqcmodel_lerpfrac2time;
+
+void CSQCModel_InterpolateAnimation_2To4_PreNote(int sf)
+{SELFPARAM();
+       if(sf & CSQCMODEL_PROPERTY_FRAME)
+       {
+               self.frame3 = self.frame;
+               self.frame3time = self.frame1time;
+       }
+       if(sf & CSQCMODEL_PROPERTY_FRAME2)
+       {
+               self.frame4 = self.frame2;
+               self.frame4time = self.frame2time;
+       }
+       if(sf & CSQCMODEL_PROPERTY_LERPFRAC)
+       {
+               self.csqcmodel_lerpfrac2 = self.csqcmodel_lerpfrac;
+               self.csqcmodel_lerpfrac2time = self.csqcmodel_lerpfractime;
+               self.lerpfrac = self.csqcmodel_lerpfrac;
+       }
+}
+void CSQCModel_InterpolateAnimation_1To2_PreNote(int sf)
+{SELFPARAM();
+       if(sf & CSQCMODEL_PROPERTY_FRAME)
+       {
+               self.frame2 = self.frame;
+               self.frame2time = self.frame1time;
+       }
+}
+void CSQCModel_InterpolateAnimation_PreNote(int sf)
+{
+#ifdef CSQCMODEL_HAVE_TWO_FRAMES
+       CSQCModel_InterpolateAnimation_2To4_PreNote(sf);
+#else
+       CSQCModel_InterpolateAnimation_1To2_PreNote(sf);
+#endif
+}
+
+void CSQCModel_InterpolateAnimation_2To4_Note(int sf, float set_times)
+{SELFPARAM();
+       if(sf & CSQCMODEL_PROPERTY_FRAME)
+       {
+               if(set_times)
+                       self.frame1time = time;
+       }
+       if(sf & CSQCMODEL_PROPERTY_FRAME2)
+       {
+               if(set_times)
+                       self.frame2time = time;
+       }
+       if(sf & CSQCMODEL_PROPERTY_LERPFRAC)
+       {
+               self.csqcmodel_lerpfrac = self.lerpfrac;
+               if(set_times)
+                       self.csqcmodel_lerpfractime = time;
+       }
+}
+void CSQCModel_InterpolateAnimation_1To2_Note(int sf, float set_times)
+{SELFPARAM();
+       if(sf & CSQCMODEL_PROPERTY_FRAME)
+       {
+               if(set_times)
+                       self.frame1time = time;
+       }
+}
+void CSQCModel_InterpolateAnimation_Note(int sf)
+{
+#ifdef CSQCMODEL_HAVE_TWO_FRAMES
+       CSQCModel_InterpolateAnimation_2To4_Note(sf, true);
+#else
+       CSQCModel_InterpolateAnimation_1To2_Note(sf, true);
+#endif
+}
+
+void CSQCModel_InterpolateAnimation_2To4_Do()
+{SELFPARAM();
+       if(autocvar_cl_nolerp || (autocvar_cl_lerpanim_maxdelta_framegroups == 0))
+       {
+               self.lerpfrac = self.csqcmodel_lerpfrac;
+               self.lerpfrac3 = 0;
+               self.lerpfrac4 = 0;
+       }
+       else
+       {
+               float l13, l24, llf;
+               float l24_13;
+
+               if(self.frame3time == 0) // if frame1/3 were not previously displayed, only frame1 can make sense
+                       l13 = 1;
+               else
+                       l13 = bound(0, (time - self.frame1time) / autocvar_cl_lerpanim_maxdelta_framegroups, 1);
+
+               if(self.frame4time == 0) // if frame2/4 were not previously displayed, only frame2 can make sense
+                       l24 = 1;
+               else
+                       l24 = bound(0, (time - self.frame2time) / autocvar_cl_lerpanim_maxdelta_framegroups, 1);
+
+               if(self.csqcmodel_lerpfrac2time == 0) // if there is no old lerpfrac (newly displayed model), only lerpfrac makes sense
+                       llf = 1;
+               else
+                       llf = bound(0, (time - self.csqcmodel_lerpfractime) / autocvar_cl_lerpanim_maxdelta_framegroups, 1);
+
+               l24_13 = self.csqcmodel_lerpfrac * llf + self.csqcmodel_lerpfrac2 * (1 - llf);
+
+               self.lerpfrac  = l24 * l24_13;
+               self.lerpfrac4 = (1 - l24) * l24_13;
+               self.lerpfrac3 = (1 - l13) * (1 - l24_13);
+
+               if(l24_13 == 0) // if frames 2/4 are not displayed, clear their frametime
+               {
+                       self.frame2time = 0;
+                       self.frame4time = 0;
+               }
+
+               if(l24_13 == 1) // if frames 1/3 are not displayed, clear their frametime
+               {
+                       self.frame1time = 0;
+                       self.frame3time = 0;
+               }
+       }
+}
+void CSQCModel_InterpolateAnimation_1To2_Do()
+{SELFPARAM();
+       if(autocvar_cl_nolerp || (autocvar_cl_lerpanim_maxdelta_framegroups == 0))
+       {
+               self.lerpfrac = 0;
+       }
+       else
+       {
+               if(self.frame2time == 0) // if frame2 was not previously displayed, only frame1 can make sense
+                       self.lerpfrac = 0;
+               else
+                       self.lerpfrac = 1 - bound(0, (time - self.frame1time) / autocvar_cl_lerpanim_maxdelta_framegroups, 1);
+       }
+}
+void CSQCModel_InterpolateAnimation_Do()
+{
+#ifdef CSQCMODEL_HAVE_TWO_FRAMES
+       CSQCModel_InterpolateAnimation_2To4_Do();
+#else
+       CSQCModel_InterpolateAnimation_1To2_Do();
+#endif
+}
+
+void CSQCModel_Draw()
+{SELFPARAM();
+       // some nice flags for CSQCMODEL_IF and the hooks
+       bool isplayer = (self.entnum >= 1 && self.entnum <= maxclients);
+       noref bool islocalplayer = (self.entnum == player_localnum + 1);
+       noref bool isnolocalplayer = (isplayer && (self.entnum != player_localnum + 1));
+
+       // we don't do this for the local player as that one is already handled
+       // by CSQCPlayer_SetCamera()
+       if(!CSQCPlayer_IsLocalPlayer())
+               InterpolateOrigin_Do();
+
+       CSQCModel_InterpolateAnimation_Do();
+
+       { CSQCMODEL_HOOK_PREDRAW }
+
+       // inherit draw flags easily
+       entity root = self;
+       while(root.tag_entity)
+               root = root.tag_entity;
+       if(self != root)
+       {
+               self.renderflags &= ~(RF_EXTERNALMODEL | RF_VIEWMODEL);
+               self.renderflags |= (root.renderflags & (RF_EXTERNALMODEL | RF_VIEWMODEL));
+       }
+
+       // we're drawn, now teleporting is over
+       self.csqcmodel_teleported = 0;
+}
+
+void CSQCModel_Read(bool isnew)
+{SELFPARAM();
+       int sf = ReadInt24_t();
+
+       // some nice flags for CSQCMODEL_IF and the hooks
+       bool isplayer = (self.entnum >= 1 && self.entnum <= maxclients);
+       bool islocalplayer = (self.entnum == player_localnum + 1);
+       noref bool isnolocalplayer = (isplayer && (self.entnum != player_localnum + 1));
+
+       self.classname = "csqcmodel";
+       self.iflags |= IFLAG_ORIGIN; // interpolate origin too
+       self.iflags |= IFLAG_ANGLES; // interpolate angles too
+       self.iflags |= IFLAG_VELOCITY | IFLAG_AUTOVELOCITY; // let's calculate velocity automatically
+
+       { CSQCMODEL_HOOK_PREUPDATE }
+
+       CSQCPlayer_PreUpdate();
+       InterpolateOrigin_Undo();
+       CSQCModel_InterpolateAnimation_PreNote(sf);
+
+#define CSQCMODEL_IF(cond) if(cond) {
+#define CSQCMODEL_ENDIF }
+#define CSQCMODEL_PROPERTY(flag,t,r,w,f) \
+       if(sf & flag) \
+               self.f = r();
+#define CSQCMODEL_PROPERTY_SCALED(flag,t,r,w,f,s,mi,ma) \
+       if(sf & flag) \
+               self.f = (r() + mi) / s;
+       ALLPROPERTIES
+#undef CSQCMODEL_PROPERTY_SCALED
+#undef CSQCMODEL_PROPERTY
+#undef CSQCMODEL_ENDIF
+#undef CSQCMODEL_IF
+
+       if(sf & CSQCMODEL_PROPERTY_MODELINDEX)
+       {
+               vector pmin = self.mins, pmax = self.maxs;
+               setmodelindex(self, self.modelindex); // this retrieves the .model key and sets mins/maxs/absmin/absmax
+               setsize(self, pmin, pmax);
+       }
+
+       if(sf & CSQCMODEL_PROPERTY_TELEPORTED)
+       {
+               self.iflags |= IFLAG_TELEPORTED;
+               self.csqcmodel_teleported = 1;
+       }
+
+       CSQCModel_InterpolateAnimation_Note(sf);
+       InterpolateOrigin_Note();
+       CSQCPlayer_PostUpdate();
+
+       { CSQCMODEL_HOOK_POSTUPDATE }
+
+#ifdef CSQCMODEL_SUPPORT_GETTAGINFO_BEFORE_DRAW
+       InterpolateOrigin_Do();
+       CSQCModel_InterpolateAnimation_Do();
+#endif
+
+       // relink
+       setorigin(self, self.origin);
+
+       // set obvious render flags
+       if(self.entnum == player_localentnum)
+               self.renderflags |= RF_EXTERNALMODEL;
+       else
+               self.renderflags &= ~RF_EXTERNALMODEL;
+
+       // draw it
+       self.drawmask = MASK_NORMAL;
+       self.predraw = CSQCModel_Draw;
+}
+
+entity CSQCModel_server2csqc(float pl)
+{
+       return findfloat(world, entnum, pl); // FIXME optimize this using an array
+}
diff --git a/qcsrc/lib/csqcmodel/cl_model.qh b/qcsrc/lib/csqcmodel/cl_model.qh
new file mode 100644 (file)
index 0000000..55401e4
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2011 Rudolf Polzer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+#ifndef LIB_CSQCMODEL_CL_MODEL_H
+#define LIB_CSQCMODEL_CL_MODEL_H
+
+#include "common.qh"
+
+void CSQCModel_Read(bool isnew);
+
+#define CSQCMODEL_IF(cond)
+#define CSQCMODEL_ENDIF
+#define CSQCMODEL_PROPERTY(flag,t,r,w,f) \
+       .t f;
+#define CSQCMODEL_PROPERTY_SCALED(flag,t,r,w,f,s,mi,ma) CSQCMODEL_PROPERTY(flag,t,r,w,f)
+       ALLPROPERTIES
+#undef CSQCMODEL_PROPERTY_SCALED
+#undef CSQCMODEL_PROPERTY
+#undef CSQCMODEL_ENDIF
+#undef CSQCMODEL_IF
+
+entity CSQCModel_server2csqc(float pl);
+.float csqcmodel_teleported;
+
+// this is exported for custom frame animation code. Use with care.
+// to update frames, first call this:
+void CSQCModel_InterpolateAnimation_2To4_PreNote(int sf);
+void CSQCModel_InterpolateAnimation_1To2_PreNote(int sf);
+// then update frame, frame1time (and possibly frame2, frame2time, lerpfrac)
+// if set_times is not set, caller is responsible for frame1time, frame2time, csqcmodel_lerpfractime!
+void CSQCModel_InterpolateAnimation_2To4_Note(int sf, float set_times);
+void CSQCModel_InterpolateAnimation_1To2_Note(int sf, float set_times);
+// to retrieve animation state, call this
+void CSQCModel_InterpolateAnimation_2To4_Do();
+void CSQCModel_InterpolateAnimation_1To2_Do();
+// will overwrite lerpfrac, lerpfrac3, lerpfrac4, and possibly clear frame*time if they are undisplayed according to lerpfracs
+#endif
diff --git a/qcsrc/lib/csqcmodel/cl_player.qc b/qcsrc/lib/csqcmodel/cl_player.qc
new file mode 100644 (file)
index 0000000..ae4e55a
--- /dev/null
@@ -0,0 +1,363 @@
+/*
+ * Copyright (c) 2011 Rudolf Polzer
+ * Copyright (c) 2015 Micah Talkiewicz
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+#include "cl_player.qh"
+
+#include "cl_model.qh"
+#include "common.qh"
+#include "interpolate.qh"
+#include "../../client/defs.qh"
+#include "../../client/main.qh"
+#include "../../common/constants.qh"
+#include "../../common/stats.qh"
+#include "../../common/triggers/trigger/viewloc.qh"
+#include "../../common/util.qh"
+#include "../../common/viewloc.qh"
+
+float autocvar_cl_movement_errorcompensation = 0;
+int autocvar_cl_movement = 1;
+
+// engine stuff
+float pmove_onground; // weird engine flag we shouldn't really use but have to for now
+
+vector csqcplayer_origin, csqcplayer_velocity;
+float csqcplayer_sequence;
+int player_pmflags;
+float csqcplayer_moveframe;
+vector csqcplayer_predictionerroro;
+vector csqcplayer_predictionerrorv;
+float csqcplayer_predictionerrortime;
+float csqcplayer_predictionerrorfactor;
+
+vector CSQCPlayer_GetPredictionErrorO()
+{
+       if(time >= csqcplayer_predictionerrortime)
+               return '0 0 0';
+       return csqcplayer_predictionerroro * (csqcplayer_predictionerrortime - time) * csqcplayer_predictionerrorfactor;
+}
+
+vector CSQCPlayer_GetPredictionErrorV()
+{
+       if(time >= csqcplayer_predictionerrortime)
+               return '0 0 0';
+       return csqcplayer_predictionerrorv * (csqcplayer_predictionerrortime - time) * csqcplayer_predictionerrorfactor;
+}
+
+void CSQCPlayer_SetPredictionError(vector o, vector v, float onground_diff)
+{
+       // error too big to compensate, we LIKELY hit a teleport or a
+       // jumppad, or it's a jump time disagreement that'll get fixed
+       // next frame
+
+       // FIXME we sometimes have disagreement in order of jump velocity. Do not act on them!
+       /*
+       // commented out as this one did not help
+       if(onground_diff)
+       {
+               printf("ONGROUND MISMATCH: %d x=%v v=%v\n", onground_diff, o, v);
+               return;
+       }
+       */
+       if(vlen(o) > 32 || vlen(v) > 192)
+       {
+               //printf("TOO BIG: x=%v v=%v\n", o, v);
+               return;
+       }
+
+       if(!autocvar_cl_movement_errorcompensation)
+       {
+               csqcplayer_predictionerrorfactor = 0;
+               return;
+       }
+
+       csqcplayer_predictionerroro = CSQCPlayer_GetPredictionErrorO() + o;
+       csqcplayer_predictionerrorv = CSQCPlayer_GetPredictionErrorV() + v;
+       csqcplayer_predictionerrorfactor = autocvar_cl_movement_errorcompensation / ticrate;
+       csqcplayer_predictionerrortime = time + 1.0 / csqcplayer_predictionerrorfactor;
+}
+
+void CSQCPlayer_Unpredict()
+{SELFPARAM();
+       if(csqcplayer_status == CSQCPLAYERSTATUS_UNPREDICTED)
+               return;
+       if(csqcplayer_status != CSQCPLAYERSTATUS_PREDICTED)
+               error("Cannot unpredict in current status");
+       self.origin = csqcplayer_origin;
+       self.velocity = csqcplayer_velocity;
+       csqcplayer_moveframe = csqcplayer_sequence+1; //+1 because the recieved frame has the move already done (server side)
+       self.flags = player_pmflags;
+}
+
+void CSQCPlayer_SetMinsMaxs()
+{SELFPARAM();
+       if(self.flags & FL_DUCKED)
+       {
+               self.mins = PL_CROUCH_MIN;
+               self.maxs = PL_CROUCH_MAX;
+               self.view_ofs = PL_CROUCH_VIEW_OFS;
+       }
+       else
+       {
+               self.mins = PL_MIN;
+               self.maxs = PL_MAX;
+               self.view_ofs = PL_VIEW_OFS;
+       }
+}
+
+void CSQCPlayer_SavePrediction()
+{SELFPARAM();
+       player_pmflags = self.flags;
+       csqcplayer_origin = self.origin;
+       csqcplayer_velocity = self.velocity;
+       csqcplayer_sequence = servercommandframe;
+       csqcplayer_status = CSQCPLAYERSTATUS_PREDICTED;
+}
+
+void CSQC_ClientMovement_PlayerMove_Frame();
+
+void PM_Movement_Move()
+{SELFPARAM();
+       runstandardplayerphysics(self);
+#ifdef CSQC
+       self.flags =
+                       ((self.pmove_flags & PMF_DUCKED) ? FL_DUCKED : 0) |
+                       (!(self.pmove_flags & PMF_JUMP_HELD) ? FL_JUMPRELEASED : 0) |
+                       ((self.pmove_flags & PMF_ONGROUND) ? FL_ONGROUND : 0);
+#endif
+}
+
+void CSQCPlayer_Physics(void)
+{
+       switch(autocvar_cl_movement)
+       {
+               case 1: CSQC_ClientMovement_PlayerMove_Frame(); break;
+               case 2: PM_Movement_Move(); break;
+       }
+}
+
+void CSQCPlayer_PredictTo(float endframe, float apply_error)
+{SELFPARAM();
+       CSQCPlayer_Unpredict();
+       if(apply_error)
+       {
+               self.origin += CSQCPlayer_GetPredictionErrorO();
+               self.velocity += CSQCPlayer_GetPredictionErrorV();
+       }
+       CSQCPlayer_SetMinsMaxs();
+
+       csqcplayer_status = CSQCPLAYERSTATUS_PREDICTED;
+
+#if 0
+       // we don't need this
+       // darkplaces makes servercommandframe == 0 in these cases anyway
+       if (getstatf(STAT_HEALTH) <= 0)
+       {
+               csqcplayer_moveframe = clientcommandframe;
+               getinputstate(csqcplayer_moveframe-1);
+               LOG_INFO("the Weird code path got hit\n");
+               return;
+       }
+#endif
+
+       if(csqcplayer_moveframe >= endframe)
+       {
+               getinputstate(csqcplayer_moveframe - 1);
+       }
+       else
+       {
+               do
+               {
+                       if (!getinputstate(csqcplayer_moveframe))
+                               break;
+                       CSQCPlayer_Physics();
+                       CSQCPlayer_SetMinsMaxs();
+                       csqcplayer_moveframe++;
+               }
+               while(csqcplayer_moveframe < endframe);
+       }
+
+       //add in anything that was applied after (for low packet rate protocols)
+       input_angles = view_angles;
+}
+
+bool CSQCPlayer_IsLocalPlayer()
+{SELFPARAM();
+       return (self == csqcplayer);
+}
+
+void CSQCPlayer_SetViewLocation()
+{
+       viewloc_SetViewLocation();
+}
+
+void CSQCPlayer_SetCamera()
+{SELFPARAM();
+       vector v0;
+       v0 = pmove_vel; // TRICK: pmove_vel is set by the engine when we get here. No need to network velocity
+
+       if(csqcplayer)
+       {
+               setself(csqcplayer);
+
+               if(servercommandframe == 0 || clientcommandframe == 0)
+               {
+                       InterpolateOrigin_Do();
+                       self.view_ofs = '0 0 1' * getstati(STAT_VIEWHEIGHT);
+
+                       // get crouch state from the server
+                       if(getstati(STAT_VIEWHEIGHT) == PL_VIEW_OFS.z)
+                               self.flags &= ~FL_DUCKED;
+                       else if(getstati(STAT_VIEWHEIGHT) == PL_CROUCH_VIEW_OFS.z)
+                               self.flags |= FL_DUCKED;
+
+                       // get onground state from the server
+                       if(pmove_onground)
+                               self.flags |= FL_ONGROUND;
+                       else
+                               self.flags &= ~FL_ONGROUND;
+
+                       CSQCPlayer_SetMinsMaxs();
+
+                       // override it back just in case
+                       self.view_ofs = '0 0 1' * getstati(STAT_VIEWHEIGHT);
+
+                       // set velocity
+                       self.velocity = v0;
+               }
+               else
+               {
+                       float flg = self.iflags;
+                       self.iflags &= ~(IFLAG_ORIGIN | IFLAG_ANGLES);
+                       InterpolateOrigin_Do();
+                       self.iflags = flg;
+
+                       if(csqcplayer_status == CSQCPLAYERSTATUS_FROMSERVER)
+                       {
+                               vector o, v;
+                               o = self.origin;
+                               v = v0;
+                               csqcplayer_status = CSQCPLAYERSTATUS_PREDICTED;
+                               CSQCPlayer_PredictTo(servercommandframe + 1, false);
+                               CSQCPlayer_SetPredictionError(self.origin - o, self.velocity - v, pmove_onground - !!(self.flags & FL_ONGROUND));
+                               self.origin = o;
+                               self.velocity = v;
+
+                               // get crouch state from the server
+                               if(getstati(STAT_VIEWHEIGHT) == PL_VIEW_OFS.z)
+                                       self.flags &= ~FL_DUCKED;
+                               else if(getstati(STAT_VIEWHEIGHT) == PL_CROUCH_VIEW_OFS.z)
+                                       self.flags |= FL_DUCKED;
+
+                               // get onground state from the server
+                               if(pmove_onground)
+                                       self.flags |= FL_ONGROUND;
+                               else
+                                       self.flags &= ~FL_ONGROUND;
+
+                               CSQCPlayer_SavePrediction();
+                       }
+                       CSQCPlayer_PredictTo(clientcommandframe + 1, true);
+
+#ifdef CSQCMODEL_SERVERSIDE_CROUCH
+                       // get crouch state from the server (LAG)
+                       if(getstati(STAT_VIEWHEIGHT) == PL_VIEW_OFS.z)
+                               self.flags &= ~FL_DUCKED;
+                       else if(getstati(STAT_VIEWHEIGHT) == PL_CROUCH_VIEW_OFS.z)
+                               self.flags |= FL_DUCKED;
+#endif
+
+                       CSQCPlayer_SetMinsMaxs();
+
+                       self.angles_y = input_angles.y;
+               }
+
+               // relink
+               setorigin(self, self.origin);
+
+               setself(this);
+       }
+
+       entity view = CSQCModel_server2csqc(player_localentnum);
+
+       if(view && view != csqcplayer)
+       {
+               WITH(entity, self, view, InterpolateOrigin_Do());
+               view.view_ofs = '0 0 1' * getstati(STAT_VIEWHEIGHT);
+       }
+
+       if(view)
+       {
+               int refdefflags = 0;
+
+               if(view.csqcmodel_teleported)
+                       refdefflags |= REFDEFFLAG_TELEPORTED;
+
+               if(input_buttons & 4)
+                       refdefflags |= REFDEFFLAG_JUMPING;
+
+               // note: these two only work in WIP2, but are harmless in WIP1
+               if(getstati(STAT_HEALTH) <= 0)
+                       refdefflags |= REFDEFFLAG_DEAD;
+
+               if(intermission)
+                       refdefflags |= REFDEFFLAG_INTERMISSION;
+
+               V_CalcRefdef(view, refdefflags);
+       }
+       else
+       {
+               // FIXME by CSQC spec we have to do this:
+               // but it breaks chase cam
+               /*
+               setproperty(VF_ORIGIN, pmove_org + '0 0 1' * getstati(STAT_VIEWHEIGHT));
+               setproperty(VF_ANGLES, view_angles);
+               */
+       }
+
+       { CSQCPLAYER_HOOK_POSTCAMERASETUP }
+}
+
+void CSQCPlayer_Remove()
+{
+       csqcplayer = world;
+       cvar_settemp("cl_movement_replay", "1");
+}
+
+float CSQCPlayer_PreUpdate()
+{SELFPARAM();
+       if(self != csqcplayer)
+               return 0;
+       if(csqcplayer_status != CSQCPLAYERSTATUS_FROMSERVER)
+               CSQCPlayer_Unpredict();
+       return 1;
+}
+
+float CSQCPlayer_PostUpdate()
+{SELFPARAM();
+       if(self.entnum != player_localnum + 1)
+               return 0;
+       csqcplayer = self;
+       csqcplayer_status = CSQCPLAYERSTATUS_FROMSERVER;
+       cvar_settemp("cl_movement_replay", "0");
+       self.entremove = CSQCPlayer_Remove;
+       return 1;
+}
diff --git a/qcsrc/lib/csqcmodel/cl_player.qh b/qcsrc/lib/csqcmodel/cl_player.qh
new file mode 100644 (file)
index 0000000..c9598c8
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2011 Rudolf Polzer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+#ifndef LIB_CSQCMODEL_CL_PLAYER_H
+#define LIB_CSQCMODEL_CL_PLAYER_H
+
+entity csqcplayer;
+float csqcplayer_status;
+const int CSQCPLAYERSTATUS_UNPREDICTED = 0;
+const int CSQCPLAYERSTATUS_FROMSERVER = 1;
+const int CSQCPLAYERSTATUS_PREDICTED = 2;
+
+// only ever READ these!
+.int pmove_flags;
+const int PMF_JUMP_HELD = 1;
+//const int PMF_DUCKED = 4;
+//const int PMF_ONGROUND = 8;
+
+const int FL_DUCKED = 524288;
+
+void CSQCPlayer_SetCamera();
+float CSQCPlayer_PreUpdate();
+float CSQCPlayer_PostUpdate();
+float CSQCPlayer_IsLocalPlayer();
+#endif
diff --git a/qcsrc/lib/csqcmodel/common.qh b/qcsrc/lib/csqcmodel/common.qh
new file mode 100644 (file)
index 0000000..884977f
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2011 Rudolf Polzer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+#ifndef LIB_CSQCMODEL_COMMON_H
+#define LIB_CSQCMODEL_COMMON_H
+
+#include "../../common/csqcmodel_settings.qh"
+
+noref string csqcmodel_license = "\
+Copyright (c) 2011 Rudolf Polzer\
+\
+Permission is hereby granted, free of charge, to any person obtaining a copy\
+of this software and associated documentation files (the \"Software\"), to\
+deal in the Software without restriction, including without limitation the\
+rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\
+sell copies of the Software, and to permit persons to whom the Software is\
+furnished to do so, subject to the following conditions:\
+\
+The above copyright notice and this permission notice shall be included in\
+all copies or substantial portions of the Software.\
+\
+THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\
+IN THE SOFTWARE.\
+";
+
+.vector glowmod;
+.vector view_ofs;
+.int frame;
+.float frame1time;
+.int frame2;
+.float frame2time;
+.float lerpfrac;
+
+const int CSQCMODEL_PROPERTY_FRAME = 8388608;
+const int CSQCMODEL_PROPERTY_TELEPORTED = 4194304; // the "teleport bit" cancelling interpolation
+const int CSQCMODEL_PROPERTY_MODELINDEX = 2097152;
+const int CSQCMODEL_PROPERTY_ORIGIN = 1048576;
+const int CSQCMODEL_PROPERTY_YAW = 524288;
+const int CSQCMODEL_PROPERTY_PITCHROLL = 262144;
+const int CSQCMODEL_PROPERTY_FRAME2 = 131072;
+const int CSQCMODEL_PROPERTY_LERPFRAC = 65536;
+const int CSQCMODEL_PROPERTY_SIZE = 32768;
+
+#define ALLPROPERTIES_COMMON \
+       CSQCMODEL_PROPERTY(CSQCMODEL_PROPERTY_FRAME, int, ReadByte, WriteByte, frame) \
+       CSQCMODEL_PROPERTY(CSQCMODEL_PROPERTY_MODELINDEX, int, ReadShort, WriteShort, modelindex) \
+       CSQCMODEL_PROPERTY(CSQCMODEL_PROPERTY_ORIGIN, float, ReadCoord, WriteCoord, origin_x) \
+       CSQCMODEL_PROPERTY(CSQCMODEL_PROPERTY_ORIGIN, float, ReadCoord, WriteCoord, origin_y) \
+       CSQCMODEL_PROPERTY(CSQCMODEL_PROPERTY_ORIGIN, float, ReadCoord, WriteCoord, origin_z) \
+       CSQCMODEL_PROPERTY(CSQCMODEL_PROPERTY_SIZE, float, ReadShort, WriteShort, mins_x) \
+       CSQCMODEL_PROPERTY(CSQCMODEL_PROPERTY_SIZE, float, ReadShort, WriteShort, mins_y) \
+       CSQCMODEL_PROPERTY(CSQCMODEL_PROPERTY_SIZE, float, ReadShort, WriteShort, mins_z) \
+       CSQCMODEL_PROPERTY(CSQCMODEL_PROPERTY_SIZE, float, ReadShort, WriteShort, maxs_x) \
+       CSQCMODEL_PROPERTY(CSQCMODEL_PROPERTY_SIZE, float, ReadShort, WriteShort, maxs_y) \
+       CSQCMODEL_PROPERTY(CSQCMODEL_PROPERTY_SIZE, float, ReadShort, WriteShort, maxs_z) \
+       CSQCMODEL_PROPERTY(CSQCMODEL_PROPERTY_PITCHROLL, float, ReadAngle, WriteAngle, angles_x) \
+       CSQCMODEL_PROPERTY(CSQCMODEL_PROPERTY_YAW, float, ReadAngle, WriteAngle, angles_y) \
+       CSQCMODEL_PROPERTY(CSQCMODEL_PROPERTY_PITCHROLL, float, ReadAngle, WriteAngle, angles_z) \
+       CSQCMODEL_EXTRAPROPERTIES
+
+#ifdef CSQCMODEL_HAVE_TWO_FRAMES
+.float frame3;
+.float frame3time;
+.float lerpfrac3;
+.float frame4;
+.float frame4time;
+.float lerpfrac4;
+#define ALLPROPERTIES ALLPROPERTIES_COMMON \
+       CSQCMODEL_PROPERTY(CSQCMODEL_PROPERTY_FRAME2, int, ReadByte, WriteByte, frame2) \
+       CSQCMODEL_PROPERTY_SCALED(CSQCMODEL_PROPERTY_LERPFRAC, float, ReadByte, WriteByte, lerpfrac, 255, 0, 255)
+#else
+#define ALLPROPERTIES ALLPROPERTIES_COMMON
+#endif
+#endif
diff --git a/qcsrc/lib/csqcmodel/interpolate.qc b/qcsrc/lib/csqcmodel/interpolate.qc
new file mode 100644 (file)
index 0000000..ca846da
--- /dev/null
@@ -0,0 +1,180 @@
+/*
+ * Copyright (c) 2011 Rudolf Polzer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+#include "interpolate.qh"
+
+#if defined(CSQC)
+//     #include "../../client/defs.qh"
+//     #include "../warpzone/anglestransform.qh"
+//     #include "../../client/autocvars.qh"
+//     #include "cl_model.qh"
+#elif defined(MENUQC)
+#elif defined(SVQC)
+#endif
+
+.vector iorigin1, iorigin2;
+.vector ivelocity1, ivelocity2;
+.vector iforward1, iforward2;
+.vector iup1, iup2;
+.vector ivforward1, ivforward2;
+.vector ivup1, ivup2;
+.float itime1, itime2;
+void InterpolateOrigin_Reset()
+{SELFPARAM();
+       self.iflags &= ~IFLAG_INTERNALMASK;
+       self.itime1 = self.itime2 = 0;
+}
+void InterpolateOrigin_Note()
+{SELFPARAM();
+       float dt;
+       int f0;
+
+       dt = time - self.itime2;
+
+       f0 = self.iflags;
+       if(self.iflags & IFLAG_PREVALID)
+               self.iflags |= IFLAG_VALID;
+       else
+               self.iflags |= IFLAG_PREVALID;
+
+       if(self.iflags & IFLAG_ORIGIN)
+       {
+               self.iorigin1 = self.iorigin2;
+               self.iorigin2 = self.origin;
+       }
+
+       if(self.iflags & IFLAG_AUTOANGLES)
+               if(self.iorigin2 != self.iorigin1)
+                       self.angles = vectoangles(self.iorigin2 - self.iorigin1);
+
+       if(self.iflags & IFLAG_AUTOVELOCITY)
+               if(self.itime2 != self.itime1)
+                       self.velocity = (self.iorigin2 - self.iorigin1) * (1.0 / (self.itime2 - self.itime1));
+
+       if(self.iflags & IFLAG_ANGLES)
+       {
+               fixedmakevectors(self.angles);
+               if(f0 & IFLAG_VALID)
+               {
+                       self.iforward1 = self.iforward2;
+                       self.iup1 = self.iup2;
+               }
+               else
+               {
+                       self.iforward1 = v_forward;
+                       self.iup1 = v_up;
+               }
+               self.iforward2 = v_forward;
+               self.iup2 = v_up;
+       }
+
+       if(self.iflags & IFLAG_V_ANGLE)
+       {
+               fixedmakevectors(self.v_angle);
+               if(f0 & IFLAG_VALID)
+               {
+                       self.ivforward1 = self.ivforward2;
+                       self.ivup1 = self.ivup2;
+               }
+               else
+               {
+                       self.ivforward1 = v_forward;
+                       self.ivup1 = v_up;
+               }
+               self.ivforward2 = v_forward;
+               self.ivup2 = v_up;
+       }
+       else if(self.iflags & IFLAG_V_ANGLE_X)
+       {
+               self.ivforward1_x = self.ivforward2_x;
+               self.ivforward2_x = self.v_angle.x;
+       }
+
+       if(self.iflags & IFLAG_VELOCITY)
+       {
+               self.ivelocity1 = self.ivelocity2;
+               self.ivelocity2 = self.velocity;
+       }
+
+       if(self.iflags & IFLAG_TELEPORTED)
+       {
+               self.iflags &= ~IFLAG_TELEPORTED;
+               self.itime1 = self.itime2 = time; // don't lerp
+       }
+       else if(vlen(self.iorigin2 - self.iorigin1) > 1000)
+       {
+               self.itime1 = self.itime2 = time; // don't lerp
+       }
+       else if((self.iflags & IFLAG_VELOCITY) && (vlen(self.ivelocity2 - self.ivelocity1) > 1000))
+       {
+               self.itime1 = self.itime2 = time; // don't lerp
+       }
+       else if(dt >= 0.2)
+       {
+               self.itime1 = self.itime2 = time;
+       }
+       else
+       {
+               self.itime1 = serverprevtime;
+               self.itime2 = time;
+       }
+}
+void InterpolateOrigin_Do()
+{SELFPARAM();
+       vector forward, up;
+       if(self.itime1 && self.itime2 && self.itime1 != self.itime2)
+       {
+               float f;
+               f = bound(0, (time - self.itime1) / (self.itime2 - self.itime1), 1 + autocvar_cl_lerpexcess);
+               if(self.iflags & IFLAG_ORIGIN)
+                       setorigin(self, (1 - f) * self.iorigin1 + f * self.iorigin2);
+               if(self.iflags & IFLAG_ANGLES)
+               {
+                       forward = (1 - f) * self.iforward1 + f * self.iforward2;
+                       up = (1 - f) * self.iup1 + f * self.iup2;
+                       self.angles = fixedvectoangles2(forward, up);
+               }
+               if(self.iflags & IFLAG_V_ANGLE)
+               {
+                       forward = (1 - f) * self.ivforward1 + f * self.ivforward2;
+                       up = (1 - f) * self.ivup1 + f * self.ivup2;
+                       self.v_angle = fixedvectoangles2(forward, up);
+               }
+               else if(self.iflags & IFLAG_V_ANGLE_X)
+                       self.v_angle_x = (1 - f) * self.ivforward1_x + f * self.ivforward2_x;
+               if(self.iflags & IFLAG_VELOCITY)
+                       self.velocity = (1 - f) * self.ivelocity1 + f * self.ivelocity2;
+       }
+}
+void InterpolateOrigin_Undo()
+{SELFPARAM();
+       if(self.iflags & IFLAG_ORIGIN)
+               setorigin(self, self.iorigin2);
+       if(self.iflags & IFLAG_ANGLES)
+               self.angles = fixedvectoangles2(self.iforward2, self.iup2);
+       if(self.iflags & IFLAG_V_ANGLE)
+               self.v_angle = fixedvectoangles2(self.ivforward2, self.ivup2);
+       else if(self.iflags & IFLAG_V_ANGLE_X)
+               self.v_angle_x = self.ivforward2_x;
+       if(self.iflags & IFLAG_VELOCITY)
+               self.velocity = self.ivelocity2;
+}
+
diff --git a/qcsrc/lib/csqcmodel/interpolate.qh b/qcsrc/lib/csqcmodel/interpolate.qh
new file mode 100644 (file)
index 0000000..e07ad4a
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2011 Rudolf Polzer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+#ifndef LIB_CSQCMODEL_INTERPOLATE_H
+#define LIB_CSQCMODEL_INTERPOLATE_H
+
+.int iflags;
+const int IFLAG_VELOCITY = 1;
+const int IFLAG_ANGLES = 2;
+const int IFLAG_AUTOANGLES = 4;
+const int IFLAG_VALID = 8;
+const int IFLAG_PREVALID = 16;
+const int IFLAG_TELEPORTED = 32;
+const int IFLAG_AUTOVELOCITY = 64;
+const int IFLAG_V_ANGLE = 128;
+const int IFLAG_V_ANGLE_X = 256;
+const int IFLAG_ORIGIN = 512;
+#define IFLAG_INTERNALMASK (IFLAG_VALID | IFLAG_PREVALID)
+
+// call this BEFORE reading an entity update
+void InterpolateOrigin_Undo();
+
+// call this AFTER receiving an entity update
+void InterpolateOrigin_Note();
+
+// call this when the entity got teleported, before InterpolateOrigin_Note
+void InterpolateOrigin_Reset();
+
+// call this BEFORE drawing
+void InterpolateOrigin_Do();
+
+// in case we interpolate that:
+.vector v_angle;
+#endif
diff --git a/qcsrc/lib/csqcmodel/settings.qh b/qcsrc/lib/csqcmodel/settings.qh
new file mode 100644 (file)
index 0000000..128da85
--- /dev/null
@@ -0,0 +1,30 @@
+#ifndef LIB_CSQCMODEL_SETTINGS_H
+#define LIB_CSQCMODEL_SETTINGS_H
+// define this if svqc code wants to use .frame2 and .lerpfrac
+//#define CSQCMODEL_HAVE_TWO_FRAMES
+
+// don't define this ever
+//#define CSQCMODEL_SUPPORT_GETTAGINFO_BEFORE_DRAW
+
+// add properties you want networked to CSQC here
+#define CSQCMODEL_EXTRAPROPERTIES \
+       /* CSQCMODEL_PROPERTY(1, float, ReadShort, WriteShort, colormap) */ \
+       /* CSQCMODEL_PROPERTY(2, float, ReadInt24_t, WriteInt24_t, effects) */
+
+// add hook function calls here
+#define CSQCMODEL_HOOK_PREUPDATE
+#define CSQCMODEL_HOOK_POSTUPDATE
+#define CSQCMODEL_HOOK_PREDRAW
+#define CSQCPLAYER_HOOK_POSTCAMERASETUP
+
+// force updates of player entities that often even if unchanged
+#define CSQCPLAYER_FORCE_UPDATES 0.25
+
+// mod must define:
+//vector PL_MIN  = ...;
+//vector PL_MAX  = ...;
+//vector PL_VIEW_OFS  = ...;
+//vector PL_CROUCH_MIN  = ...;
+//vector PL_CROUCH_MAX  = ...;
+//vector PL_CROUCH_VIEW_OFS  = ...;
+#endif
diff --git a/qcsrc/lib/csqcmodel/sv_model.qc b/qcsrc/lib/csqcmodel/sv_model.qc
new file mode 100644 (file)
index 0000000..8fcdcfb
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2011 Rudolf Polzer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+#include "sv_model.qh"
+
+#include "common.qh"
+#include "../../common/animdecide.qh"
+#include "../../common/constants.qh"
+#include "../../common/util.qh"
+#include "../../server/constants.qh"
+#include "../../server/defs.qh"
+
+// generic CSQC model code
+
+bool CSQCModel_Send(entity to, int sf)
+{SELFPARAM();
+       // some nice flags for CSQCMODEL_IF
+       float isplayer = (IS_CLIENT(self));
+       float islocalplayer = (self == to);
+       float isnolocalplayer = (isplayer && (self != to));
+
+       unused_float = isplayer;
+       unused_float = islocalplayer;
+       unused_float = isnolocalplayer;
+
+       WriteByte(MSG_ENTITY, ENT_CLIENT_MODEL);
+       WriteInt24_t(MSG_ENTITY, sf);
+
+#define CSQCMODEL_IF(cond) if(cond) {
+#define CSQCMODEL_ENDIF }
+#define CSQCMODEL_PROPERTY(flag,t,r,w,f) \
+       if(sf & flag) \
+       { \
+               w(MSG_ENTITY, self.csqcmodel_##f); \
+       }
+#define CSQCMODEL_PROPERTY_SCALED(flag,t,r,w,f,s,mi,ma) CSQCMODEL_PROPERTY(flag,t,r,w,f)
+       ALLPROPERTIES
+#undef CSQCMODEL_PROPERTY_SCALED
+#undef CSQCMODEL_PROPERTY
+#undef CSQCMODEL_ENDIF
+#undef CSQCMODEL_IF
+
+       return true;
+}
+
+#ifdef CSQCPLAYER_FORCE_UPDATES
+.float csqcmodel_nextforcedupdate;
+#endif
+void CSQCModel_CheckUpdate(entity e)
+{
+       // some nice flags for CSQCMODEL_IF
+       float isplayer = (IS_CLIENT(e));
+       float islocalplayer = isplayer; // we set BOTH to 1 here as we need the sendflags
+       float isnolocalplayer = isplayer; // we set BOTH to 1 here as we need the sendflags
+
+       unused_float = isplayer;
+       unused_float = islocalplayer;
+       unused_float = isnolocalplayer;
+
+#ifdef CSQCPLAYER_FORCE_UPDATES
+       if(isplayer && time > e.csqcmodel_nextforcedupdate)
+       {
+               e.SendFlags |= CSQCMODEL_PROPERTY_ORIGIN;
+               e.csqcmodel_nextforcedupdate = time + CSQCPLAYER_FORCE_UPDATES * (0.5 + random()); // ensure about 4 origin sends per sec
+       }
+#endif
+
+       if(e.effects & EF_RESTARTANIM_BIT)
+       {
+               e.SendFlags |= CSQCMODEL_PROPERTY_FRAME | CSQCMODEL_PROPERTY_FRAME2; // full anim resend please
+               e.effects &= ~EF_RESTARTANIM_BIT;
+       }
+
+       if(e.effects & EF_TELEPORT_BIT)
+       {
+               e.SendFlags |= CSQCMODEL_PROPERTY_TELEPORTED; // no interpolation please
+               e.effects &= ~EF_TELEPORT_BIT;
+       }
+
+#define CSQCMODEL_IF(cond) if(cond) {
+#define CSQCMODEL_ENDIF }
+#define CSQCMODEL_PROPERTY(flag,t,r,w,f) \
+       { \
+               t tmp = e.f; \
+               if(tmp != e.csqcmodel_##f) \
+               { \
+                       e.csqcmodel_##f = tmp; \
+                       e.SendFlags |= flag; \
+               } \
+       }
+#define CSQCMODEL_PROPERTY_SCALED(flag,t,r,w,f,s,mi,ma) \
+       { \
+               t tmp = rint(bound(mi, s * e.f, ma) - mi); \
+               if(tmp != e.csqcmodel_##f) \
+               { \
+                       e.csqcmodel_##f = tmp; \
+                       e.SendFlags |= flag; \
+               } \
+       }
+       ALLPROPERTIES
+#undef CSQCMODEL_PROPERTY_SCALED
+#undef CSQCMODEL_PROPERTY
+#undef CSQCMODEL_ENDIF
+#undef CSQCMODEL_IF
+}
+
+void CSQCModel_LinkEntity(entity e)
+{
+       e.SendEntity = CSQCModel_Send;
+       e.SendFlags = 0xFFFFFF;
+       CSQCModel_CheckUpdate(e);
+}
+
+void CSQCModel_UnlinkEntity(entity e)
+{
+       e.SendEntity = func_null;
+}
diff --git a/qcsrc/lib/csqcmodel/sv_model.qh b/qcsrc/lib/csqcmodel/sv_model.qh
new file mode 100644 (file)
index 0000000..3e043d3
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2011 Rudolf Polzer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+#ifndef LIB_CSQCMODEL_SV_MODEL_H
+#define LIB_CSQCMODEL_SV_MODEL_H
+
+#include "common.qh"
+
+// generic CSQC model code
+
+void CSQCModel_CheckUpdate(entity e);
+void CSQCModel_LinkEntity(entity e);
+void CSQCModel_UnlinkEntity(entity e);
+
+#define CSQCMODEL_IF(cond)
+#define CSQCMODEL_ENDIF
+#define CSQCMODEL_PROPERTY(flag,t,r,w,f) \
+       .t f; \
+       .t csqcmodel_##f;
+#define CSQCMODEL_PROPERTY_SCALED(flag,t,r,w,f,s,mi,ma) CSQCMODEL_PROPERTY(flag,t,r,w,f)
+       ALLPROPERTIES
+#undef CSQCMODEL_PROPERTY_SCALED
+#undef CSQCMODEL_PROPERTY
+#undef CSQCMODEL_ENDIF
+#undef CSQCMODEL_IF
+#endif
index 2a13611168fd806382b42b069897591d6582b1f0..6c495663452c2a0dffe4bf001b450c2c8a01498f 100644 (file)
@@ -1,7 +1,9 @@
 #ifndef MENUQC
 #ifndef DEFER_H
 #define DEFER_H
+
 #include "oo.qh"
+#include "self.qh"
 
 entityclass(Defer);
 class(Defer) .entity owner;
diff --git a/qcsrc/lib/functional.qh b/qcsrc/lib/functional.qh
new file mode 100644 (file)
index 0000000..2bbe7d5
--- /dev/null
@@ -0,0 +1,45 @@
+#ifndef FUNCTIONAL_H
+#define FUNCTIONAL_H
+
+#define MAP(f, ...) EVAL(OVERLOAD(MAP, f, __VA_ARGS__))
+#define MAP_2(f, it) f(it)
+#define MAP_3(f, it, ...) f(it)MAP_2(f, __VA_ARGS__)
+#define MAP_4(f, it, ...) f(it)MAP_3(f, __VA_ARGS__)
+#define MAP_5(f, it, ...) f(it)MAP_4(f, __VA_ARGS__)
+#define MAP_6(f, it, ...) f(it)MAP_5(f, __VA_ARGS__)
+#define MAP_7(f, it, ...) f(it)MAP_6(f, __VA_ARGS__)
+#define MAP_8(f, it, ...) f(it)MAP_7(f, __VA_ARGS__)
+#define MAP_9(f, it, ...) f(it)MAP_8(f, __VA_ARGS__)
+#define MAP_10(f, it, ...) f(it)MAP_9(f, __VA_ARGS__)
+#define MAP_11(f, it, ...) f(it)MAP_10(f, __VA_ARGS__)
+#define MAP_12(f, it, ...) f(it)MAP_11(f, __VA_ARGS__)
+#define MAP_13(f, it, ...) f(it)MAP_12(f, __VA_ARGS__)
+#define MAP_14(f, it, ...) f(it)MAP_13(f, __VA_ARGS__)
+#define MAP_15(f, it, ...) f(it)MAP_14(f, __VA_ARGS__)
+#define MAP_16(f, it, ...) f(it)MAP_15(f, __VA_ARGS__)
+#define MAP_17(f, it, ...) f(it)MAP_16(f, __VA_ARGS__)
+#define MAP_18(f, it, ...) f(it)MAP_17(f, __VA_ARGS__)
+#define MAP_19(f, it, ...) f(it)MAP_18(f, __VA_ARGS__)
+#define MAP_20(f, it, ...) f(it)MAP_19(f, __VA_ARGS__)
+
+#define IDENTITY(it) it
+
+#define UNWORDS(...) MAP(IDENTITY, __VA_ARGS__)
+
+#define APPLY(f, ...) f(__VA_ARGS__)
+
+#ifdef SVQC
+    #define SV(f, ...) f(__VA_ARGS__)
+#else
+    #define SV(f, ...)
+#endif
+
+#ifdef CSQC
+    #define CL(f, ...) f(__VA_ARGS__)
+#else
+    #define CL(f, ...)
+#endif
+
+#define IF(cond, f, ...) cond(f, __VA_ARGS__)
+
+#endif
diff --git a/qcsrc/lib/int.qh b/qcsrc/lib/int.qh
new file mode 100644 (file)
index 0000000..d9ea61f
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef INT_H
+#define INT_H
+
+#ifndef QCC_SUPPORT_INT
+    #define stoi(s) stof(s)
+    #define stob(s) stof(s)
+    #define itos(i) ftos(i)
+#else
+    #define stoi(s) ((int) stof(s))
+    #define stob(s) ((bool) stof(s))
+    #define itos(i) ftos(i)
+#endif
+
+#endif
diff --git a/qcsrc/lib/iter.qh b/qcsrc/lib/iter.qh
new file mode 100644 (file)
index 0000000..53b3d66
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef ITER_H
+#define ITER_H
+
+#define FOREACH_ARRAY(arr, start, end, cond, body) do { \
+    for (int i = start; i < end; ++i) {                 \
+        const noref entity it = arr[i];                 \
+        if (cond) { body }                              \
+    }                                                   \
+} while(0)
+
+#define FOREACH_LIST(list, next, cond, body) do {               \
+    noref int i = 0;                                            \
+    for (entity it = list##_first; it; (it = it.next, ++i)) {   \
+        if (cond) { body }                                      \
+    }                                                           \
+} while(0)
+
+#define FOREACH(list, cond, body) FOREACH_LIST(list, enemy, cond, body)
+
+#endif
diff --git a/qcsrc/lib/misc.qh b/qcsrc/lib/misc.qh
new file mode 100644 (file)
index 0000000..8a6e117
--- /dev/null
@@ -0,0 +1,39 @@
+#ifndef MISC_H
+#define MISC_H
+
+#ifdef GMQCC
+    #define EVAL(...)           __VA_ARGS__
+
+    #define OVERLOAD_(F, ...)   F##_##__VA_COUNT__(__VA_ARGS__)
+    #define OVERLOAD(F, ...)    F##_##__VA_COUNT__(__VA_ARGS__)
+#else
+    #define EMPTY()
+    #define DEFER(id) id EMPTY()
+
+    #define EVAL(...)  EVAL1(EVAL1(EVAL1(__VA_ARGS__)))
+    #define EVAL1(...) EVAL2(EVAL2(EVAL2(__VA_ARGS__)))
+    #define EVAL2(...) EVAL3(EVAL3(EVAL3(__VA_ARGS__)))
+    #define EVAL3(...) EVAL4(EVAL4(EVAL4(__VA_ARGS__)))
+    #define EVAL4(...) EVAL5(EVAL5(EVAL5(__VA_ARGS__)))
+    #define EVAL5(...) __VA_ARGS__
+
+    #define OVERLOAD___(F,_16,_15,_14,_13,_12,_11,_10,_9,_8,_7,_6,_5,_4,_3,_2,_1,n,...) F##_##n
+    #define OVERLOAD__(F, ...)  OVERLOAD___(F,##__VA_ARGS__,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0)
+    #define OVERLOAD_(...)      DEFER(OVERLOAD__(__VA_ARGS__))
+    #define OVERLOAD(F, ...)    OVERLOAD_(F,##__VA_ARGS__)(__VA_ARGS__)
+#endif
+
+#define GET(name) name##get
+#define GETTER(type, name) type GET(name)() { return name; }
+
+#define LAMBDA(...) { __VA_ARGS__ ; }
+
+// Can't wrap with do-while as block may contain continue or break
+#define WITH(type, name, value, block) { \
+    type __with_save = (name); \
+    name = (value); \
+    LAMBDA(block) \
+    name = __with_save; \
+} do { } while (0)
+
+#endif
index 789b1f9c0f530163c030d95437e993df9c39a9ae..87e3aea5e545a9a09d6c6c5136915ab3c509bc24 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef NIL_H
 #define NIL_H
 
-#if QCC_SUPPORT_NIL
+#ifdef QCC_SUPPORT_NIL
 #define func_null nil
 #define string_null nil
 #else
index fce18cbfddac268702fdedfe33eeab5129f5b111..0615282c3e1a7f7031aa1571eb8e51f5d9ce8e53 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef OO_H
 #define OO_H
 
+#include "misc.qh"
 #include "nil.qh"
 
 #ifdef MENUQC
@@ -35,6 +36,7 @@ entity __spawn(string _classname, string _sourceFile, int _sourceLine) {
     #define class(name) [[class(name)]]
     #define new(class) ((class) __spawn(#class, __FILE__, __LINE__))
 #endif
+#define spawn() new(entity)
 
 // Classes have a `spawn##cname(entity)` constructor
 // The parameter is used across [[accumulate]] functions
index 688a711912cd1e43694b1856d03a0493b09c10b5..4c39a9dec6e59379f719e24b865857e9503c5ebe 100644 (file)
  * @param fld       The field to store the current count into
  * @param inst      An expression to create a new instance, invoked for every registration
  */
-#define REGISTER(initfunc, ns, array, id, fld, inst)            \
-    entity ns##_##id;                                           \
-    REGISTER_INIT(ns, id) { }                                   \
-    REGISTER_INIT_POST(ns, id) { }                              \
-    .entity enemy; /* internal next pointer */                  \
-    void Register_##ns##_##id() {                               \
+#define REGISTER(initfunc, ns, array, id, fld, inst)                \
+    entity ns##_##id;                                               \
+    REGISTER_INIT(ns, id) { }                                       \
+    REGISTER_INIT_POST(ns, id) { }                                  \
+    void Register_##ns##_##id() {                                   \
         if (array##_COUNT >= array##_MAX) LOG_FATALF("Registry capacity exceeded (%s)", ftos(array##_MAX)); \
-        entity this = inst;                                     \
-        ns##_##id = this;                                       \
-        this.fld = array##_COUNT;                               \
-        array[array##_COUNT++] = this;                          \
-        if (!array##_first)    array##_first = this;            \
-        if ( array##_last)     array##_last.enemy = this;       \
-        array##_last = this;                                    \
-        Register_##ns##_##id##_init(this);                      \
-        Register_##ns##_##id##_init_post(this);                 \
-    }                                                           \
-    ACCUMULATE_FUNCTION(initfunc, Register_##ns##_##id)         \
+        entity this = inst;                                         \
+        ns##_##id = this;                                           \
+        this.fld = array##_COUNT;                                   \
+        array[array##_COUNT++] = this;                              \
+        if (!array##_first)    array##_first = this;                \
+        if ( array##_last)     array##_last.REGISTRY_NEXT = this;   \
+        array##_last = this;                                        \
+        Register_##ns##_##id##_init(this);                          \
+        Register_##ns##_##id##_init_post(this);                     \
+    }                                                               \
+    ACCUMULATE_FUNCTION(initfunc, Register_##ns##_##id)             \
     REGISTER_INIT(ns, id)
 
-#define REGISTRY_SORT(id, field, skip)                          \
-    void _REGISTRY_SWAP_##id(int i, int j, entity pass) {       \
-        i += skip; j += skip;                                   \
-        entity e = id[i];                                       \
-        id[i] = id[j];                                          \
-        id[j] = e;                                              \
-    }                                                           \
-    float _REGISTRY_CMP_##id(int i, int j, entity pass) {       \
-        i += skip; j += skip;                                   \
-        string a = id[i].field;                                 \
-        string b = id[j].field;                                 \
-        return strcasecmp(a, b);                                \
-    }                                                           \
-    STATIC_INIT(Registry_sort_##id) {                           \
+/** internal next pointer */
+#define REGISTRY_NEXT enemy
+.entity REGISTRY_NEXT;
+
+#define REGISTRY_SORT(id, field, skip)                              \
+    void _REGISTRY_SWAP_##id(int i, int j, entity pass) {           \
+        i += skip; j += skip;                                       \
+                                                                    \
+        entity a = id[i], b = id[j];                                \
+        id[i] = b;                                                  \
+        id[j] = a;                                                  \
+                                                                    \
+        entity a_next = a.REGISTRY_NEXT, b_next = b.REGISTRY_NEXT;  \
+        a.REGISTRY_NEXT = b_next;                                   \
+        b.REGISTRY_NEXT = a_next;                                   \
+                                                                    \
+        if (i == 0) id##_first = b;                                 \
+        else id[i - 1].REGISTRY_NEXT = b;                           \
+                                                                    \
+        if (j == 0) id##_first = a;                                 \
+        else id[j - 1].REGISTRY_NEXT = a;                           \
+    }                                                               \
+    float _REGISTRY_CMP_##id(int i, int j, entity pass) {           \
+        i += skip; j += skip;                                       \
+        string a = id[i].field;                                     \
+        string b = id[j].field;                                     \
+        return strcasecmp(a, b);                                    \
+    }                                                               \
+    STATIC_INIT(Registry_sort_##id) {                               \
         heapsort(id##_COUNT - (skip), _REGISTRY_SWAP_##id, _REGISTRY_CMP_##id, NULL); \
     }
 
diff --git a/qcsrc/lib/self.qh b/qcsrc/lib/self.qh
new file mode 100644 (file)
index 0000000..eac0c64
--- /dev/null
@@ -0,0 +1,37 @@
+#ifndef SELF_H
+#define SELF_H
+
+// Transition from global 'self' to local 'this'
+
+[[alias("self")]] entity __self;
+
+// Step 1: auto oldself
+#if 1
+#define SELFPARAM() noref entity this = __self
+#define setself(s) (__self = s)
+#define self __self
+#endif
+
+// Step 2: check SELFPARAM() is present for functions that use self
+#if 0
+#define SELFPARAM() [[alias("__self")]] noref entity this = __self
+#define setself(s) (__self = s)
+#define self this
+#endif
+
+// Step 3: const self
+#if 0
+#define SELFPARAM() noref const entity this = __self
+entity setself(entity e) { return self = e; }
+entity getself() { return self; }
+#define self getself()
+#endif
+
+// Step 4: enable when possible
+// TODO: Remove SELFPARAM in favor of a parameter
+#if 0
+#define SELFPARAM() noref const entity this = __self
+#define self this
+#endif
+
+#endif
index d1f5357a5ef39bb5c8bddde4a8a4671b64c07c4d..edc2f5bf37ff959f3b6fe6375d29923b5f9b086b 100644 (file)
@@ -1,8 +1,6 @@
 #ifndef TEST_H
 #define TEST_H
 
-#include "../common/util.qh"
-
 #define TEST_Check(cond) do { if(!(cond)) TEST_Fail(#cond); } while(0)
 
 void TEST_OK();
index 6f196785177dc6e1617cdf5b09d2c7b5e6a80ee6..e4b8a8f27312f5d096817262abb6e1908363a057 100644 (file)
@@ -1,8 +1,6 @@
 #ifndef URLLIB_H
 #define URLLIB_H
 
-#include "../common/util.qh"
-
 // URI handles
 const int URI_GET_DISCARD = 0;
 const int URI_GET_IPBAN = 1;
diff --git a/qcsrc/lib/warpzone/COPYING b/qcsrc/lib/warpzone/COPYING
new file mode 100644 (file)
index 0000000..d61ba0a
--- /dev/null
@@ -0,0 +1,369 @@
+The code in this directory is dual-licensed MIT and GPLv2 "or any later version".
+
+
+
+MIT license:
+
+Copyright (c) 2010 Rudolf Polzer
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+
+
+GPL v2:
+
+                   GNU GENERAL PUBLIC LICENSE
+                      Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                   GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                           NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
+
+           How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    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.,
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
diff --git a/qcsrc/lib/warpzone/TODO b/qcsrc/lib/warpzone/TODO
new file mode 100644 (file)
index 0000000..927ab12
--- /dev/null
@@ -0,0 +1,24 @@
+Open issues:
+- grep for TODO and FIXME
+- when shot origin is inside warpzone, vortex shot fails (and is even drawn in totally wrong direction). WHY? Possibly v_forward got lost?
+
+Weapon support:
+
+- blaster: YES
+- shotgun: YES
+- machinegun: YES
+- mortar: YES
+- electro: YES
+- crylink: YES
+- vortex: YES
+- hagar: YES
+- devastator: YES (except for trail bug)
+- porto: YES (bwahahahaha)
+- hlac: YES
+- vaporizer: YES
+- rifle: YES
+- fireball: YES (BFG effect cannot work through warpzones by design, so it's not available through warpzones)
+- hook: YES
+
+- shockwave: NO (does not support warpzones currently)
+- tuba: NO (sound)
diff --git a/qcsrc/lib/warpzone/anglestransform.qc b/qcsrc/lib/warpzone/anglestransform.qc
new file mode 100644 (file)
index 0000000..d6423f1
--- /dev/null
@@ -0,0 +1,225 @@
+#include "anglestransform.qh"
+
+#ifdef POSITIVE_PITCH_IS_DOWN
+vector fixedvectoangles(vector a)
+{
+       vector ang;
+       ang = vectoangles(a);
+       ang.x = -ang.x;
+       return ang;
+}
+vector fixedvectoangles2(vector a, vector b)
+{
+       vector ang;
+       ang = vectoangles2(a, b);
+       ang.x = -ang.x;
+       return ang;
+}
+#else
+void fixedmakevectors(vector a)
+{
+       // a makevectors that actually inverts vectoangles
+       a.x = -a.x;
+       makevectors(a);
+}
+#endif
+
+// angles transforms
+// angles in fixedmakevectors/fixedvectoangles space
+vector AnglesTransform_Apply(vector transform, vector v)
+{
+       fixedmakevectors(transform);
+       return v_forward * v.x
+               + v_right   * (-v.y)
+               + v_up      * v.z;
+}
+
+vector AnglesTransform_Multiply(vector t1, vector t2)
+{
+       vector m_forward, m_up;
+       fixedmakevectors(t2); m_forward = v_forward; m_up = v_up;
+       m_forward = AnglesTransform_Apply(t1, m_forward); m_up = AnglesTransform_Apply(t1, m_up);
+       return fixedvectoangles2(m_forward, m_up);
+}
+
+vector AnglesTransform_Invert(vector transform)
+{
+       vector i_forward, i_up;
+       fixedmakevectors(transform);
+       // we want angles that turn v_forward into '1 0 0', v_right into '0 1 0' and v_up into '0 0 1'
+       // but these are orthogonal unit vectors!
+       // so to invert, we can simply fixedvectoangles the TRANSPOSED matrix
+       // TODO is this always -transform?
+       i_forward.x = v_forward.x;
+       i_forward.y = -v_right.x;
+       i_forward.z = v_up.x;
+       i_up.x = v_forward.z;
+       i_up.y = -v_right.z;
+       i_up.z = v_up.z;
+       return fixedvectoangles2(i_forward, i_up);
+}
+
+vector AnglesTransform_TurnDirectionFR(vector transform)
+{
+       // turn 180 degrees around v_up
+       // changes in-direction to out-direction
+       //fixedmakevectors(transform);
+       //return fixedvectoangles2(-1 * v_forward, 1 * v_up);
+       transform.x = -transform.x;
+       transform.y = 180 + transform.y;
+       transform.z = -transform.z;
+       // pitch: -s +c
+       // yaw:   -s -c
+       // roll:  -s +c
+       return transform;
+}
+
+vector AnglesTransform_TurnDirectionFU(vector transform)
+{
+       // turn 180 degrees around v_up
+       // changes in-direction to out-direction
+       //fixedmakevectors(transform);
+       //return fixedvectoangles2(-1 * v_forward, 1 * v_up);
+       transform.x = -transform.x;
+       transform.y = 180 + transform.y;
+       transform.z = 180 - transform.z;
+       return transform;
+}
+
+vector AnglesTransform_RightDivide(vector to_transform, vector from_transform)
+{
+       return AnglesTransform_Multiply(to_transform, AnglesTransform_Invert(from_transform));
+}
+
+vector AnglesTransform_LeftDivide(vector from_transform, vector to_transform)
+{
+       return AnglesTransform_Multiply(AnglesTransform_Invert(from_transform), to_transform);
+}
+
+vector AnglesTransform_Normalize(vector t, float minimize_roll)
+{
+       float need_flip;
+       // first, bring all angles in their range...
+       t.x = t.x - 360 * rint(t.x / 360);
+       t.y = t.y - 360 * rint(t.y / 360);
+       t.z = t.z - 360 * rint(t.z / 360);
+       if(minimize_roll)
+               need_flip = (t.z > 90 || t.z <= -90);
+       else
+               need_flip = (t.x > 90 || t.x < -90); // for pitch we prefer to allow exactly -90 degrees for looking straight down
+       if(need_flip)
+       {
+               if(t.x >= 0) t.x = 180 - t.x; else t.x = -180 - t.x;
+               if(t.y > 0) t.y -= 180; else t.y += 180;
+               if(t.z > 0) t.z -= 180; else t.z += 180;
+       }
+       return t;
+}
+
+vector AnglesTransform_CancelRoll(vector t)
+{
+       const float epsilon = 30;
+       float f;
+
+       // constraints:
+       // forward vector (NOT SO important)
+       // right vector, up vector: screen rotation (MORE important)
+       // choose best match among all pitch-yaw only rotations
+
+       // FIXME find a better method
+
+       f = fabs(t.x - (-90)) / epsilon;
+       if(f < 1)
+       {
+               //t_x = -90;
+               t.y += t.z;
+               t.z = 0;
+       }
+       else
+       {
+               f = fabs(t.x - 90) / epsilon;
+               if(f < 1)
+               {
+                       //t_x = 90;
+                       t.y -= t.z;
+                       t.z = 0;
+               }
+       }
+       return t;
+}
+
+#ifdef POSITIVE_PITCH_IS_DOWN
+vector AnglesTransform_ApplyToAngles(vector transform, vector v)
+{
+       v.x = -v.x;
+       v = AnglesTransform_Multiply(transform, v);
+       v.x = -v.x;
+       return v;
+}
+vector AnglesTransform_ApplyToVAngles(vector transform, vector v)
+{
+       v = AnglesTransform_Multiply(transform, v);
+       return v;
+}
+vector AnglesTransform_FromAngles(vector v)
+{
+       v.x = -v.x;
+       return v;
+}
+vector AnglesTransform_ToAngles(vector v)
+{
+       v.x = -v.x;
+       return v;
+}
+vector AnglesTransform_FromVAngles(vector v)
+{
+       return v;
+}
+vector AnglesTransform_ToVAngles(vector v)
+{
+       return v;
+}
+#else
+vector AnglesTransform_ApplyToAngles(vector transform, vector v)
+{
+       v = AnglesTransform_Multiply(transform, v);
+       return v;
+}
+vector AnglesTransform_ApplyToVAngles(vector transform, vector v)
+{
+       v.x = -v.x;
+       v = AnglesTransform_Multiply(transform, v);
+       v.x = -v.x;
+       return v;
+}
+vector AnglesTransform_FromAngles(vector v)
+{
+       return v;
+}
+vector AnglesTransform_ToAngles(vector v)
+{
+       return v;
+}
+vector AnglesTransform_FromVAngles(vector v)
+{
+       v.x = -v.x;
+       return v;
+}
+vector AnglesTransform_ToVAngles(vector v)
+{
+       v.x = -v.x;
+       return v;
+}
+#endif
+
+vector AnglesTransform_Multiply_GetPostShift(vector t0, vector st0, vector t1, vector st1)
+{
+       // we want the result of:
+       //   t0 * (t1 * p + st1) + st0
+       //   t0 * t1 * p + t0 * st1 + st0
+       return st0 + AnglesTransform_Apply(t0, st1);
+}
+vector AnglesTransform_PrePostShift_GetPostShift(vector sf, vector t, vector st)
+{
+       return st - AnglesTransform_Apply(t, sf);
+}
diff --git a/qcsrc/lib/warpzone/anglestransform.qh b/qcsrc/lib/warpzone/anglestransform.qh
new file mode 100644 (file)
index 0000000..5c356ea
--- /dev/null
@@ -0,0 +1,36 @@
+#ifndef LIB_WARPZONE_ANGLETRANSFORM_H
+#define LIB_WARPZONE_ANGLETRANSFORM_H
+
+#define POSITIVE_PITCH_IS_DOWN
+
+#ifdef POSITIVE_PITCH_IS_DOWN
+#define fixedmakevectors makevectors
+vector fixedvectoangles(vector a);
+vector fixedvectoangles2(vector a, vector b);
+#else
+void fixedmakevectors(vector a);
+#define fixedvectoangles2 vectoangles2
+#define fixedvectoangles vectoangles
+#endif
+
+vector AnglesTransform_Apply(vector transform, vector v);
+vector AnglesTransform_Multiply(vector t1, vector t2); // A B
+vector AnglesTransform_Invert(vector transform);
+vector AnglesTransform_TurnDirectionFU(vector transform);
+vector AnglesTransform_TurnDirectionFR(vector transform);
+vector AnglesTransform_RightDivide(vector to_transform, vector from_transform); // A B^-1
+vector AnglesTransform_LeftDivide(vector from_transform, vector to_transform); // A^-1 B
+
+vector AnglesTransform_Normalize(vector t, float minimize_roll); // makes sure all angles are in their range: yaw in -180..180, pitch in -90..90, roll in -180..180 (or if minimize_roll is set, pitch in -180..180, roll in -90..90)
+
+vector AnglesTransform_ApplyToAngles(vector transform, vector v);
+vector AnglesTransform_ApplyToVAngles(vector transform, vector v);
+vector AnglesTransform_FromAngles(vector v);
+vector AnglesTransform_ToAngles(vector v);
+vector AnglesTransform_FromVAngles(vector v);
+vector AnglesTransform_ToVAngles(vector v);
+
+// transformed = original * transform + postshift
+vector AnglesTransform_Multiply_GetPostShift(vector sf0, vector st0, vector t1, vector st1);
+vector AnglesTransform_PrePostShift_GetPostShift(vector sf, vector t, vector st);
+#endif
diff --git a/qcsrc/lib/warpzone/client.qc b/qcsrc/lib/warpzone/client.qc
new file mode 100644 (file)
index 0000000..aba39c2
--- /dev/null
@@ -0,0 +1,289 @@
+#include "client.qh"
+#include "common.qh"
+
+#if defined(CSQC)
+       #include "../../client/autocvars.qh"
+       #include "../csqcmodel/cl_model.qh"
+#elif defined(MENUQC)
+#elif defined(SVQC)
+#endif
+
+void WarpZone_Fade_PreDraw()
+{SELFPARAM();
+       vector org;
+       org = getpropertyvec(VF_ORIGIN);
+       if(!checkpvs(org, self)) // this makes sense as long as we don't support recursive warpzones
+               self.alpha = 0;
+       else if(self.warpzone_fadestart)
+               self.alpha = bound(0, (self.warpzone_fadeend - vlen(org - self.origin - 0.5 * (self.mins + self.maxs))) / (self.warpzone_fadeend - self.warpzone_fadestart), 1);
+       else
+               self.alpha = 1;
+       //printf("%v <-> %v\n", view_origin, self.origin + 0.5 * (self.mins + self.maxs));
+       if(self.alpha <= 0)
+               self.drawmask = 0;
+       else
+               self.drawmask = MASK_NORMAL;
+}
+
+void WarpZone_Read(float isnew)
+{SELFPARAM();
+       warpzone_warpzones_exist = 1;
+       if (!self.enemy)
+       {
+               self.enemy = spawn();
+               self.enemy.classname = "warpzone_from";
+       }
+       self.classname = "trigger_warpzone";
+
+       int f = ReadByte();
+       self.warpzone_isboxy = (f & 1);
+       if(f & 4)
+       {
+               self.origin_x = ReadCoord();
+               self.origin_y = ReadCoord();
+               self.origin_z = ReadCoord();
+       }
+       else
+               self.origin = '0 0 0';
+       self.modelindex = ReadShort();
+       self.mins_x = ReadCoord();
+       self.mins_y = ReadCoord();
+       self.mins_z = ReadCoord();
+       self.maxs_x = ReadCoord();
+       self.maxs_y = ReadCoord();
+       self.maxs_z = ReadCoord();
+       self.scale = ReadByte() / 16;
+       self.enemy.oldorigin_x = ReadCoord();
+       self.enemy.oldorigin_y = ReadCoord();
+       self.enemy.oldorigin_z = ReadCoord();
+       self.enemy.avelocity_x = ReadCoord();
+       self.enemy.avelocity_y = ReadCoord();
+       self.enemy.avelocity_z = ReadCoord();
+       self.oldorigin_x = ReadCoord();
+       self.oldorigin_y = ReadCoord();
+       self.oldorigin_z = ReadCoord();
+       self.avelocity_x = ReadCoord();
+       self.avelocity_y = ReadCoord();
+       self.avelocity_z = ReadCoord();
+
+       if(f & 2)
+       {
+               self.warpzone_fadestart = ReadShort();
+               self.warpzone_fadeend = max(self.warpzone_fadestart + 1, ReadShort());
+       }
+       else
+       {
+               self.warpzone_fadestart = 0;
+               self.warpzone_fadeend = 0;
+       }
+
+       // common stuff
+       WarpZone_SetUp(self, self.enemy.oldorigin, self.enemy.avelocity, self.oldorigin, self.avelocity);
+
+       // link me
+       //setmodel(self, self.model);
+       setorigin(self, self.origin);
+       setsize(self, self.mins, self.maxs);
+
+       // how to draw
+       // engine currently wants this
+       self.predraw = WarpZone_Fade_PreDraw;
+}
+
+void WarpZone_Camera_Read(float isnew)
+{SELFPARAM();
+       warpzone_cameras_exist = 1;
+       self.classname = "func_warpzone_camera";
+
+       int f = ReadByte();
+       if(f & 4)
+       {
+               self.origin_x = ReadCoord();
+               self.origin_y = ReadCoord();
+               self.origin_z = ReadCoord();
+       }
+       else
+               self.origin = '0 0 0';
+       self.modelindex = ReadShort();
+       self.mins_x = ReadCoord();
+       self.mins_y = ReadCoord();
+       self.mins_z = ReadCoord();
+       self.maxs_x = ReadCoord();
+       self.maxs_y = ReadCoord();
+       self.maxs_z = ReadCoord();
+       self.scale = ReadByte() / 16;
+       self.oldorigin_x = ReadCoord();
+       self.oldorigin_y = ReadCoord();
+       self.oldorigin_z = ReadCoord();
+       self.avelocity_x = ReadCoord();
+       self.avelocity_y = ReadCoord();
+       self.avelocity_z = ReadCoord();
+
+       if(f & 2)
+       {
+               self.warpzone_fadestart = ReadShort();
+               self.warpzone_fadeend = max(self.warpzone_fadestart + 1, ReadShort());
+       }
+       else
+       {
+               self.warpzone_fadestart = 0;
+               self.warpzone_fadeend = 0;
+       }
+
+       // common stuff
+       WarpZone_Camera_SetUp(self, self.oldorigin, self.avelocity);
+
+       // engine currently wants this
+       self.drawmask = MASK_NORMAL;
+
+       // link me
+       //setmodel(self, self.model);
+       setorigin(self, self.origin);
+       setsize(self, self.mins, self.maxs);
+
+       // how to draw
+       // engine currently wants this
+       self.predraw = WarpZone_Fade_PreDraw;
+}
+
+void CL_RotateMoves(vector ang) = #638;
+void WarpZone_Teleported_Read(float isnew)
+{SELFPARAM();
+       vector v;
+       self.classname = "warpzone_teleported";
+       v.x = ReadCoord();
+       v.y = ReadCoord();
+       v.z = ReadCoord();
+       if(!isnew)
+               return;
+       self.warpzone_transform = v;
+       setproperty(VF_CL_VIEWANGLES, WarpZone_TransformVAngles(self, getpropertyvec(VF_CL_VIEWANGLES)));
+       if(checkextension("DP_CSQC_ROTATEMOVES"))
+               CL_RotateMoves(v);
+               //CL_RotateMoves('0 90 0');
+}
+
+float warpzone_fixingview;
+float warpzone_fixingview_drawexteriormodel;
+
+void WarpZone_View_Outside()
+{
+       if(!warpzone_fixingview)
+               return;
+       warpzone_fixingview = 0;
+       cvar_set("r_drawexteriormodel", ftos(warpzone_fixingview_drawexteriormodel));
+}
+
+void WarpZone_View_Inside()
+{
+       if(autocvar_chase_active)
+       {
+               WarpZone_View_Outside();
+               return;
+       }
+       if(warpzone_fixingview)
+               return;
+       warpzone_fixingview = 1;
+       warpzone_fixingview_drawexteriormodel = cvar("r_drawexteriormodel");
+       cvar_set("r_drawexteriormodel", "0");
+}
+
+vector WarpZone_FixNearClip(vector o, vector c0, vector c1, vector c2, vector c3)
+{
+       vector mi, ma;
+       entity e;
+       float pd;
+
+       mi.x = min(o.x, c0_x, c1_x, c2_x, c3_x);
+       ma.x = max(o.x, c0_x, c1_x, c2_x, c3_x);
+       mi.y = min(o.y, c0_y, c1_y, c2_y, c3_y);
+       ma.y = max(o.y, c0_y, c1_y, c2_y, c3_y);
+       mi.z = min(o.z, c0_z, c1_z, c2_z, c3_z);
+       ma.z = max(o.z, c0_z, c1_z, c2_z, c3_z);
+
+       e = WarpZone_Find(mi, ma);
+       if(e)
+       {
+               if(WarpZone_PlaneDist(e, o) < 0)
+                       return '0 0 0';
+                       // can't really be, though, but if it is, this is not my warpzone, but a random different one in the same mins/maxs
+               pd = min(
+                               WarpZone_PlaneDist(e, c0),
+                               WarpZone_PlaneDist(e, c1),
+                               WarpZone_PlaneDist(e, c2),
+                               WarpZone_PlaneDist(e, c3)
+                       );
+               if(pd < 0)
+                       return e.warpzone_forward * -pd;
+       }
+
+       return '0 0 0';
+}
+
+void WarpZone_FixPMove()
+{
+       entity e;
+       e = WarpZone_Find(pmove_org, pmove_org);
+       if(e)
+       {
+               pmove_org = WarpZone_TransformOrigin(e, pmove_org);
+               input_angles = WarpZone_TransformVAngles(e, input_angles);
+       }
+}
+
+#ifndef KEEP_ROLL
+float autocvar_cl_rollkillspeed = 10;
+#endif
+void WarpZone_FixView()
+{
+       entity e;
+       vector org, ang, nearclip, corner0, corner1, corner2, corner3, o;
+       float f;
+
+       warpzone_save_view_origin = org = getpropertyvec(VF_ORIGIN);
+       warpzone_save_view_angles = ang = getpropertyvec(VF_ANGLES);
+
+       e = WarpZone_Find(org, org);
+       if(e)
+       {
+               org = WarpZone_TransformOrigin(e, org);
+               ang = WarpZone_TransformVAngles(e, ang);
+               WarpZone_View_Inside();
+       }
+       else
+               WarpZone_View_Outside();
+
+#ifndef KEEP_ROLL
+       float rick;
+       if(autocvar_cl_rollkillspeed)
+               f = max(0, (1 - frametime * autocvar_cl_rollkillspeed));
+       else
+               f = 0;
+
+       rick = getproperty(VF_CL_VIEWANGLES_Z);
+       rick *= f;
+       setproperty(VF_CL_VIEWANGLES_Z, rick);
+       ang.z *= f;
+#endif
+
+       setproperty(VF_ORIGIN, org);
+       setproperty(VF_ANGLES, ang);
+
+       nearclip = '0 0 1' * (cvar("r_nearclip") * 1.125);
+       corner0 = cs_unproject('0 0 0' + nearclip);
+       corner1 = cs_unproject('1 0 0' * cvar("vid_conwidth") + nearclip);
+       corner2 = cs_unproject('0 1 0' * cvar("vid_conheight") + nearclip);
+       corner3 = cs_unproject('1 0 0' * cvar("vid_conwidth") + '0 1 0' * cvar("vid_conheight") + nearclip);
+       o = WarpZone_FixNearClip(org, corner0, corner1, corner2, corner3);
+       if(o != '0 0 0')
+               setproperty(VF_ORIGIN, org + o);
+}
+
+void WarpZone_Init()
+{
+}
+
+void WarpZone_Shutdown()
+{
+       WarpZone_View_Outside();
+}
diff --git a/qcsrc/lib/warpzone/client.qh b/qcsrc/lib/warpzone/client.qh
new file mode 100644 (file)
index 0000000..016ac58
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef LIB_WARPZONE_CLIENT_H
+#define LIB_WARPZONE_CLIENT_H
+
+void WarpZone_Read(float bIsNewEntity);
+void WarpZone_Camera_Read(float bIsNewEntity);
+void WarpZone_Teleported_Read(float bIsNewEntity);
+
+void WarpZone_FixPMove();
+void WarpZone_FixView();
+
+void WarpZone_Init();
+void WarpZone_Shutdown();
+
+vector warpzone_save_view_origin;
+vector warpzone_save_view_angles;
+#endif
diff --git a/qcsrc/lib/warpzone/common.qc b/qcsrc/lib/warpzone/common.qc
new file mode 100644 (file)
index 0000000..6fe901b
--- /dev/null
@@ -0,0 +1,874 @@
+#include "common.qh"
+
+#if defined(CSQC)
+    #include "../../server/t_items.qh"
+#elif defined(MENUQC)
+#elif defined(SVQC)
+    #include "../../common/weapons/all.qh"
+#endif
+
+void WarpZone_Accumulator_Clear(entity acc)
+{
+       acc.warpzone_transform = '0 0 0';
+       acc.warpzone_shift = '0 0 0';
+}
+void WarpZone_Accumulator_AddTransform(entity acc, vector t, vector s)
+{
+       vector tr, st;
+       tr = AnglesTransform_Multiply(t, acc.warpzone_transform);
+       st = AnglesTransform_Multiply_GetPostShift(t, s, acc.warpzone_transform, acc.warpzone_shift);
+       acc.warpzone_transform = tr;
+       acc.warpzone_shift = st;
+}
+void WarpZone_Accumulator_Add(entity acc, entity wz)
+{
+       WarpZone_Accumulator_AddTransform(acc, wz.warpzone_transform, wz.warpzone_shift);
+}
+void WarpZone_Accumulator_AddInverseTransform(entity acc, vector t, vector s)
+{
+       vector tt, ss;
+       tt = AnglesTransform_Invert(t);
+       ss = AnglesTransform_PrePostShift_GetPostShift(s, tt, '0 0 0');
+       WarpZone_Accumulator_AddTransform(acc, tt, ss);
+       // yes, this probably can be done simpler... but this way is "obvious" :)
+}
+void WarpZone_Accumulator_AddInverse(entity acc, entity wz)
+{
+       WarpZone_Accumulator_AddInverseTransform(acc, wz.warpzone_transform, wz.warpzone_shift);
+}
+
+.vector(vector, vector) camera_transform;
+float autocvar_cl_warpzone_usetrace = 1;
+vector WarpZone_camera_transform(vector org, vector ang)
+{SELFPARAM();
+       vector vf, vr, vu;
+       if(self.warpzone_fadestart)
+               if(vlen(org - self.origin - 0.5 * (self.mins + self.maxs)) > self.warpzone_fadeend + 400)
+                       return org;
+                       // don't transform if zone faded out (plus 400qu safety margin for typical speeds and latencies)
+                       // unneeded on client, on server this helps a lot
+       vf = v_forward;
+       vr = v_right;
+       vu = v_up;
+       org = WarpZone_TransformOrigin(self, org);
+       vf = WarpZone_TransformVelocity(self, vf);
+       vr = WarpZone_TransformVelocity(self, vr);
+       vu = WarpZone_TransformVelocity(self, vu);
+       if(autocvar_cl_warpzone_usetrace)
+               traceline(self.warpzone_targetorigin, org, MOVE_NOMONSTERS, world);
+       else
+               trace_endpos = self.warpzone_targetorigin;
+       v_forward = vf;
+       v_right = vr;
+       v_up = vu;
+       return org;
+}
+
+void WarpZone_SetUp(entity e, vector my_org, vector my_ang, vector other_org, vector other_ang)
+{
+       e.warpzone_transform = AnglesTransform_RightDivide(other_ang, AnglesTransform_TurnDirectionFR(my_ang));
+       e.warpzone_shift = AnglesTransform_PrePostShift_GetPostShift(my_org, e.warpzone_transform, other_org);
+       e.warpzone_origin = my_org;
+       e.warpzone_targetorigin = other_org;
+       e.warpzone_angles = my_ang;
+       e.warpzone_targetangles = other_ang;
+       fixedmakevectors(my_ang); e.warpzone_forward = v_forward;
+       fixedmakevectors(other_ang); e.warpzone_targetforward = v_forward;
+       e.camera_transform = WarpZone_camera_transform;
+}
+
+vector WarpZone_Camera_camera_transform(vector org, vector ang)
+{SELFPARAM();
+       // a fixed camera view
+       if(self.warpzone_fadestart)
+               if(vlen(org - self.origin - 0.5 * (self.mins + self.maxs)) > self.warpzone_fadeend + 400)
+                       return org;
+                       // don't transform if zone faded out (plus 400qu safety margin for typical speeds and latencies)
+                       // unneeded on client, on server this helps a lot
+       trace_endpos = self.warpzone_origin;
+       makevectors(self.warpzone_angles);
+       return self.warpzone_origin;
+}
+
+void WarpZone_Camera_SetUp(entity e, vector my_org, vector my_ang) // we assume that e.oldorigin and e.avelocity point to view origin and direction
+{
+       e.warpzone_origin = my_org;
+       e.warpzone_angles = my_ang;
+       e.camera_transform = WarpZone_Camera_camera_transform;
+}
+
+.entity enemy;
+
+vector WarpZoneLib_BoxTouchesBrush_mins;
+vector WarpZoneLib_BoxTouchesBrush_maxs;
+entity WarpZoneLib_BoxTouchesBrush_ent;
+entity WarpZoneLib_BoxTouchesBrush_ignore;
+float WarpZoneLib_BoxTouchesBrush_Recurse()
+{
+       float s;
+       entity se;
+       float f;
+
+       tracebox('0 0 0', WarpZoneLib_BoxTouchesBrush_mins, WarpZoneLib_BoxTouchesBrush_maxs, '0 0 0', MOVE_NOMONSTERS, WarpZoneLib_BoxTouchesBrush_ignore);
+#ifdef CSQC
+       if (trace_networkentity)
+       {
+               LOG_TRACE("hit a network ent, cannot continue WarpZoneLib_BoxTouchesBrush\n");
+               // we cannot continue, as a player blocks us...
+               // so, abort
+               return 0;
+       }
+#endif
+       if (!trace_ent)
+               return 0;
+       if (trace_ent == WarpZoneLib_BoxTouchesBrush_ent)
+               return 1;
+
+       se = trace_ent;
+       s = se.solid;
+       se.solid = SOLID_NOT;
+       f = WarpZoneLib_BoxTouchesBrush_Recurse();
+       se.solid = s;
+
+       return f;
+}
+
+float WarpZoneLib_BoxTouchesBrush(vector mi, vector ma, entity e, entity ig)
+{
+    float f, s;
+
+    if(!e.modelindex || e.warpzone_isboxy)
+        return 1;
+
+    s = e.solid;
+    e.solid = SOLID_BSP;
+    WarpZoneLib_BoxTouchesBrush_mins = mi;
+    WarpZoneLib_BoxTouchesBrush_maxs = ma;
+    WarpZoneLib_BoxTouchesBrush_ent = e;
+    WarpZoneLib_BoxTouchesBrush_ignore = ig;
+    f = WarpZoneLib_BoxTouchesBrush_Recurse();
+    e.solid = s;
+
+    return f;
+}
+
+entity WarpZone_Find(vector mi, vector ma)
+{
+       // if we are near any warpzone planes - MOVE AWAY (work around nearclip)
+       entity e;
+       if(!warpzone_warpzones_exist)
+               return world;
+       for(e = world; (e = find(e, classname, "trigger_warpzone")); )
+               if(WarpZoneLib_BoxTouchesBrush(mi, ma, e, world))
+                       return e;
+       return world;
+}
+
+void WarpZone_MakeAllSolid()
+{
+       entity e;
+       if(!warpzone_warpzones_exist)
+               return;
+       for(e = world; (e = find(e, classname, "trigger_warpzone")); )
+               e.solid = SOLID_BSP;
+}
+
+void WarpZone_MakeAllOther()
+{
+       entity e;
+       if(!warpzone_warpzones_exist)
+               return;
+       for(e = world; (e = find(e, classname, "trigger_warpzone")); )
+               e.solid = SOLID_TRIGGER;
+}
+
+void WarpZone_Trace_InitTransform()
+{
+       if(!WarpZone_trace_transform)
+       {
+               WarpZone_trace_transform = spawn();
+               WarpZone_trace_transform.classname = "warpzone_trace_transform";
+       }
+       WarpZone_Accumulator_Clear(WarpZone_trace_transform);
+}
+void WarpZone_Trace_AddTransform(entity wz)
+{
+       WarpZone_Accumulator_Add(WarpZone_trace_transform, wz);
+}
+
+void WarpZone_TraceBox_ThroughZone(vector org, vector mi, vector ma, vector end, float nomonsters, entity forent, entity zone, WarpZone_trace_callback_t cb)
+{
+       float nomonsters_adjusted;
+       float frac, sol, i;
+       float contentshack;
+       vector o0, e0;
+       entity wz;
+       vector vf, vr, vu;
+
+       WarpZone_trace_forent = forent;
+       WarpZone_trace_firstzone = world;
+       WarpZone_trace_lastzone = world;
+       WarpZone_Trace_InitTransform();
+       if(!warpzone_warpzones_exist)
+       {
+               if(nomonsters == MOVE_NOTHING)
+               {
+                       trace_endpos = end;
+                       trace_fraction = 1;
+                       if(cb)
+                               cb(org, trace_endpos, end);
+                       return;
+               }
+               else
+               {
+                       tracebox(org, mi, ma, end, nomonsters, WarpZone_trace_forent);
+                       if(cb)
+                               cb(org, trace_endpos, end);
+                       return;
+               }
+       }
+
+       vf = v_forward;
+       vr = v_right;
+       vu = v_up;
+       o0 = org;
+       e0 = end;
+
+       switch(nomonsters)
+       {
+               case MOVE_WORLDONLY:
+               case MOVE_NOTHING:
+                       nomonsters_adjusted = MOVE_NOMONSTERS;
+                       break;
+               default:
+                       nomonsters_adjusted = nomonsters;
+                       break;
+       }
+       if((contentshack = (WarpZone_trace_forent.dphitcontentsmask && !(WarpZone_trace_forent.dphitcontentsmask & DPCONTENTS_SOLID))))
+               BITSET_ASSIGN(WarpZone_trace_forent.dphitcontentsmask, DPCONTENTS_SOLID);
+
+       // if starting in warpzone, first transform
+       wz = WarpZone_Find(org + mi, org + ma);
+       if(wz)
+       {
+               WarpZone_trace_firstzone = wz;
+               WarpZone_trace_lastzone = wz;
+               if(zone && wz != zone)
+               {
+                       // we are in ANOTHER warpzone. This is bad. Make a zero length trace and return.
+                       sol = 1;
+                       trace_fraction = 0;
+                       trace_endpos = org;
+                       goto fail;
+               }
+               WarpZone_Trace_AddTransform(wz);
+               org = WarpZone_TransformOrigin(wz, org);
+               end = WarpZone_TransformOrigin(wz, end);
+       }
+       WarpZone_MakeAllSolid();
+       sol = -1;
+       frac = 0;
+       i = 16;
+       for (;;)
+       {
+               if(--i < 1)
+               {
+                       LOG_TRACE("Too many warpzones in sequence, aborting trace.\n");
+                       trace_ent = world;
+                       break;
+               }
+               tracebox(org, mi, ma, end, nomonsters_adjusted, WarpZone_trace_forent);
+               if(cb)
+                       cb(org, trace_endpos, end);
+               if(sol < 0)
+                       sol = trace_startsolid;
+
+               frac = trace_fraction = frac + (1 - frac) * trace_fraction;
+               if(trace_fraction >= 1)
+                       break;
+               if(trace_ent.classname != "trigger_warpzone")
+               {
+                       if((nomonsters == MOVE_NOTHING) || ((nomonsters == MOVE_WORLDONLY) && trace_ent) || (contentshack && (trace_dphitcontents & WarpZone_trace_forent.dphitcontentsmask) == DPCONTENTS_SOLID))
+                       {
+                               // continue the trace, ignoring this hit (we only care for warpzones)
+                               org = trace_endpos + normalize(end - org);
+                               continue;
+                               // we cannot do an inverted trace here, as we do care for further warpzones inside that "solid" to be found
+                               // otherwise, players could block entrances that way
+                       }
+                       break;
+               }
+               if(trace_ent == wz)
+               {
+                       // FIXME can this check be removed? Do we really need it?
+                       LOG_TRACE("I transformed into the same zone again, wtf, aborting the trace\n");
+                       trace_ent = world;
+                       break;
+               }
+               wz = trace_ent;
+               if(!WarpZone_trace_firstzone)
+                       WarpZone_trace_firstzone = wz;
+               WarpZone_trace_lastzone = wz;
+               if(zone && wz != zone)
+                       break;
+               WarpZone_Trace_AddTransform(wz);
+               // we hit a warpzone... so, let's perform the trace after the warp again
+               org = WarpZone_TransformOrigin(wz, trace_endpos);
+               end = WarpZone_TransformOrigin(wz, end);
+
+               // we got warped, so let's step back a bit
+               tracebox(org, mi, ma, org + normalize(org - end) * 32, nomonsters_adjusted, WarpZone_trace_forent);
+               org = trace_endpos;
+       }
+       WarpZone_MakeAllOther();
+:fail
+       if(contentshack)
+               BITCLR_ASSIGN(WarpZone_trace_forent.dphitcontentsmask, DPCONTENTS_SOLID);
+       trace_startsolid = sol;
+       v_forward = vf;
+       v_right = vr;
+       v_up = vu;
+}
+
+void WarpZone_TraceBox(vector org, vector mi, vector ma, vector end, float nomonsters, entity forent)
+{
+       WarpZone_TraceBox_ThroughZone(org, mi, ma, end, nomonsters, forent, world, WarpZone_trace_callback_t_null);
+}
+
+void WarpZone_TraceLine(vector org, vector end, float nomonsters, entity forent)
+{
+       WarpZone_TraceBox(org, '0 0 0', '0 0 0', end, nomonsters, forent);
+}
+
+void WarpZone_TraceToss_ThroughZone(entity e, entity forent, entity zone, WarpZone_trace_callback_t cb)
+{
+       float g, dt, i;
+       vector vf, vr, vu, v0, o0;
+       entity wz;
+
+       o0 = e.origin;
+       v0 = e.velocity;
+       g = cvar("sv_gravity") * e.gravity;
+
+       WarpZone_trace_forent = forent;
+       WarpZone_trace_firstzone = world;
+       WarpZone_trace_lastzone = world;
+       WarpZone_Trace_InitTransform();
+       WarpZone_tracetoss_time = 0;
+       if(!warpzone_warpzones_exist)
+       {
+               tracetoss(e, WarpZone_trace_forent);
+               if(cb)
+                       cb(e.origin, trace_endpos, trace_endpos);
+               dt = vlen(e.origin - o0) / vlen(e.velocity);
+               WarpZone_tracetoss_time += dt;
+               e.velocity_z -= dt * g;
+               WarpZone_tracetoss_velocity = e.velocity;
+               e.velocity = v0;
+               return;
+       }
+
+       vf = v_forward;
+       vr = v_right;
+       vu = v_up;
+
+       // if starting in warpzone, first transform
+       wz = WarpZone_Find(e.origin + e.mins, e.origin + e.maxs);
+       if(wz)
+       {
+               WarpZone_trace_firstzone = wz;
+               WarpZone_trace_lastzone = wz;
+               if(zone && wz != zone)
+               {
+                       // we are in ANOTHER warpzone. This is bad. Make a zero length trace and return.
+
+                       WarpZone_tracetoss_time = 0;
+                       trace_endpos = o0;
+                       goto fail;
+               }
+               WarpZone_Trace_AddTransform(wz);
+               setorigin(e, WarpZone_TransformOrigin(wz, e.origin));
+               e.velocity = WarpZone_TransformVelocity(wz, e.velocity);
+       }
+       WarpZone_MakeAllSolid();
+       i = 16;
+       for (;;)
+       {
+               if(--i < 1)
+               {
+                       LOG_TRACE("Too many warpzones in sequence, aborting trace.\n");
+                       trace_ent = world;
+                       break;
+               }
+               tracetoss(e, WarpZone_trace_forent);
+               if(cb)
+                       cb(e.origin, trace_endpos, trace_endpos);
+               dt = vlen(trace_endpos - e.origin) / vlen(e.velocity);
+               WarpZone_tracetoss_time += dt;
+               e.origin = trace_endpos;
+               e.velocity_z -= dt * g;
+               if(trace_fraction >= 1)
+                       break;
+               if(trace_ent.classname != "trigger_warpzone")
+                       break;
+               if(trace_ent == wz)
+               {
+                       // FIXME can this check be removed? Do we really need it?
+                       LOG_TRACE("I transformed into the same zone again, wtf, aborting the trace\n");
+                       trace_ent = world;
+                       break;
+               }
+               wz = trace_ent;
+               if(!WarpZone_trace_firstzone)
+                       WarpZone_trace_firstzone = wz;
+               WarpZone_trace_lastzone = wz;
+               if(zone && wz != zone)
+                       break;
+               WarpZone_Trace_AddTransform(wz);
+               // we hit a warpzone... so, let's perform the trace after the warp again
+               e.origin = WarpZone_TransformOrigin(wz, e.origin);
+               e.velocity = WarpZone_TransformVelocity(wz, e.velocity);
+
+               // we got warped, so let's step back a bit
+               e.velocity = -e.velocity;
+               tracetoss(e, WarpZone_trace_forent);
+               dt = vlen(trace_endpos - e.origin) / vlen(e.velocity);
+               WarpZone_tracetoss_time -= dt;
+               e.origin = trace_endpos;
+               e.velocity = -e.velocity;
+       }
+       WarpZone_MakeAllOther();
+:fail
+       WarpZone_tracetoss_velocity = e.velocity;
+       v_forward = vf;
+       v_right = vr;
+       v_up = vu;
+       // restore old entity data (caller just uses trace_endpos, WarpZone_tracetoss_velocity and the transform)
+       e.velocity = v0;
+       e.origin = o0;
+}
+
+void WarpZone_TraceToss(entity e, entity forent)
+{
+       WarpZone_TraceToss_ThroughZone(e, forent, world, WarpZone_trace_callback_t_null);
+}
+
+entity WarpZone_TrailParticles_trace_callback_own;
+float WarpZone_TrailParticles_trace_callback_eff;
+void WarpZone_TrailParticles_trace_callback(vector from, vector endpos, vector to)
+{
+       trailparticles(WarpZone_TrailParticles_trace_callback_own, WarpZone_TrailParticles_trace_callback_eff, from, endpos);
+}
+
+void WarpZone_TrailParticles(entity own, float eff, vector org, vector end)
+{
+       WarpZone_TrailParticles_trace_callback_own = own;
+       WarpZone_TrailParticles_trace_callback_eff = eff;
+       WarpZone_TraceBox_ThroughZone(org, '0 0 0', '0 0 0', end, MOVE_NOMONSTERS, world, world, WarpZone_TrailParticles_trace_callback);
+}
+
+#ifdef CSQC
+float WarpZone_TrailParticles_trace_callback_f;
+float WarpZone_TrailParticles_trace_callback_flags;
+void WarpZone_TrailParticles_WithMultiplier_trace_callback(vector from, vector endpos, vector to)
+{
+       boxparticles(WarpZone_TrailParticles_trace_callback_eff, WarpZone_TrailParticles_trace_callback_own, from, endpos, WarpZone_TrailParticles_trace_callback_own.velocity, WarpZone_TrailParticles_trace_callback_own.velocity, WarpZone_TrailParticles_trace_callback_f, WarpZone_TrailParticles_trace_callback_flags);
+}
+
+void WarpZone_TrailParticles_WithMultiplier(entity own, float eff, vector org, vector end, float f, int boxflags)
+{
+       WarpZone_TrailParticles_trace_callback_own = own;
+       WarpZone_TrailParticles_trace_callback_eff = eff;
+       WarpZone_TrailParticles_trace_callback_f = f;
+       WarpZone_TrailParticles_trace_callback_flags = boxflags | PARTICLES_DRAWASTRAIL;
+       WarpZone_TraceBox_ThroughZone(org, '0 0 0', '0 0 0', end, MOVE_NOMONSTERS, world, world, WarpZone_TrailParticles_WithMultiplier_trace_callback);
+}
+#endif
+
+float WarpZone_PlaneDist(entity wz, vector v)
+{
+       return (v - wz.warpzone_origin) * wz.warpzone_forward;
+}
+
+float WarpZone_TargetPlaneDist(entity wz, vector v)
+{
+       return (v - wz.warpzone_targetorigin) * wz.warpzone_targetforward;
+}
+
+vector WarpZone_TransformOrigin(entity wz, vector v)
+{
+       return wz.warpzone_shift + AnglesTransform_Apply(wz.warpzone_transform, v);
+}
+
+vector WarpZone_TransformVelocity(entity wz, vector v)
+{
+       return AnglesTransform_Apply(wz.warpzone_transform, v);
+}
+
+vector WarpZone_TransformAngles(entity wz, vector v)
+{
+       return AnglesTransform_ApplyToAngles(wz.warpzone_transform, v);
+}
+
+vector WarpZone_TransformVAngles(entity wz, vector ang)
+{
+#ifdef KEEP_ROLL
+       float roll;
+       roll = ang.z;
+       ang.z = 0;
+#endif
+
+       ang = AnglesTransform_ApplyToVAngles(wz.warpzone_transform, ang);
+
+#ifdef KEEP_ROLL
+       ang = AnglesTransform_Normalize(ang, true);
+       ang = AnglesTransform_CancelRoll(ang);
+       ang.z = roll;
+#else
+       ang = AnglesTransform_Normalize(ang, false);
+#endif
+
+       return ang;
+}
+
+vector WarpZone_UnTransformOrigin(entity wz, vector v)
+{
+       return AnglesTransform_Apply(AnglesTransform_Invert(wz.warpzone_transform), v - wz.warpzone_shift);
+}
+
+vector WarpZone_UnTransformVelocity(entity wz, vector v)
+{
+       return AnglesTransform_Apply(AnglesTransform_Invert(wz.warpzone_transform), v);
+}
+
+vector WarpZone_UnTransformAngles(entity wz, vector v)
+{
+       return AnglesTransform_ApplyToAngles(AnglesTransform_Invert(wz.warpzone_transform), v);
+}
+
+vector WarpZone_UnTransformVAngles(entity wz, vector ang)
+{
+       float roll;
+
+       roll = ang.z;
+       ang.z = 0;
+
+       ang = AnglesTransform_ApplyToVAngles(AnglesTransform_Invert(wz.warpzone_transform), ang);
+       ang = AnglesTransform_Normalize(ang, true);
+       ang = AnglesTransform_CancelRoll(ang);
+
+       ang.z = roll;
+       return ang;
+}
+
+vector WarpZoneLib_NearestPointOnBox(vector mi, vector ma, vector org)
+{
+       vector nearest;
+       nearest.x = bound(mi.x, org.x, ma.x);
+       nearest.y = bound(mi.y, org.y, ma.y);
+       nearest.z = bound(mi.z, org.z, ma.z);
+       return nearest;
+}
+
+bool WarpZoneLib_BadEntity(entity e)
+{
+       string myclassname = e.classname;
+       if (e.instanceOfObject) return true;
+       switch(myclassname)
+       {
+               case "deathtype":
+               case "weaponentity":
+               case "exteriorweaponentity":
+               case "csqc_score_team":
+               case "pingplreport":
+               case "ent_client_scoreinfo":
+               case "saved_cvar_value":
+               case "accuracy":
+               case "entcs_sender":
+               case "entcs_receiver":
+               case "clientinit":
+               case "sprite_waypoint":
+               case "waypoint":
+               case "gibsplash":
+               //case "net_linked": // actually some real entities are linked without classname, fail
+               case "":
+                       return true;
+       }
+
+       if(startsWith(myclassname, "msg_"))
+               return true;
+
+       if(startsWith(myclassname, "target_"))
+               return true;
+
+       if(startsWith(myclassname, "info_"))
+               return true;
+
+       return false;
+}
+
+.float WarpZone_findradius_hit;
+.entity WarpZone_findradius_next;
+void WarpZone_FindRadius_Recurse(vector org, float rad,        vector org0,               vector transform, vector shift, float needlineofsight)
+//                               blast origin of current search   original blast origin   how to untransform (victim to blast system)
+{
+       vector org_new;
+       vector org0_new;
+       vector shift_new, transform_new;
+       vector p;
+       entity e, e0;
+       entity wz;
+       if(rad <= 0)
+               return;
+       e0 = findradius(org, rad);
+       wz = world;
+
+       for(e = e0; e; e = e.chain)
+       {
+               if(WarpZoneLib_BadEntity(e))
+                       continue;
+               p = WarpZoneLib_NearestPointOnBox(e.origin + e.mins, e.origin + e.maxs, org0);
+               if(needlineofsight)
+               {
+                       traceline(org, p, MOVE_NOMONSTERS, e);
+                       if(trace_fraction < 1)
+                               continue;
+               }
+               if(!e.WarpZone_findradius_hit || vlen(e.WarpZone_findradius_dist) > vlen(org0 - p))
+               {
+                       e.WarpZone_findradius_nearest = p;
+                       e.WarpZone_findradius_dist = org0 - p;
+                       e.WarpZone_findradius_findorigin = org;
+                       e.WarpZone_findradius_findradius = rad;
+                       if(e.classname == "warpzone_refsys")
+                       {
+                               // ignore, especially: do not overwrite the refsys parameters
+                       }
+                       else if(e.classname == "trigger_warpzone")
+                       {
+                               e.WarpZone_findradius_next = wz;
+                               wz = e;
+                               e.WarpZone_findradius_hit = 1;
+                               e.enemy.WarpZone_findradius_dist = '0 0 0'; // we don't want to go through this zone ever again
+                               e.enemy.WarpZone_findradius_hit = 1;
+                       }
+                       else
+                       {
+                               e.warpzone_transform = transform;
+                               e.warpzone_shift = shift;
+                               e.WarpZone_findradius_hit = 1;
+                       }
+               }
+       }
+       for(e = wz; e; e = e.WarpZone_findradius_next)
+       {
+               if(WarpZoneLib_BadEntity(e))
+                       continue;
+
+               org0_new = WarpZone_TransformOrigin(e, org);
+               traceline(e.warpzone_targetorigin, org0_new, MOVE_NOMONSTERS, e);
+               org_new = trace_endpos;
+
+               transform_new = AnglesTransform_Multiply(e.warpzone_transform, transform);
+               shift_new = AnglesTransform_Multiply_GetPostShift(e.warpzone_transform, e.warpzone_shift, transform, shift);
+               WarpZone_FindRadius_Recurse(
+                       org_new,
+                       bound(0, rad - vlen(org_new - org0_new), rad - 8),
+                       org0_new,
+                       transform_new, shift_new,
+                       needlineofsight);
+               e.WarpZone_findradius_hit = 0;
+               e.enemy.WarpZone_findradius_hit = 0;
+       }
+}
+entity WarpZone_FindRadius(vector org, float rad, float needlineofsight)
+{
+       entity e0, e;
+       WarpZone_FindRadius_Recurse(org, rad, org, '0 0 0', '0 0 0', needlineofsight);
+       e0 = findchainfloat(WarpZone_findradius_hit, 1);
+       for(e = e0; e; e = e.chain)
+               e.WarpZone_findradius_hit = 0;
+       return e0;
+}
+
+.entity WarpZone_refsys;
+void WarpZone_RefSys_GC()
+{SELFPARAM();
+       // garbage collect unused reference systems
+       self.nextthink = time + 1;
+       if(self.owner.WarpZone_refsys != self)
+               remove(self);
+}
+void WarpZone_RefSys_CheckCreate(entity me)
+{
+       if(me.WarpZone_refsys.owner != me)
+       {
+               me.WarpZone_refsys = spawn();
+               me.WarpZone_refsys.classname = "warpzone_refsys";
+               me.WarpZone_refsys.owner = me;
+               me.WarpZone_refsys.think = WarpZone_RefSys_GC;
+               me.WarpZone_refsys.nextthink = time + 1;
+               WarpZone_Accumulator_Clear(me.WarpZone_refsys);
+       }
+}
+void WarpZone_RefSys_Clear(entity me)
+{
+       if(me.WarpZone_refsys)
+       {
+               remove(me.WarpZone_refsys);
+               me.WarpZone_refsys = world;
+       }
+}
+void WarpZone_RefSys_AddTransform(entity me, vector t, vector s)
+{
+       if(t != '0 0 0' || s != '0 0 0')
+       {
+               WarpZone_RefSys_CheckCreate(me);
+               WarpZone_Accumulator_AddTransform(me.WarpZone_refsys, t, s);
+       }
+}
+void WarpZone_RefSys_Add(entity me, entity wz)
+{
+       WarpZone_RefSys_AddTransform(me, wz.warpzone_transform, wz.warpzone_shift);
+}
+void WarpZone_RefSys_AddInverseTransform(entity me, vector t, vector s)
+{
+       if(t != '0 0 0' || s != '0 0 0')
+       {
+               WarpZone_RefSys_CheckCreate(me);
+               WarpZone_Accumulator_AddInverseTransform(me.WarpZone_refsys, t, s);
+       }
+}
+void WarpZone_RefSys_AddInverse(entity me, entity wz)
+{
+       WarpZone_RefSys_AddInverseTransform(me, wz.warpzone_transform, wz.warpzone_shift);
+}
+.vector WarpZone_refsys_incremental_shift;
+.vector WarpZone_refsys_incremental_transform;
+void WarpZone_RefSys_AddIncrementally(entity me, entity ref)
+{
+       //vector t, s;
+       if(me.WarpZone_refsys_incremental_transform == ref.WarpZone_refsys.warpzone_transform)
+       if(me.WarpZone_refsys_incremental_shift == ref.WarpZone_refsys.warpzone_shift)
+               return;
+       WarpZone_Accumulator_AddInverseTransform(me.WarpZone_refsys, me.WarpZone_refsys_incremental_transform, me.WarpZone_refsys_incremental_shift);
+       WarpZone_Accumulator_Add(me.WarpZone_refsys, ref.WarpZone_refsys);
+       me.WarpZone_refsys_incremental_shift = ref.WarpZone_refsys.warpzone_shift;
+       me.WarpZone_refsys_incremental_transform = ref.WarpZone_refsys.warpzone_transform;
+}
+void WarpZone_RefSys_BeginAddingIncrementally(entity me, entity ref)
+{
+       me.WarpZone_refsys_incremental_shift = ref.WarpZone_refsys.warpzone_shift;
+       me.WarpZone_refsys_incremental_transform = ref.WarpZone_refsys.warpzone_transform;
+}
+vector WarpZone_RefSys_TransformOrigin(entity from, entity to, vector org)
+{
+       if(from.WarpZone_refsys)
+               org = WarpZone_UnTransformOrigin(from.WarpZone_refsys, org);
+       if(to.WarpZone_refsys)
+               org = WarpZone_TransformOrigin(to.WarpZone_refsys, org);
+       return org;
+}
+vector WarpZone_RefSys_TransformVelocity(entity from, entity to, vector vel)
+{
+       if(from.WarpZone_refsys)
+               vel = WarpZone_UnTransformVelocity(from.WarpZone_refsys, vel);
+       if(to.WarpZone_refsys)
+               vel = WarpZone_TransformVelocity(to.WarpZone_refsys, vel);
+       return vel;
+}
+vector WarpZone_RefSys_TransformAngles(entity from, entity to, vector ang)
+{
+       if(from.WarpZone_refsys)
+               ang = WarpZone_UnTransformAngles(from.WarpZone_refsys, ang);
+       if(to.WarpZone_refsys)
+               ang = WarpZone_TransformAngles(to.WarpZone_refsys, ang);
+       return ang;
+}
+vector WarpZone_RefSys_TransformVAngles(entity from, entity to, vector ang)
+{
+       if(from.WarpZone_refsys)
+               ang = WarpZone_UnTransformVAngles(from.WarpZone_refsys, ang);
+       if(to.WarpZone_refsys)
+               ang = WarpZone_TransformVAngles(to.WarpZone_refsys, ang);
+       return ang;
+}
+void WarpZone_RefSys_Copy(entity me, entity from)
+{
+       if(from.WarpZone_refsys)
+       {
+               WarpZone_RefSys_CheckCreate(me);
+               me.WarpZone_refsys.warpzone_shift = from.WarpZone_refsys.warpzone_shift;
+               me.WarpZone_refsys.warpzone_transform = from.WarpZone_refsys.warpzone_transform;
+       }
+       else
+               WarpZone_RefSys_Clear(me);
+}
+entity WarpZone_RefSys_SpawnSameRefSys(entity me)
+{
+       entity e;
+       e = spawn();
+       WarpZone_RefSys_Copy(e, me);
+       return e;
+}
+
+float WarpZoneLib_ExactTrigger_Touch()
+{SELFPARAM();
+       return !WarpZoneLib_BoxTouchesBrush(other.absmin, other.absmax, self, other);
+}
+
+
+void WarpZoneLib_MoveOutOfSolid_Expand(entity e, vector by)
+{
+       float eps = 0.0625;
+       tracebox(e.origin, e.mins - '1 1 1' * eps, e.maxs + '1 1 1' * eps, e.origin + by, MOVE_WORLDONLY, e);
+       if (trace_startsolid)
+               return;
+       if (trace_fraction < 1)
+       {
+               // hit something
+               // adjust origin in the other direction...
+               setorigin(e,e.origin - by * (1 - trace_fraction));
+       }
+}
+
+float WarpZoneLib_MoveOutOfSolid(entity e)
+{
+       vector o, m0, m1;
+
+       o = e.origin;
+       traceline(o, o, MOVE_WORLDONLY, e);
+       if (trace_startsolid)
+               return false;
+
+       tracebox(o, e.mins, e.maxs, o, MOVE_WORLDONLY, e);
+       if (!trace_startsolid)
+               return true;
+
+       m0 = e.mins;
+       m1 = e.maxs;
+       e.mins = '0 0 0';
+       e.maxs = '0 0 0';
+       WarpZoneLib_MoveOutOfSolid_Expand(e, '1 0 0' * m0_x);
+       e.mins_x = m0_x;
+       WarpZoneLib_MoveOutOfSolid_Expand(e, '1 0 0' * m1_x);
+       e.maxs_x = m1_x;
+       WarpZoneLib_MoveOutOfSolid_Expand(e, '0 1 0' * m0_y);
+       e.mins_y = m0_y;
+       WarpZoneLib_MoveOutOfSolid_Expand(e, '0 1 0' * m1_y);
+       e.maxs_y = m1_y;
+       WarpZoneLib_MoveOutOfSolid_Expand(e, '0 0 1' * m0_z);
+       e.mins_z = m0_z;
+       WarpZoneLib_MoveOutOfSolid_Expand(e, '0 0 1' * m1_z);
+       e.maxs_z = m1_z;
+       setorigin(e, e.origin);
+
+       tracebox(e.origin, e.mins, e.maxs, e.origin, MOVE_WORLDONLY, e);
+       if (trace_startsolid)
+       {
+               setorigin(e, o);
+               return false;
+       }
+
+       return true;
+}
diff --git a/qcsrc/lib/warpzone/common.qh b/qcsrc/lib/warpzone/common.qh
new file mode 100644 (file)
index 0000000..d0c1f22
--- /dev/null
@@ -0,0 +1,116 @@
+#ifndef LIB_WARPZONE_COMMON_H
+#define LIB_WARPZONE_COMMON_H
+
+// uncomment this if your mod uses the roll angle in fixangle
+// #define KEEP_ROLL
+
+float warpzone_warpzones_exist;
+float warpzone_cameras_exist;
+
+.float warpzone_isboxy;
+.vector warpzone_shift;
+.vector warpzone_origin;
+.vector warpzone_angles;
+.vector warpzone_forward;
+.vector warpzone_targetorigin;
+.vector warpzone_targetangles;
+.vector warpzone_targetforward;
+.vector warpzone_transform;
+.float warpzone_fadestart;
+.float warpzone_fadeend;
+void WarpZone_SetUp(entity e, vector my_org, vector my_ang, vector other_org, vector other_ang);
+void WarpZone_Camera_SetUp(entity e, vector my_org, vector my_ang);
+
+float WarpZoneLib_BoxTouchesBrush(vector mi, vector ma, entity e, entity ig);
+vector WarpZoneLib_NearestPointOnBox(vector mi, vector ma, vector org);
+
+entity WarpZone_Find(vector mi, vector ma);
+void WarpZone_MakeAllSolid();
+void WarpZone_MakeAllOther();
+
+#define MOVE_NOTHING -1
+entity WarpZone_trace_forent; // temp, callback is allowed to change it
+typedef void(vector start, vector hit, vector end) WarpZone_trace_callback_t; // called on every elementary trace
+var WarpZone_trace_callback_t WarpZone_trace_callback_t_null;
+entity WarpZone_trace_transform; // transform accumulator during a trace
+entity WarpZone_trace_firstzone; // first warpzone hit by a trace (can differ from the requested zone in case of _ThroughZone, the trace is aborted then)
+entity WarpZone_trace_lastzone; // first warpzone hit by a trace (can differ from the requested zone in case of _ThroughZone, the trace is aborted then)
+vector WarpZone_tracetoss_velocity; // ending velocity of a tracetoss (post-transform)
+float WarpZone_tracetoss_time; // duration of toss (approximate)
+void WarpZone_TraceBox(vector org, vector min, vector max, vector end, float nomonsters, entity forent);
+void WarpZone_TraceBox_ThroughZone(vector org, vector min, vector max, vector end, float nomonsters, entity forent, entity zone, WarpZone_trace_callback_t cb);
+void WarpZone_TraceLine(vector org, vector end, float nomonsters, entity forent);
+void WarpZone_TraceToss(entity e, entity forent);
+void WarpZone_TraceToss_ThroughZone(entity e, entity forent, entity zone, WarpZone_trace_callback_t cb);
+void WarpZone_TrailParticles(entity own, float eff, vector org, vector end);
+#ifdef CSQC
+void WarpZone_TrailParticles_WithMultiplier(entity own, float eff, vector org, vector end, float f, float boxflags);
+#endif
+
+.vector WarpZone_findradius_dist;
+.vector WarpZone_findradius_nearest;
+// also set: warpzone parameters, so WarpZone_TransformOrigin can transform vectors from blast's to victim's system
+.vector WarpZone_findradius_findorigin;
+.float WarpZone_findradius_findradius;
+entity WarpZone_FindRadius(vector org, float radius, float needlineofsight);
+
+float WarpZone_PlaneDist(entity wz, vector v);
+float WarpZone_TargetPlaneDist(entity wz, vector v);
+vector WarpZone_TransformOrigin(entity wz, vector v);
+vector WarpZone_TransformVelocity(entity wz, vector v);
+vector WarpZone_TransformAngles(entity wz, vector v);
+vector WarpZone_TransformVAngles(entity wz, vector v);
+vector WarpZone_UnTransformOrigin(entity wz, vector v);
+vector WarpZone_UnTransformVelocity(entity wz, vector v);
+vector WarpZone_UnTransformAngles(entity wz, vector v);
+vector WarpZone_UnTransformVAngles(entity wz, vector v);
+
+// reference systems (chained warpzone transforms)
+void WarpZone_RefSys_Clear(entity me); // R := id
+void WarpZone_RefSys_Add(entity me, entity wz); // me.R := wz me.R
+void WarpZone_RefSys_AddInverse(entity me, entity wz); // me.R := wz^-1 me.R
+void WarpZone_RefSys_AddTransform(entity me, vector t, vector s); // me.R := [t s] me.R
+void WarpZone_RefSys_AddInverseTransform(entity me, vector t, vector s); // me.R := [t s]^-1 me.R
+
+// makes this reference system track ref's changes
+// NOTE: this is ONLY sensible if WarpZone_RefSys_Add is no longer called on "me" while doing this
+// To achieve this, make sure no touch events on warpzone are raised by this entity
+// or set a movetype that causes no warpzoning (e.g. MOVETYPE_NONE, MOVETYPE_FOLLOW)
+void WarpZone_RefSys_AddIncrementally(entity me, entity ref); // me.R := ref.R me.Rref^-1 me.R; me.Rref := ref.R
+void WarpZone_RefSys_BeginAddingIncrementally(entity me, entity ref); // me.Rref := ref.R
+
+vector WarpZone_RefSys_TransformOrigin(entity from, entity to, vector org); // return to.R from.R^-1 org
+vector WarpZone_RefSys_TransformVelocity(entity from, entity to, vector vel); // return to.R from.R^-1 vel
+vector WarpZone_RefSys_TransformAngles(entity from, entity to, vector ang); // return to.R from.R^-1 ang
+vector WarpZone_RefSys_TransformVAngles(entity from, entity to, vector ang); // return to.R from.R^-1 ang
+void WarpZone_RefSys_Copy(entity me, entity from); // to.R := from.R
+entity WarpZone_RefSys_SpawnSameRefSys(entity me); // spawn().R = me.R
+
+#ifndef BITCLR
+# define BITCLR(a,b) ((a) - ((a) & (b)))
+#endif
+#ifndef BITSET
+# define BITSET(a,b) ((a) | (b))
+#endif
+#ifndef BITXOR
+# define BITXOR(a,b) (((a) | (b)) - ((a) & (b)))
+#endif
+#ifndef BITCLR_ASSIGN
+# define BITCLR_ASSIGN(a,b) ((a) = (a) - ((a) & (b)))
+#endif
+#ifndef BITSET_ASSIGN
+# define BITSET_ASSIGN(a,b) ((a) |= (b))
+#endif
+#ifndef BITXOR_ASSIGN
+# define BITXOR_ASSIGN(a,b) ((a) = ((a) | (b)) - ((a) & (b)))
+#endif
+float WarpZoneLib_MoveOutOfSolid(entity e);
+#define move_out_of_solid(e) WarpZoneLib_MoveOutOfSolid(e)
+
+float WarpZoneLib_ExactTrigger_Touch();
+void WarpZoneLib_ExactTrigger_Init();
+
+// WARNING: this kills the trace globals
+#define EXACTTRIGGER_TOUCH if(WarpZoneLib_ExactTrigger_Touch()) return
+#define EXACTTRIGGER_INIT  WarpZoneLib_ExactTrigger_Init()
+#endif
diff --git a/qcsrc/lib/warpzone/mathlib.qc b/qcsrc/lib/warpzone/mathlib.qc
new file mode 100644 (file)
index 0000000..92b7ee1
--- /dev/null
@@ -0,0 +1,300 @@
+#include "mathlib.qh"
+#if defined(CSQC)
+#elif defined(MENUQC)
+#elif defined(SVQC)
+#endif
+
+int fpclassify(float x)
+{
+       if(isnan(x))
+               return FP_NAN;
+       if(isinf(x))
+               return FP_INFINITE;
+       if(x == 0)
+               return FP_ZERO;
+       return FP_NORMAL;
+}
+bool isfinite(float x)
+{
+       return !(isnan(x) || isinf(x));
+}
+bool isinf(float x)
+{
+       return (x != 0) && (x + x == x);
+}
+bool isnan(float x)
+{
+       float y;
+       y = x;
+       return (x != y);
+}
+bool isnormal(float x)
+{
+       return isfinite(x);
+}
+bool signbit(float x)
+{
+       return (x < 0);
+}
+
+float acosh(float x)
+{
+       return log(x + sqrt(x*x - 1));
+}
+float asinh(float x)
+{
+       return log(x + sqrt(x*x + 1));
+}
+float atanh(float x)
+{
+       return 0.5 * log((1+x) / (1-x));
+}
+float cosh(float x)
+{
+       return 0.5 * (exp(x) + exp(-x));
+}
+float sinh(float x)
+{
+       return 0.5 * (exp(x) - exp(-x));
+}
+float tanh(float x)
+{
+       return sinh(x) / cosh(x);
+}
+
+float exp(float x)
+{
+       return pow(M_E, x);
+}
+float exp2(float x)
+{
+       return pow(2, x);
+}
+float expm1(float x)
+{
+       return exp(x) - 1;
+}
+
+vector frexp(float x)
+{
+       vector v;
+       v.z = 0;
+       v.y = ilogb(x) + 1;
+       v.x = x / exp2(v.y);
+       return v;
+}
+int ilogb(float x)
+{
+       return floor(log2(fabs(x)));
+}
+float ldexp(float x, int e)
+{
+       return x * pow(2, e);
+}
+float logn(float x, float base)
+{
+       return log(x) / log(base);
+}
+float log10(float x)
+{
+       return log(x) * M_LOG10E;
+}
+float log1p(float x)
+{
+       return log(x + 1);
+}
+float log2(float x)
+{
+       return log(x) * M_LOG2E;
+}
+float logb(float x)
+{
+       return floor(log2(fabs(x)));
+}
+vector modf(float f)
+{
+       return '1 0 0' * (f - trunc(f)) + '0 1 0' * trunc(f);
+}
+
+float scalbn(float x, int n)
+{
+       return x * pow(2, n);
+}
+
+float cbrt(float x)
+{
+       return copysign(pow(fabs(x), 1.0/3.0), x);
+}
+float hypot(float x, float y)
+{
+       return sqrt(x*x + y*y);
+}
+
+float erf(float x)
+{
+       // approximation taken from wikipedia
+       float y;
+       y = x*x;
+       return copysign(sqrt(1 - exp(-y * (1.273239544735163 + 0.14001228868667 * y) / (1 + 0.14001228868667 * y))), x);
+}
+float erfc(float x)
+{
+       return 1.0 - erf(x);
+}
+vector lgamma(float x)
+{
+       // TODO improve accuracy
+       if(!isfinite(x))
+               return fabs(x) * '1 0 0' + copysign(1, x) * '0 1 0';
+       if(x < 1 && x == floor(x))
+               return nan("gamma") * '1 1 1';
+       if(x < 0.1)
+       {
+               vector v;
+               v = lgamma(1.0 - x);
+               // reflection formula:
+               // gamma(1-z) * gamma(z) = pi / sin(pi*z)
+               // lgamma(1-z) + lgamma(z) = log(pi) - log(sin(pi*z))
+               // sign of gamma(1-z) = sign of gamma(z) * sign of sin(pi*z)
+               v.z = sin(M_PI * x);
+               v.x = log(M_PI) - log(fabs(v.z)) - v.x;
+               if(v.z < 0)
+                       v.y = -v.y;
+               v.z = 0;
+               return v;
+       }
+       if(x < 1.1)
+               return lgamma(x + 1) - log(x) * '1 0 0';
+       x -= 1;
+       return (0.5 * log(2 * M_PI * x) + x * (log(x) - 1)) * '1 0 0' + '0 1 0';
+}
+float tgamma(float x)
+{
+       vector v;
+       v = lgamma(x);
+       return exp(v.x) * v.y;
+}
+
+/**
+ * Pythonic mod:
+ * TODO: %% operator?
+ *
+ *  1 %  2 ==  1
+ * -1 %  2 ==  1
+ *  1 % -2 == -1
+ * -1 % -2 == -1
+ */
+float pymod(float x, float y)
+{
+       return x - y * floor(x / y);
+}
+
+float nearbyint(float x)
+{
+       return rint(x);
+}
+float trunc(float x)
+{
+       return (x>=0) ? floor(x) : ceil(x);
+}
+
+float fmod(float x, float y)
+{
+       return x - y * trunc(x / y);
+}
+float remainder(float x, float y)
+{
+       return x - y * rint(x / y);
+}
+vector remquo(float x, float y)
+{
+       vector v;
+       v.z = 0;
+       v.y = rint(x / y);
+       v.x = x - y * v.y;
+       return v;
+}
+
+float copysign(float x, float y)
+{
+       return fabs(x) * ((y>0) ? 1 : -1);
+}
+float nan(string tag)
+{
+       return sqrt(-1);
+}
+float nextafter(float x, float y)
+{
+       // TODO very crude
+       if(x == y)
+               return nan("nextafter");
+       if(x > y)
+               return -nextafter(-x, -y);
+       // now we know that x < y
+       // so we need the next number > x
+       float d, a, b;
+       d = max(fabs(x), 0.00000000000000000000001);
+       a = x + d;
+       do
+       {
+               d *= 0.5;
+               b = a;
+               a = x + d;
+       }
+       while(a != x);
+       return b;
+}
+float nexttoward(float x, float y)
+{
+       return nextafter(x, y);
+}
+
+float fdim(float x, float y)
+{
+       return max(x-y, 0);
+}
+float fmax(float x, float y)
+{
+       return max(x, y);
+}
+float fmin(float x, float y)
+{
+       return min(x, y);
+}
+float fma(float x, float y, float z)
+{
+       return x * y + z;
+}
+
+int isgreater(float x, float y)
+{
+       return x > y;
+}
+int isgreaterequal(float x, float y)
+{
+       return x >= y;
+}
+int isless(float x, float y)
+{
+       return x < y;
+}
+int islessequal(float x, float y)
+{
+       return x <= y;
+}
+int islessgreater(float x, float y)
+{
+       return x < y || x > y;
+}
+int isunordered(float x, float y)
+{
+       return !(x < y || x == y || x > y);
+}
+
+vector cross(vector a, vector b)
+{
+       return
+               '1 0 0' * (a.y * b.z - a.z * b.y)
+       +       '0 1 0' * (a.z * b.x - a.x * b.z)
+       +       '0 0 1' * (a.x * b.y - a.y * b.x);
+}
diff --git a/qcsrc/lib/warpzone/mathlib.qh b/qcsrc/lib/warpzone/mathlib.qh
new file mode 100644 (file)
index 0000000..9acece2
--- /dev/null
@@ -0,0 +1,121 @@
+#ifndef LIB_WARPZONE_MATHLIB_H
+#define LIB_WARPZONE_MATHLIB_H
+
+// <math.h>
+
+// The commented-out functions need no implementation because DarkPlaces offers
+// them as builtins. They are listed here anyway for completeness sake.
+
+const int FP_NAN = 0;
+const int FP_INFINITE = 1;
+const int FP_ZERO = 2;
+const int FP_SUBNORMAL = 3;
+const int FP_NORMAL = 4;
+int fpclassify(float x);
+bool isfinite(float x);
+bool isinf(float x);
+bool isnan(float x);
+bool isnormal(float x);
+bool signbit(float x);
+
+//float acos(float x);
+//float asin(float x);
+//float atan(float x);
+//float atan2(float y, float x);
+//float cos(float x);
+//float sin(float x);
+//float tan(float x);
+
+float acosh(float x);
+float asinh(float x);
+float atanh(float x);
+float cosh(float x);
+float sinh(float x);
+float tanh(float x);
+
+float exp(float x);
+float exp2(float x);
+float expm1(float x);
+
+vector frexp(float x); // returns mantissa as _x, exponent as _y
+int ilogb(float x);
+float ldexp(float x, int e);
+//float log(float x);
+float logn(float x, float base);
+float log10(float x);
+float log1p(float x);
+float log2(float x);
+float logb(float x);
+vector modf(float f); // fraction as _x, integer as _y
+
+float scalbn(float x, int n);
+
+float cbrt(float x);
+//float fabs(float x);
+float hypot(float x, float y);
+//float pow(float x, float y);
+//float sqrt(float x, float y);
+
+float erf(float x);
+float erfc(float x);
+vector lgamma(float x); // value in _x, sign in _y
+float tgamma(float x);
+
+/**
+ * Pythonic mod:
+ * TODO: %% operator?
+ *
+ *  1 %  2 ==  1
+ * -1 %  2 ==  1
+ *  1 % -2 == -1
+ * -1 % -2 == -1
+ */
+float pymod(float x, float y);
+
+//float ceil(float x);
+//float floor(float x);
+float nearbyint(float x);
+//float rint(float x);
+//float round(float x);
+float trunc(float x);
+
+float fmod(float x, float y);
+float remainder(float x, float y);
+vector remquo(float x, float y);
+
+float copysign(float x, float y);
+float nan(string tag);
+float nextafter(float x, float y);
+float nexttoward(float x, float y);
+
+float fdim(float x, float y);
+float fmax(float x, float y);
+float fmin(float x, float y);
+float fma(float x, float y, float z);
+
+int isgreater(float x, float y);
+int isgreaterequal(float x, float y);
+int isless(float x, float y);
+int islessequal(float x, float y);
+int islessgreater(float x, float y);
+int isunordered(float x, float y);
+
+const float M_E        = 2.7182818284590452354;   /* e */
+const float M_LOG2E    = 1.4426950408889634074;   /* log_2 e */
+const float M_LOG10E   = 0.43429448190325182765;  /* log_10 e */
+const float M_LN2      = 0.69314718055994530942;  /* log_e 2 */
+const float M_LN10     = 2.30258509299404568402;  /* log_e 10 */
+// -Wdouble-declaration
+#define M_PI             3.14159265358979323846   /* pi */
+const float M_PI_2     = 1.57079632679489661923;  /* pi/2 */
+const float M_PI_4     = 0.78539816339744830962;  /* pi/4 */
+const float M_1_PI     = 0.31830988618379067154;  /* 1/pi */
+const float M_2_PI     = 0.63661977236758134308;  /* 2/pi */
+const float M_2_SQRTPI = 1.12837916709551257390;  /* 2/sqrt(pi) */
+const float M_SQRT2    = 1.41421356237309504880;  /* sqrt(2) */
+const float M_SQRT1_2  = 0.70710678118654752440;  /* 1/sqrt(2) */
+
+// Non-<math.h> stuff follows here.
+vector cross(vector a, vector b);
+
+#endif
diff --git a/qcsrc/lib/warpzone/server.qc b/qcsrc/lib/warpzone/server.qc
new file mode 100644 (file)
index 0000000..e21e4ca
--- /dev/null
@@ -0,0 +1,899 @@
+#include "server.qh"
+
+#include "common.qh"
+#if defined(CSQC)
+#elif defined(MENUQC)
+#elif defined(SVQC)
+       #include "../../common/constants.qh"
+       #include "../../common/triggers/subs.qh"
+       #include "../../common/util.qh"
+       #include "../../server/command/common.qh"
+       #include "../../server/constants.qh"
+       #include "../../server/defs.qh"
+#endif
+
+#ifdef WARPZONELIB_KEEPDEBUG
+#define WARPZONELIB_REMOVEHACK
+#endif
+
+// for think function
+.vector warpzone_save_origin;
+.vector warpzone_save_angles;
+.vector warpzone_save_eorigin;
+.vector warpzone_save_eangles;
+
+// for all entities
+.vector warpzone_oldorigin, warpzone_oldvelocity, warpzone_oldangles;
+.float warpzone_teleport_time;
+.float warpzone_teleport_finishtime;
+.entity warpzone_teleport_zone;
+
+void WarpZone_StoreProjectileData(entity e)
+{
+       e.warpzone_oldorigin = e.origin;
+       e.warpzone_oldvelocity = e.velocity;
+       e.warpzone_oldangles = e.angles;
+}
+
+void WarpZone_TeleportPlayer(entity teleporter, entity player, vector to, vector to_angles, vector to_velocity)
+{
+       setorigin (player, to); // NOTE: this also aborts the move, when this is called by touch
+       player.oldorigin = to; // for DP's unsticking
+       player.angles = to_angles;
+       player.fixangle = true;
+       player.velocity = to_velocity;
+
+       BITXOR_ASSIGN(player.effects, EF_TELEPORT_BIT);
+
+       if(IS_PLAYER(player))
+               BITCLR_ASSIGN(player.flags, FL_ONGROUND);
+
+       WarpZone_PostTeleportPlayer_Callback(player);
+}
+
+bool WarpZone_Teleported_Send(entity to, int sf)
+{SELFPARAM();
+       WriteByte(MSG_ENTITY, ENT_CLIENT_WARPZONE_TELEPORTED);
+       WriteCoord(MSG_ENTITY, self.angles.x);
+       WriteCoord(MSG_ENTITY, self.angles.y);
+       WriteCoord(MSG_ENTITY, self.angles.z);
+       return true;
+}
+
+float WarpZone_Teleport(entity wz, entity player, float f0, float f1)
+{
+       vector o0, a0, v0, o1, a1, v1, o10;
+
+       o0 = player.origin + player.view_ofs;
+       v0 = player.velocity;
+       a0 = player.angles;
+
+       o10 = o1 = WarpZone_TransformOrigin(wz, o0);
+       v1 = WarpZone_TransformVelocity(wz, v0);
+       if (!IS_NOT_A_CLIENT(player))
+               a1 = WarpZone_TransformVAngles(wz, player.v_angle);
+       else
+               a1 = WarpZone_TransformAngles(wz, a0);
+
+       if(f0 != 0 || f1 != 0)
+       {
+               // retry last move but behind the warpzone!
+               // we must first go back as far as we can, then forward again, to not cause double touch events!
+
+               tracebox(o1 - player.view_ofs + v1 * frametime * f1, player.mins, player.maxs, o1 - player.view_ofs + v1 * frametime * f0, MOVE_WORLDONLY, player);
+               {
+                       entity own;
+                       own = player.owner;
+                       player.owner = world;
+                       tracebox(trace_endpos, player.mins, player.maxs, o1 - player.view_ofs + v1 * frametime * f1, MOVE_NORMAL, player); // this should get us through the warpzone
+                       player.owner = own;
+               }
+               o1 = trace_endpos + player.view_ofs;
+
+               float d, dv, md;
+               md = max(vlen(player.mins), vlen(player.maxs));
+               d = WarpZone_TargetPlaneDist(wz, o1);
+               dv = WarpZone_TargetPlaneDist(wz, v1);
+               if(d < 0)
+                       o1 = o1 - v1 * (d / dv);
+       }
+
+       // put him out of solid
+       tracebox(o1 - player.view_ofs, player.mins, player.maxs, o1 - player.view_ofs, MOVE_NOMONSTERS, player);
+       if(trace_startsolid)
+       {
+               setorigin(player, o1 - player.view_ofs);
+               if(WarpZoneLib_MoveOutOfSolid(player))
+               {
+                       o1 = player.origin + player.view_ofs;
+                       setorigin(player, o0 - player.view_ofs);
+               }
+               else
+               {
+                       LOG_INFO("would have to put player in solid, won't do that\n");
+                       setorigin(player, o0 - player.view_ofs);
+                       return 0;
+               }
+       }
+
+       // do the teleport
+       WarpZone_RefSys_Add(player, wz);
+       WarpZone_TeleportPlayer(wz, player, o1 - player.view_ofs, a1, v1);
+       WarpZone_StoreProjectileData(player);
+       player.warpzone_teleport_time = time;
+       player.warpzone_teleport_finishtime = time;
+       player.warpzone_teleport_zone = wz;
+
+       // prevent further teleports back
+       float dt = (o1 - o10) * v1 * (1 / (v1 * v1));
+       if(dt < sys_frametime)
+               player.warpzone_teleport_finishtime += sys_frametime - dt;
+
+#ifndef WARPZONE_USE_FIXANGLE
+       if(IS_VEHICLE(player) && player.owner)
+               player = player.owner; // hax
+       if(IS_PLAYER(player))
+       {
+               // instead of fixangle, send the transform to the client for smoother operation
+               player.fixangle = false;
+
+               entity ts = spawn();
+               setmodel(ts, MDL_Null);
+               ts.SendEntity = WarpZone_Teleported_Send;
+               ts.SendFlags = 0xFFFFFF;
+               ts.drawonlytoclient = player;
+               ts.think = SUB_Remove;
+               ts.nextthink = time + 1;
+               ts.owner = player;
+               ts.enemy = wz;
+               ts.effects = EF_NODEPTHTEST;
+               ts.classname = "warpzone_teleported";
+               ts.angles = wz.warpzone_transform;
+       }
+#endif
+
+       return 1;
+}
+
+void WarpZone_Touch (void)
+{SELFPARAM();
+       if(other.classname == "trigger_warpzone")
+               return;
+
+       if(time <= other.warpzone_teleport_finishtime) // already teleported this frame
+               return;
+
+       // FIXME needs a better check to know what is safe to teleport and what not
+       if(other.movetype == MOVETYPE_NONE || other.movetype == MOVETYPE_FOLLOW || other.tag_entity)
+               return;
+
+       if(WarpZoneLib_ExactTrigger_Touch())
+               return;
+
+       if(WarpZone_PlaneDist(self, other.origin + other.view_ofs) >= 0) // wrong side of the trigger_warpzone (don't teleport yet)
+               return;
+
+       float f;
+       // number of frames we need to go back:
+       //   dist = 16*sqrt(2) qu
+       //   dist ~ 24 qu
+       //   24 qu = v*t
+       //   24 qu = v*frametime*n
+       //       n = 24 qu/(v*frametime)
+       // for clients go only one frame though, may be too irritating otherwise
+       // but max 0.25 sec = 0.25/frametime frames
+       //       24/(0.25/frametime)
+       //       96*frametime
+       float d;
+       d = 24 + max(vlen(other.mins), vlen(other.maxs));
+       if(IS_NOT_A_CLIENT(other))
+               f = -d / bound(frametime * d * 1, frametime * vlen(other.velocity), d);
+       else
+               f = -1;
+       if(WarpZone_Teleport(self, other, f, 0))
+       {
+               string save1, save2;
+               activator = other;
+
+               save1 = self.target; self.target = string_null;
+               save2 = self.target3; self.target3 = string_null;
+               SUB_UseTargets();
+               if (!self.target) self.target = save1;
+               if (!self.target3) self.target3 = save2;
+
+               setself(self.enemy);
+               save1 = self.target; self.target = string_null;
+               save2 = self.target2; self.target2 = string_null;
+               SUB_UseTargets();
+               if (!self.target) self.target = save1;
+               if (!self.target2) self.target2 = save2;
+               setself(this);
+       }
+       else
+       {
+               LOG_TRACE("WARPZONE FAIL AHAHAHAHAH))\n");
+       }
+}
+
+bool WarpZone_Send(entity to, int sendflags)
+{SELFPARAM();
+       WriteByte(MSG_ENTITY, ENT_CLIENT_WARPZONE);
+
+       // we must send this flag for clientside to match properly too
+       int f = 0;
+       if(self.warpzone_isboxy)
+               BITSET_ASSIGN(f, 1);
+       if(self.warpzone_fadestart)
+               BITSET_ASSIGN(f, 2);
+       if(self.origin != '0 0 0')
+               BITSET_ASSIGN(f, 4);
+       WriteByte(MSG_ENTITY, f);
+
+       // we need THESE to render the warpzone (and cull properly)...
+       if(f & 4)
+       {
+               WriteCoord(MSG_ENTITY, self.origin.x);
+               WriteCoord(MSG_ENTITY, self.origin.y);
+               WriteCoord(MSG_ENTITY, self.origin.z);
+       }
+
+       WriteShort(MSG_ENTITY, self.modelindex);
+       WriteCoord(MSG_ENTITY, self.mins.x);
+       WriteCoord(MSG_ENTITY, self.mins.y);
+       WriteCoord(MSG_ENTITY, self.mins.z);
+       WriteCoord(MSG_ENTITY, self.maxs.x);
+       WriteCoord(MSG_ENTITY, self.maxs.y);
+       WriteCoord(MSG_ENTITY, self.maxs.z);
+       WriteByte(MSG_ENTITY, bound(1, self.scale * 16, 255));
+
+       // we need THESE to calculate the proper transform
+       WriteCoord(MSG_ENTITY, self.warpzone_origin.x);
+       WriteCoord(MSG_ENTITY, self.warpzone_origin.y);
+       WriteCoord(MSG_ENTITY, self.warpzone_origin.z);
+       WriteCoord(MSG_ENTITY, self.warpzone_angles.x);
+       WriteCoord(MSG_ENTITY, self.warpzone_angles.y);
+       WriteCoord(MSG_ENTITY, self.warpzone_angles.z);
+       WriteCoord(MSG_ENTITY, self.warpzone_targetorigin.x);
+       WriteCoord(MSG_ENTITY, self.warpzone_targetorigin.y);
+       WriteCoord(MSG_ENTITY, self.warpzone_targetorigin.z);
+       WriteCoord(MSG_ENTITY, self.warpzone_targetangles.x);
+       WriteCoord(MSG_ENTITY, self.warpzone_targetangles.y);
+       WriteCoord(MSG_ENTITY, self.warpzone_targetangles.z);
+
+       if(f & 2)
+       {
+               WriteShort(MSG_ENTITY, self.warpzone_fadestart);
+               WriteShort(MSG_ENTITY, self.warpzone_fadeend);
+       }
+
+       return true;
+}
+
+bool WarpZone_Camera_Send(entity to, int sendflags)
+{SELFPARAM();
+       int f = 0;
+       WriteByte(MSG_ENTITY, ENT_CLIENT_WARPZONE_CAMERA);
+
+       if(self.warpzone_fadestart)
+               BITSET_ASSIGN(f, 2);
+       if(self.origin != '0 0 0')
+               BITSET_ASSIGN(f, 4);
+       WriteByte(MSG_ENTITY, f);
+
+       // we need THESE to render the warpzone (and cull properly)...
+       if(f & 4)
+       {
+               WriteCoord(MSG_ENTITY, self.origin.x);
+               WriteCoord(MSG_ENTITY, self.origin.y);
+               WriteCoord(MSG_ENTITY, self.origin.z);
+       }
+
+       WriteShort(MSG_ENTITY, self.modelindex);
+       WriteCoord(MSG_ENTITY, self.mins.x);
+       WriteCoord(MSG_ENTITY, self.mins.y);
+       WriteCoord(MSG_ENTITY, self.mins.z);
+       WriteCoord(MSG_ENTITY, self.maxs.x);
+       WriteCoord(MSG_ENTITY, self.maxs.y);
+       WriteCoord(MSG_ENTITY, self.maxs.z);
+       WriteByte(MSG_ENTITY, bound(1, self.scale * 16, 255));
+
+       // we need THESE to calculate the proper transform
+       WriteCoord(MSG_ENTITY, self.enemy.origin.x);
+       WriteCoord(MSG_ENTITY, self.enemy.origin.y);
+       WriteCoord(MSG_ENTITY, self.enemy.origin.z);
+       WriteCoord(MSG_ENTITY, self.enemy.angles.x);
+       WriteCoord(MSG_ENTITY, self.enemy.angles.y);
+       WriteCoord(MSG_ENTITY, self.enemy.angles.z);
+
+       if(f & 2)
+       {
+               WriteShort(MSG_ENTITY, self.warpzone_fadestart);
+               WriteShort(MSG_ENTITY, self.warpzone_fadeend);
+       }
+
+       return true;
+}
+
+#ifdef WARPZONELIB_KEEPDEBUG
+float WarpZone_CheckProjectileImpact(entity player)
+{SELFPARAM();
+       vector o0, v0;
+
+       o0 = player.origin + player.view_ofs;
+       v0 = player.velocity;
+
+       // if we teleported shortly before, abort
+       if(time <= player.warpzone_teleport_finishtime + 0.1)
+               return 0;
+
+       // if player hit a warpzone, abort
+       entity wz;
+       wz = WarpZone_Find(o0 + player.mins, o0 + player.maxs);
+       if(!wz)
+               return 0;
+
+#ifdef WARPZONELIB_REMOVEHACK
+       LOG_INFO("impactfilter found something - and it no longer gets handled correctly - please tell divVerent whether anything behaves broken now\n");
+#else
+       LOG_INFO("impactfilter found something - and it even gets handled correctly - please tell divVerent that this code apparently gets triggered again\n");
+#endif
+       LOG_INFO("Entity type: ", player.classname, "\n");
+       LOG_INFO("Origin: ", vtos(player.origin), "\n");
+       LOG_INFO("Velocity: ", vtos(player.velocity), "\n");
+
+#ifdef WARPZONELIB_REMOVEHACK
+       return 0;
+#else
+       // retry previous move
+       setorigin(player, player.warpzone_oldorigin);
+       player.velocity = player.warpzone_oldvelocity;
+       if(WarpZone_Teleport(wz, player, 0, 1))
+       {
+               entity oldself;
+               string save1, save2;
+
+               oldself = self;
+               self = wz;
+               other = player;
+               activator = player;
+
+               save1 = self.target; self.target = string_null;
+               save2 = self.target3; self.target3 = string_null;
+               SUB_UseTargets();
+               if (!self.target) self.target = save1;
+               if (!self.target3) self.target3 = save2;
+
+               self = self.enemy;
+               save1 = self.target; self.target = string_null;
+               save2 = self.target2; self.target2 = string_null;
+               SUB_UseTargets();
+               if (!self.target) self.target = save1;
+               if (!self.target2) self.target2 = save2;
+               self = oldself;
+       }
+       else
+       {
+               setorigin(player, o0 - player.view_ofs);
+               player.velocity = v0;
+       }
+
+       return +1;
+#endif
+}
+#endif
+
+float WarpZone_Projectile_Touch()
+{SELFPARAM();
+       if(other.classname == "trigger_warpzone")
+               return true;
+
+       // no further impacts if we teleported this frame!
+       // this is because even if we did teleport, the engine still may raise
+       // touch events for the previous location
+       // engine now aborts moves on teleport, so this SHOULD not happen any more
+       // but if this is called from TouchAreaGrid of the projectile moving,
+       // then this won't do
+       if(time == self.warpzone_teleport_time)
+               return true;
+
+#ifdef WARPZONELIB_KEEPDEBUG
+       // this SEEMS to not happen at the moment, but if it did, it would be more reliable
+       {
+               float save_dpstartcontents;
+               float save_dphitcontents;
+               float save_dphitq3surfaceflags;
+               string save_dphittexturename;
+               float save_allsolid;
+               float save_startsolid;
+               float save_fraction;
+               vector save_endpos;
+               vector save_plane_normal;
+               float save_plane_dist;
+               entity save_ent;
+               float save_inopen;
+               float save_inwater;
+               save_dpstartcontents = trace_dpstartcontents;
+               save_dphitcontents = trace_dphitcontents;
+               save_dphitq3surfaceflags = trace_dphitq3surfaceflags;
+               save_dphittexturename = trace_dphittexturename;
+               save_allsolid = trace_allsolid;
+               save_startsolid = trace_startsolid;
+               save_fraction = trace_fraction;
+               save_endpos = trace_endpos;
+               save_plane_normal = trace_plane_normal;
+               save_plane_dist = trace_plane_dist;
+               save_ent = trace_ent;
+               save_inopen = trace_inopen;
+               save_inwater = trace_inwater;
+               float f;
+               if((f = WarpZone_CheckProjectileImpact(self)) != 0)
+                       return (f > 0);
+               trace_dpstartcontents = save_dpstartcontents;
+               trace_dphitcontents = save_dphitcontents;
+               trace_dphitq3surfaceflags = save_dphitq3surfaceflags;
+               trace_dphittexturename = save_dphittexturename;
+               trace_allsolid = save_allsolid;
+               trace_startsolid = save_startsolid;
+               trace_fraction = save_fraction;
+               trace_endpos = save_endpos;
+               trace_plane_normal = save_plane_normal;
+               trace_plane_dist = save_plane_dist;
+               trace_ent = save_ent;
+               trace_inopen = save_inopen;
+               trace_inwater = save_inwater;
+       }
+#endif
+
+       if(WarpZone_Projectile_Touch_ImpactFilter_Callback())
+               return true;
+
+       return false;
+}
+
+void WarpZone_InitStep_FindOriginTarget()
+{SELFPARAM();
+       if(self.killtarget != "")
+       {
+               self.aiment = find(world, targetname, self.killtarget);
+               if(self.aiment == world)
+               {
+                       error("Warp zone with nonexisting killtarget");
+                       return;
+               }
+               self.killtarget = string_null;
+       }
+}
+
+void WarpZonePosition_InitStep_FindTarget()
+{SELFPARAM();
+       if(self.target == "")
+       {
+               error("Warp zone position with no target");
+               return;
+       }
+       self.enemy = find(world, targetname, self.target);
+       if(self.enemy == world)
+       {
+               error("Warp zone position with nonexisting target");
+               return;
+       }
+       if(self.enemy.aiment)
+       {
+               // already is positioned
+               error("Warp zone position targeting already oriented warpzone");
+               return;
+       }
+       self.enemy.aiment = self;
+}
+
+void WarpZoneCamera_Think(void)
+{SELFPARAM();
+       if(self.warpzone_save_origin != self.origin
+       || self.warpzone_save_angles != self.angles
+       || self.warpzone_save_eorigin != self.enemy.origin
+       || self.warpzone_save_eangles != self.enemy.angles)
+       {
+               WarpZone_Camera_SetUp(self, self.enemy.origin, self.enemy.angles);
+               self.warpzone_save_origin = self.origin;
+               self.warpzone_save_angles = self.angles;
+               self.warpzone_save_eorigin = self.enemy.origin;
+               self.warpzone_save_eangles = self.enemy.angles;
+       }
+       self.nextthink = time;
+}
+
+void WarpZoneCamera_InitStep_FindTarget()
+{SELFPARAM();
+       entity e;
+       float i;
+       if(self.target == "")
+       {
+               error("Camera with no target");
+               return;
+       }
+       self.enemy = world;
+       for(e = world, i = 0; (e = find(e, targetname, self.target)); )
+               if(random() * ++i < 1)
+                       self.enemy = e;
+       if(self.enemy == world)
+       {
+               error("Camera with nonexisting target");
+               return;
+       }
+       warpzone_cameras_exist = 1;
+       WarpZone_Camera_SetUp(self, self.enemy.origin, self.enemy.angles);
+       self.SendFlags = 0xFFFFFF;
+       if(self.spawnflags & 1)
+       {
+               self.think = WarpZoneCamera_Think;
+               self.nextthink = time;
+       }
+       else
+               self.nextthink = 0;
+}
+
+void WarpZone_InitStep_UpdateTransform()
+{SELFPARAM();
+       vector org, ang, norm, point;
+       float area;
+       vector tri, a, b, c, n;
+       float i_s, i_t, n_t;
+       string tex;
+
+       org = self.origin;
+       if(org == '0 0 0')
+               org = 0.5 * (self.mins + self.maxs);
+
+       norm = point = '0 0 0';
+       area = 0;
+       for(i_s = 0; ; ++i_s)
+       {
+               tex = getsurfacetexture(self, i_s);
+               if (!tex)
+                       break; // this is beyond the last one
+               if(tex == "textures/common/trigger" || tex == "trigger")
+                       continue;
+               n_t = getsurfacenumtriangles(self, i_s);
+               for(i_t = 0; i_t < n_t; ++i_t)
+               {
+                       tri = getsurfacetriangle(self, i_s, i_t);
+                       a = getsurfacepoint(self, i_s, tri.x);
+                       b = getsurfacepoint(self, i_s, tri.y);
+                       c = getsurfacepoint(self, i_s, tri.z);
+                       n = cross(c - a, b - a);
+                       area = area + vlen(n);
+                       norm = norm + n;
+                       point = point + vlen(n) * (a + b + c);
+               }
+       }
+       if(area > 0)
+       {
+               norm = norm * (1 / area);
+               point = point * (1 / (3 * area));
+               if(vlen(norm) < 0.99)
+               {
+                       LOG_INFO("trigger_warpzone near ", vtos(self.aiment.origin), " is nonplanar. BEWARE.\n");
+                       area = 0; // no autofixing in this case
+               }
+               norm = normalize(norm);
+       }
+
+       ang = '0 0 0';
+       if(self.aiment)
+       {
+               org = self.aiment.origin;
+               ang = self.aiment.angles;
+               if(area > 0)
+               {
+                       org = org - ((org - point) * norm) * norm; // project to plane
+                       makevectors(ang);
+                       if(norm * v_forward < 0)
+                       {
+                               LOG_INFO("Position target of trigger_warpzone near ", vtos(self.aiment.origin), " points into trigger_warpzone. BEWARE.\n");
+                               norm = -1 * norm;
+                       }
+                       ang = vectoangles2(norm, v_up); // keep rotation, but turn exactly against plane
+                       ang.x = -ang.x;
+                       if(norm * v_forward < 0.99)
+                               LOG_INFO("trigger_warpzone near ", vtos(self.aiment.origin), " has been turned to match plane orientation (", vtos(self.aiment.angles), " -> ", vtos(ang), "\n");
+                       if(vlen(org - self.aiment.origin) > 0.5)
+                               LOG_INFO("trigger_warpzone near ", vtos(self.aiment.origin), " has been moved to match the plane (", vtos(self.aiment.origin), " -> ", vtos(org), ").\n");
+               }
+       }
+       else if(area > 0)
+       {
+               org = point;
+               ang = vectoangles(norm);
+               ang.x = -ang.x;
+       }
+       else
+               error("cannot infer origin/angles for this warpzone, please use a killtarget or a trigger_warpzone_position");
+
+       self.warpzone_origin = org;
+       self.warpzone_angles = ang;
+}
+
+void WarpZone_InitStep_ClearTarget()
+{SELFPARAM();
+       if(self.enemy)
+               self.enemy.enemy = world;
+       self.enemy = world;
+}
+
+entity warpzone_first; .entity warpzone_next;
+void WarpZone_InitStep_FindTarget()
+{SELFPARAM();
+       float i;
+       entity e, e2;
+
+       if(self.enemy)
+               return;
+
+       // this way only one of the two ents needs to target
+       if(self.target != "")
+       {
+               self.enemy = self; // so the if(!e.enemy) check also skips self, saves one IF
+
+               e2 = world;
+               for(e = world, i = 0; (e = find(e, targetname, self.target)); )
+                       if(!e.enemy)
+                               if(e.classname == self.classname) // possibly non-warpzones may use the same targetname!
+                                       if(random() * ++i < 1)
+                                               e2 = e;
+               if(!e2)
+               {
+                       self.enemy = world;
+                       error("Warpzone with non-existing target");
+                       return;
+               }
+               self.enemy = e2;
+               e2.enemy = self;
+       }
+}
+
+void WarpZone_Think();
+void WarpZone_InitStep_FinalizeTransform()
+{SELFPARAM();
+       if(!self.enemy || self.enemy.enemy != self)
+       {
+               error("Invalid warp zone detected. Killed.");
+               return;
+       }
+
+       warpzone_warpzones_exist = 1;
+       WarpZone_SetUp(self, self.warpzone_origin, self.warpzone_angles, self.enemy.warpzone_origin, self.enemy.warpzone_angles);
+       self.touch = WarpZone_Touch;
+       self.SendFlags = 0xFFFFFF;
+       if(self.spawnflags & 1)
+       {
+               self.think = WarpZone_Think;
+               self.nextthink = time;
+       }
+       else
+               self.nextthink = 0;
+}
+
+float warpzone_initialized;
+//entity warpzone_first;
+entity warpzone_position_first;
+entity warpzone_camera_first;
+.entity warpzone_next;
+spawnfunc(misc_warpzone_position)
+{
+       // "target", "angles", "origin"
+       self.warpzone_next = warpzone_position_first;
+       warpzone_position_first = self;
+}
+spawnfunc(trigger_warpzone_position)
+{
+       spawnfunc_misc_warpzone_position(this);
+}
+spawnfunc(trigger_warpzone)
+{
+       // warp zone entities must have:
+       // "killtarget" pointing to a target_position with a direction arrow
+       //              that points AWAY from the warp zone, and that is inside
+       //              the warp zone trigger
+       // "target"     pointing to an identical warp zone at another place in
+       //              the map, with another killtarget to designate its
+       //              orientation
+
+       if(!self.scale)
+               self.scale = self.modelscale;
+       if(!self.scale)
+               self.scale = 1;
+       string m;
+       m = self.model;
+       WarpZoneLib_ExactTrigger_Init();
+       if(m != "")
+       {
+               precache_model(m);
+               _setmodel(self, m); // no precision needed
+       }
+       setorigin(self, self.origin);
+       if(self.scale)
+               setsize(self, self.mins * self.scale, self.maxs * self.scale);
+       else
+               setsize(self, self.mins, self.maxs);
+       self.SendEntity = WarpZone_Send;
+       self.SendFlags = 0xFFFFFF;
+       BITSET_ASSIGN(self.effects, EF_NODEPTHTEST);
+       self.warpzone_next = warpzone_first;
+       warpzone_first = self;
+}
+spawnfunc(func_camera)
+{
+       if(!self.scale)
+               self.scale = self.modelscale;
+       if(!self.scale)
+               self.scale = 1;
+       if(self.model != "")
+       {
+               precache_model(self.model);
+               _setmodel(self, self.model); // no precision needed
+       }
+       setorigin(self, self.origin);
+       if(self.scale)
+               setsize(self, self.mins * self.scale, self.maxs * self.scale);
+       else
+               setsize(self, self.mins, self.maxs);
+       if(!self.solid)
+               self.solid = SOLID_BSP;
+       else if(self.solid < 0)
+               self.solid = SOLID_NOT;
+       self.SendEntity = WarpZone_Camera_Send;
+       self.SendFlags = 0xFFFFFF;
+       self.warpzone_next = warpzone_camera_first;
+       warpzone_camera_first = self;
+}
+void WarpZones_Reconnect()
+{SELFPARAM();
+       for(setself(warpzone_first); self; setself(self.warpzone_next))
+               WarpZone_InitStep_ClearTarget();
+       for(setself(warpzone_first); self; setself(self.warpzone_next))
+               WarpZone_InitStep_FindTarget();
+       for(setself(warpzone_camera_first); self; setself(self.warpzone_next))
+               WarpZoneCamera_InitStep_FindTarget();
+       for(setself(warpzone_first); self; setself(self.warpzone_next))
+               WarpZone_InitStep_FinalizeTransform();
+       setself(this);
+}
+
+void WarpZone_Think()
+{SELFPARAM();
+       if(self.warpzone_save_origin != self.origin
+       || self.warpzone_save_angles != self.angles
+       || self.warpzone_save_eorigin != self.enemy.origin
+       || self.warpzone_save_eangles != self.enemy.angles)
+       {
+               WarpZone_InitStep_UpdateTransform();
+               setself(self.enemy);
+               WarpZone_InitStep_UpdateTransform();
+               setself(this);
+               WarpZone_InitStep_FinalizeTransform();
+               setself(self.enemy);
+               WarpZone_InitStep_FinalizeTransform();
+               setself(this);
+               self.warpzone_save_origin = self.origin;
+               self.warpzone_save_angles = self.angles;
+               self.warpzone_save_eorigin = self.enemy.origin;
+               self.warpzone_save_eangles = self.enemy.angles;
+       }
+       self.nextthink = time;
+}
+
+void WarpZone_StartFrame()
+{SELFPARAM();
+       entity e;
+       if(warpzone_initialized == 0)
+       {
+               warpzone_initialized = 1;
+               for(setself(warpzone_first); self; setself(self.warpzone_next))
+                       WarpZone_InitStep_FindOriginTarget();
+               for(setself(warpzone_position_first); self; setself(self.warpzone_next))
+                       WarpZonePosition_InitStep_FindTarget();
+               for(setself(warpzone_first); self; setself(self.warpzone_next))
+                       WarpZone_InitStep_UpdateTransform();
+               setself(this);
+               WarpZones_Reconnect();
+               WarpZone_PostInitialize_Callback();
+       }
+
+       entity oldother;
+       oldother = other;
+       for(e = world; (e = nextent(e)); )
+       {
+               if(warpzone_warpzones_exist) { WarpZone_StoreProjectileData(e); }
+
+               if(IS_REAL_CLIENT(e))
+               {
+                       if(e.solid == SOLID_NOT) // not spectating?
+                       if(e.movetype == MOVETYPE_NOCLIP || e.movetype == MOVETYPE_FLY || e.movetype == MOVETYPE_FLY_WORLDONLY) // not spectating? (this is to catch observers)
+                       {
+                               other = e; // player
+
+                               // warpzones
+                               if(warpzone_warpzones_exist) {
+                               setself(WarpZone_Find(e.origin + e.mins, e.origin + e.maxs));
+                               if(self)
+                               if(!WarpZoneLib_ExactTrigger_Touch())
+                                       if(WarpZone_PlaneDist(self, e.origin + e.view_ofs) <= 0)
+                                               WarpZone_Teleport(self, e, -1, 0); } // NOT triggering targets by this!
+
+                               // teleporters
+                               setself(Teleport_Find(e.origin + e.mins, e.origin + e.maxs));
+                               if(self)
+                               if(!WarpZoneLib_ExactTrigger_Touch())
+                                       Simple_TeleportPlayer(self, other); // NOT triggering targets by this!
+                       }
+               }
+
+               if(IS_NOT_A_CLIENT(e))
+               {
+                       if(warpzone_warpzones_exist)
+                               for (; (e = nextent(e)); )
+                                       WarpZone_StoreProjectileData(e);
+                       break;
+               }
+       }
+       setself(this);
+       other = oldother;
+}
+
+.float warpzone_reconnecting;
+float visible_to_some_client(entity ent)
+{
+       entity e;
+       for(e = nextent(world); !IS_NOT_A_CLIENT(e); e = nextent(e))
+               if(IS_PLAYER(e) && IS_REAL_CLIENT(e))
+                       if(checkpvs(e.origin + e.view_ofs, ent))
+                               return 1;
+       return 0;
+}
+void trigger_warpzone_reconnect_use()
+{SELFPARAM();
+       entity e;
+       e = self;
+       // NOTE: this matches for target, not targetname, but of course
+       // targetname must be set too on the other entities
+       for(setself(warpzone_first); self; setself(self.warpzone_next))
+               self.warpzone_reconnecting = ((e.target == "" || self.target == e.target) && !((e.spawnflags & 1) && (visible_to_some_client(self) || visible_to_some_client(self.enemy))));
+       for(setself(warpzone_camera_first); self; setself(self.warpzone_next))
+               self.warpzone_reconnecting = ((e.target == "" || self.target == e.target) && !((e.spawnflags & 1) && visible_to_some_client(self)));
+       for(setself(warpzone_first); self; setself(self.warpzone_next))
+               if(self.warpzone_reconnecting)
+                       WarpZone_InitStep_ClearTarget();
+       for(setself(warpzone_first); self; setself(self.warpzone_next))
+               if(self.warpzone_reconnecting)
+                       WarpZone_InitStep_FindTarget();
+       for(setself(warpzone_camera_first); self; setself(self.warpzone_next))
+               if(self.warpzone_reconnecting)
+                       WarpZoneCamera_InitStep_FindTarget();
+       for(setself(warpzone_first); self; setself(self.warpzone_next))
+               if(self.warpzone_reconnecting || self.enemy.warpzone_reconnecting)
+                       WarpZone_InitStep_FinalizeTransform();
+       setself(e);
+}
+
+spawnfunc(trigger_warpzone_reconnect)
+{
+       self.use = trigger_warpzone_reconnect_use;
+}
+
+spawnfunc(target_warpzone_reconnect)
+{
+       spawnfunc_trigger_warpzone_reconnect(this); // both names make sense here :(
+}
+
+void WarpZone_PlayerPhysics_FixVAngle(void)
+{SELFPARAM();
+#ifndef WARPZONE_DONT_FIX_VANGLE
+       if(IS_REAL_CLIENT(self))
+       if(self.v_angle.z <= 360) // if not already adjusted
+       if(time - self.ping * 0.001 < self.warpzone_teleport_time)
+       {
+               self.v_angle = WarpZone_TransformVAngles(self.warpzone_teleport_zone, self.v_angle);
+               self.v_angle_z += 720; // mark as adjusted
+       }
+#endif
+}
diff --git a/qcsrc/lib/warpzone/server.qh b/qcsrc/lib/warpzone/server.qh
new file mode 100644 (file)
index 0000000..943f032
--- /dev/null
@@ -0,0 +1,18 @@
+#ifndef LIB_WARPZONE_SERVER_H
+#define LIB_WARPZONE_SERVER_H
+
+void WarpZone_StartFrame();
+float WarpZone_Projectile_Touch();
+
+// THESE must be defined by calling QC code:
+void WarpZone_PostTeleportPlayer_Callback(entity pl);
+float WarpZone_Projectile_Touch_ImpactFilter_Callback();
+
+// server must also define a float called ENT_CLIENT_WARPZONE for the initial byte of WarpZone entities
+//const float ENT_CLIENT_WARPZONE;
+//const float ENT_CLIENT_WARPZONE_CAMERA;
+
+void WarpZone_PlayerPhysics_FixVAngle(void);
+
+void WarpZone_PostInitialize_Callback(void);
+#endif
diff --git a/qcsrc/lib/warpzone/util_server.qc b/qcsrc/lib/warpzone/util_server.qc
new file mode 100644 (file)
index 0000000..742ec3e
--- /dev/null
@@ -0,0 +1,49 @@
+#include "util_server.qh"
+
+#include "common.qh"
+
+#if defined(CSQC)
+#elif defined(MENUQC)
+#elif defined(SVQC)
+    #include "../csqcmodel/sv_model.qh"
+#endif
+#include "common.qh"
+
+void WarpZoneLib_ExactTrigger_Init()
+{SELFPARAM();
+       vector mi, ma;
+       if (self.movedir == '0 0 0')
+       if (self.angles != '0 0 0')
+       {
+               makevectors (self.angles);
+               self.movedir = v_forward;
+       }
+       if(self.model == "")
+       {
+               // It's a box! No need to match with exacttriggers.
+               self.warpzone_isboxy = 1;
+       }
+       else
+       {
+               mi = self.mins;
+               ma = self.maxs;
+               precache_model(self.model);
+               _setmodel(self, self.model);
+               // let mapper-set mins/maxs override the model's bounds if set
+               if(mi != '0 0 0' || ma != '0 0 0')
+               {
+                       // It's a box! No need to match with exacttriggers.
+                       self.mins = mi;
+                       self.maxs = ma;
+                       self.warpzone_isboxy = 1;
+               }
+       }
+       setorigin(self, self.origin);
+       if(self.scale)
+               setsize(self, self.mins * self.scale, self.maxs * self.scale);
+       else
+               setsize(self, self.mins, self.maxs);
+       self.movetype = MOVETYPE_NONE;
+       self.solid = SOLID_TRIGGER;
+       self.model = "";
+}
diff --git a/qcsrc/lib/warpzone/util_server.qh b/qcsrc/lib/warpzone/util_server.qh
new file mode 100644 (file)
index 0000000..75df5d8
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef LIB_WARPZONE_UTIL_SERVER_H
+#define LIB_WARPZONE_UTIL_SERVER_H
+
+float WarpZoneLib_MoveOutOfSolid(entity e);
+float WarpZoneLib_ExactTrigger_Touch();
+#ifdef SVQC
+void WarpZoneLib_ExactTrigger_Init();
+#endif
+#endif
index a6903ae3dc48dc3f293eef0327d89772455b9e68..0c4f926dd95c7bf76107bd2eeb972c7a17230788 100644 (file)
@@ -1,7 +1,7 @@
-#ifndef CLIENT_ALL_H
-#define CLIENT_ALL_H
+#ifndef MENU_ALL_H
+#define MENU_ALL_H
 
-#include "../dpdefs/menudefs.qh"
-#include "../dpdefs/keycodes.qh"
+#include "draw.qh"
+#include "xonotic/util.qh"
 
 #endif
index 5563b969d98bfb4751e29e661b2c97a6c5248c45..d24220fefae0ab9fe4695d8287fcc21c1a2a7bcd 100644 (file)
@@ -1,6 +1,5 @@
 #ifndef ANIM_ANIMATION_H
 #define ANIM_ANIMATION_H
-#include "../oo/base.qh"
 void setterDummy(entity, float);
 CLASS(Animation, Object)
        METHOD(Animation, configureAnimation, void(entity, entity, void(entity, float), float, float, float, float));
index 4489de3d5a4f6b0e04fac1038097f33631289fbe..55ca901dc50f83378c2697df3010f2cb4d4f75fc 100644 (file)
@@ -2,7 +2,6 @@
 
 #ifndef ANIM_ANIMHOST_H
 #define ANIM_ANIMHOST_H
-#include "../oo/base.qh"
 CLASS(AnimHost, Object)
        METHOD(AnimHost, addAnim, void(entity, entity));
        METHOD(AnimHost, removeAnim, void(entity, entity));
index 8b12a7b7ddbe6289b0f722ed661ab468a954a9ea..179dc1949bad8c371ab1c0c2c901d6b6befbbb20 100644 (file)
@@ -81,7 +81,7 @@ void GameCommand(string theCommand)
                        entity e;
                        string s;
 
-                       for(i = 0, e = world; (e = nextent(e)); )
+                       for(i = 0, e = NULL; (e = nextent(e)); )
                                if(e.classname != "vtbl" && e.name != "")
                                {
                                        s = e.name;
index 7c7dc70db94987fd0a9ec17da3cffec0f9333713..cf0916ce9c6168cba438831b1a2bbc2641e564d1 100644 (file)
@@ -2,6 +2,8 @@
 #ifndef GAMESETTINGS_H
 #define GAMESETTINGS_H
 
+#include "xonotic/tab.qc"
+
 REGISTRY(Settings, BIT(3))
 REGISTER_REGISTRY(RegisterSettings)
 #define REGISTER_SETTINGS(id, impl) \
index 8788f2e84d7ec81bb766d332e0f495b843b25132..fa6161a9779337d7587799b4d99f54693a6f0944 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef ITEM_H
 #define ITEM_H
 #include "skin.qh"
-#include "oo/base.qh"
 CLASS(Item, Object)
        METHOD(Item, draw, void(entity));
        METHOD(Item, keyDown, float(entity, float, float, float));
index 8232125f750b69d7d3689e54eada9f7c830d7fdc..046d8e1942a18f72f80e3f935a396baa0cdb2264 100644 (file)
@@ -147,7 +147,7 @@ void ModalController_draw(entity me)
        vector fs;
        animating = 0;
 
-       front = world;
+       front = NULL;
        for(e = me.firstChild; e; e = e.nextSibling)
                if(e.ModalController_state)
                {
index 3340e335cb9aebe22d7b305022a52074cd84f123..3bde6565a6b6f16d1b436336479d5e32a091d510 100644 (file)
@@ -26,7 +26,7 @@ CLASS(Slider, Label)
        ATTRIB(Slider, value, float, 0)
        ATTRIB(Slider, animated, float, 1)
        ATTRIB(Slider, sliderValue, float, 0)
-       ATTRIB(Slider, sliderAnim, entity, world)
+       ATTRIB(Slider, sliderAnim, entity, NULL)
        ATTRIB(Slider, valueMin, float, 0)
        ATTRIB(Slider, valueMax, float, 0)
        ATTRIB(Slider, valueStep, float, 0)
@@ -311,7 +311,7 @@ void Slider_draw(entity me)
        if(me.sliderAnim.isFinished(me.sliderAnim))
        {
                anim.removeObjAnim(anim, me);
-               me.sliderAnim = world;
+               me.sliderAnim = NULL;
        }
 
        me.setText(me, me.valueToText(me, me.value));
index 3f6632f4e4663f2f57ab6c16d8088bdd311c80d3..fde2c3c1eb7594125c82cb2cac15eb99ae68284d 100644 (file)
@@ -478,7 +478,7 @@ entity m_findtooltipitem(entity root, vector pos)
        entity it;
        entity best;
 
-       best = world;
+       best = NULL;
        it = root;
 
        while(it.instanceOfContainer)
@@ -495,7 +495,7 @@ entity m_findtooltipitem(entity root, vector pos)
                                best = it;
                        else if(menu_tooltips == 2 && (it.cvarName || it.onClickCommand))
                                best = it;
-                       it = world;
+                       it = NULL;
                }
                else if(it.instanceOfModalController)
                        it = it.focusedChild;
@@ -545,9 +545,9 @@ void m_tooltip(vector pos)
        if (!menu_tooltips)
        {
                // don't return immediately, fade out the active tooltip first
-               if (menuTooltipItem == world)
+               if (menuTooltipItem == NULL)
                        return;
-               it = world;
+               it = NULL;
                menu_tooltips_old = menu_tooltips;
        }
        else
@@ -558,7 +558,7 @@ void m_tooltip(vector pos)
                if(f < 0.01)
                        it = m_findtooltipitem(main, pos);
                else
-                       it = world;
+                       it = NULL;
        }
        fontsize = '1 0 0' * (SKINFONTSIZE_TOOLTIP / conwidth) + '0 1 0' * (SKINFONTSIZE_TOOLTIP / conheight);
 
@@ -629,12 +629,12 @@ void m_tooltip(vector pos)
                        if(menuTooltipAlpha == 0)
                        {
                                menuTooltipState = 0;
-                               menuTooltipItem = world;
+                               menuTooltipItem = NULL;
                        }
                        break;
        }
 
-       if(menuTooltipItem == world)
+       if(menuTooltipItem == NULL)
        {
                if (menuTooltipText)
                {
@@ -648,7 +648,7 @@ void m_tooltip(vector pos)
                if(menu_tooltips != menu_tooltips_old)
                {
                        if (menu_tooltips != 0 && menu_tooltips_old != 0)
-                               menuTooltipItem = world; // reload tooltip next frame
+                               menuTooltipItem = NULL; // reload tooltip next frame
                        menu_tooltips_old = menu_tooltips;
                }
                else if(menuTooltipOrigin.x < 0) // unallocated?
index 0ece40c88e4fe78f5d0c9bb14fec958fabb2ebf7..6d45ca82f46a36b7f4e64f449275ec36f895a829 100644 (file)
@@ -4,8 +4,6 @@
 #include "draw.qh"
 #include "skin.qh"
 
-#include "oo/base.qh"
-
 #include "xonotic/util.qh"
 
 #include "../common/constants.qh"
diff --git a/qcsrc/menu/oo/base.qh b/qcsrc/menu/oo/base.qh
deleted file mode 100644 (file)
index 894b4b9..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef BASE_H
-#define BASE_H
-
-#include "../../common/util.qh"
-#include "../../dpdefs/keycodes.qh"
-
-#define world NULL
-
-#endif
index 4a14eea7b1d12652fbb27b73dd706e11950851c0..16a830da048af49cdf18a659a9d7f367b7e9c7fd 100644 (file)
@@ -1,6 +1,5 @@
 #ifndef CLASSES_H
 #define CLASSES_H
-#include "base.qh"
 
 #include "../classes.inc"
 #define IMPLEMENTATION
index ba7411bb697b4297a12420f7049d3e1b9db30d9d..ae221de272b18dae865438e36afdfef9786ce0b9 100644 (file)
@@ -1,10 +1,7 @@
-#include "../common/util-pre.qh"
-#include "../dpdefs/menudefs.qh"
-#include "../dpdefs/keycodes.qh"
-#include "../common/util-post.qh"
-
 #include "../lib/_all.inc"
 
+#define world NULL
+
 #include "oo/classes.qc"
 
 #include "draw.qc"
index 9943731f7b313b6f7410d690606762f569cf30ab..8323221daf8fe7c948290f6a749ebadc409cb1ba 100644 (file)
@@ -70,12 +70,12 @@ float XonoticCvarList_updateCvarType(entity me)
        t = cvar_type(me.cvarName);
        me.cvarType = "";
        float needsForcing;
-       if(strstrofs(strcat(" ", autocvar_menu_forced_saved_cvars, " "), strcat(" ", me.cvarName, " "), 0) >= 0)
+       if(strhasword(autocvar_menu_forced_saved_cvars, me.cvarName))
        {
                me.cvarType = strcat(me.cvarType, ", ", _("forced to be saved to config.cfg"));
                needsForcing = 0;
        }
-       else if(strstrofs(strcat(" ", autocvar_menu_reverted_nonsaved_cvars, " "), strcat(" ", me.cvarName, " "), 0) >= 0)
+       else if(strhasword(autocvar_menu_reverted_nonsaved_cvars, me.cvarName))
        {
                // Currently claims to be saved, but won't be on next startup.
                me.cvarType = strcat(me.cvarType, ", ", _("will not be saved"));
@@ -177,9 +177,9 @@ void XonoticCvarList_drawListBoxItem(entity me, int i, vector absSize, bool isSe
        v = cvar_string(k);
        d = cvar_defstring(k);
        t = cvar_type(k);
-       if(strstrofs(strcat(" ", autocvar_menu_forced_saved_cvars, " "), strcat(" ", k, " "), 0) >= 0)
+       if(strhasword(autocvar_menu_forced_saved_cvars, k))
                theAlpha = SKINALPHA_CVARLIST_SAVED;
-       else if(strstrofs(strcat(" ", autocvar_menu_reverted_nonsaved_cvars, " "), strcat(" ", k, " "), 0) >= 0)
+       else if(strhasword(autocvar_menu_reverted_nonsaved_cvars, k))
                theAlpha = SKINALPHA_CVARLIST_TEMPORARY;
        else if(t & CVAR_TYPEFLAG_SAVED)
                theAlpha = SKINALPHA_CVARLIST_SAVED;
@@ -200,7 +200,7 @@ float XonoticCvarList_keyDown(entity me, float scan, float ascii, float shift)
 {
        if (scan == K_MOUSE3 || ((shift & S_CTRL) && scan == K_SPACE))
        {
-               CvarList_Revert_Click(world, me);
+               CvarList_Revert_Click(NULL, me);
                return 1;
        }
        else if(scan == K_ENTER)
@@ -243,7 +243,7 @@ void CvarList_Revert_Click(entity btn, entity me)
 {
        me.cvarValueBox.setText(me.cvarValueBox, me.cvarDefault);
        me.cvarValueBox.cursorPos = strlen(me.cvarDefault);
-       if(strstrofs(strcat(" ", autocvar_menu_forced_saved_cvars, " "), strcat(" ", me.cvarName, " "), 0) >= 0)
+       if(strhasword(autocvar_menu_forced_saved_cvars, me.cvarName))
        {
                cvar_set("menu_forced_saved_cvars", substring(strreplace(strcat(" ", me.cvarName, " "), " ", strcat(" ", autocvar_menu_forced_saved_cvars, " ")), 1, -2));
                if (autocvar_menu_reverted_nonsaved_cvars == "")
index 3cf20b7b5c01bea40b73c08d3b2bffe6fac1fa9b..880dda03258c0cab772312f45474d8642c6a1671 100644 (file)
@@ -98,7 +98,7 @@ float XonoticScreenshotViewerDialog_keyDown(entity me, float key, float ascii, f
                        // to press buttons while browsing with only the keyboard
                        if (shift & S_CTRL)
                        {
-                               toggleSlideShow_Click(world, me);
+                               toggleSlideShow_Click(NULL, me);
                                return 1;
                        }
                        return SUPER(XonoticScreenshotViewerDialog).keyDown(me, key, ascii, shift);
index 244d6b2b206ecf55a047a2223391063341bd4d87..3d41104488085fe1c629fc8980f728a055b921d6 100644 (file)
@@ -32,7 +32,7 @@ void MainWindow_draw(entity me)
 
        if(me.dialogToShow)
        {
-               DialogOpenButton_Click_withCoords(world, me.dialogToShow, '0 0 0', eX * conwidth + eY * conheight);
+               DialogOpenButton_Click_withCoords(NULL, me.dialogToShow, '0 0 0', eX * conwidth + eY * conheight);
                me.dialogToShow = NULL;
        }
 }
index e7693a2e351080f0eaa6e7fba4807c040f2fbc6a..6655e8a62c1bacff3be95b2b0f88846fba30883b 100644 (file)
@@ -208,7 +208,7 @@ void ScreenshotList_Filter_Change(entity box, entity me)
        else
                me.filterString = string_null;
 
-       ScreenshotList_Refresh_Click(world, me);
+       ScreenshotList_Refresh_Click(NULL, me);
 }
 
 void ScreenshotList_Filter_Would_Change(entity box, entity me)
index f49ea947e73bb7dd8601718453a75cd152b3a1f4..e2c6472092fe53d19068e426b1adbcff9a0f279a 100644 (file)
@@ -231,7 +231,7 @@ entity RetrieveCategoryEnt(int catnum)
        else
        {
                error(sprintf("RetrieveCategoryEnt(%d): Improper category number!\n", catnum));
-               return world;
+               return NULL;
        }
 }
 
index 6d283526801ac95de2ae61d99a882832c72d716d..159cd76c53d60a2bfe8c3b3c73c9fea6a74b9679 100644 (file)
@@ -24,7 +24,7 @@ CLASS(XonoticSoundList, XonoticListBox)
        ATTRIB(XonoticSoundList, itemAbsSize, vector, '0 0 0')
 
        ATTRIB(XonoticSoundList, filterString, string, string_null)
-       ATTRIB(XonoticSoundList, playlist, entity, world)
+       ATTRIB(XonoticSoundList, playlist, entity, NULL)
 ENDCLASS(XonoticSoundList)
 
 entity makeXonoticSoundList();
index f4faea62b92a3623530aa684f63a54fb58445590..146075ecaedc0842e145d98988be47ecc07db524 100644 (file)
@@ -1,6 +1,8 @@
 #include "util.qh"
+
+#include "../item.qc"
+
 #include "../menu.qh"
-#include "../oo/base.qh"
 #include "../../common/campaign_common.qh"
 #include "../../common/constants.qh"
 #include "../../common/mapinfo.qh"
@@ -9,7 +11,7 @@
 
 float GL_CheckExtension(string ext)
 {
-       return (strstrofs(strcat(" ", cvar_string("gl_info_extensions"), " "), strcat(" ", ext, " "), 0) >= 0);
+       return strhasword(cvar_string("gl_info_extensions"), ext);
 }
 
 float GL_Have_TextureCompression()
index 3e99cabeb85d6e1bc37b1b44cc7785fb8167cfde..eeb06e7a692f9f86ad283bb5a2e84731f308c152 100644 (file)
@@ -6,9 +6,8 @@
 #include "defs.qh"
 #include "miscfunctions.qh"
 
-#include "../dpdefs/progsdefs.qh"
-#include "../dpdefs/dpextensions.qh"
 
+#include "../common/effects/all.qh"
 #include "../common/models/all.qh"
 #include "../common/sounds/all.qh"
 
index 32742d82d9555e41330fa559acbee64314a1b7f3..61bb611fdc01cda06692cb77e537f35d46a92326 100644 (file)
@@ -5,8 +5,6 @@
 #include "defs.qh"
 #include "miscfunctions.qh"
 
-#include "../dpdefs/progsdefs.qh"
-#include "../dpdefs/dpextensions.qh"
 
 
 #include "command/common.qh"
index f152c8216d93f8575ffe121dd04c3ad5701e19f5..64db8da8f0ce1beb759bf4250ae657fba1c52310 100644 (file)
@@ -1,8 +1,6 @@
 #if defined(CSQC)
 #elif defined(MENUQC)
 #elif defined(SVQC)
-       #include "../dpdefs/progsdefs.qh"
-    #include "../dpdefs/dpextensions.qh"
     #include "../common/vehicles/all.qh"
     #include "antilag.qh"
 #endif
diff --git a/qcsrc/server/bot/_all.inc b/qcsrc/server/bot/_all.inc
new file mode 100644 (file)
index 0000000..2965baa
--- /dev/null
@@ -0,0 +1,7 @@
+#include "aim.qc"
+#include "bot.qc"
+#include "navigation.qc"
+#include "scripting.qc"
+#include "waypoints.qc"
+
+#include "havocbot/_all.inc"
index 4f750cdb4d48a5cc13d152c1decfd9b0d04a0257..07ea9091dc3f605f0bb56b7c759285480a432aeb 100644 (file)
@@ -1,8 +1,9 @@
 #include "aim.qh"
-#include "../_all.qh"
 
 #include "bot.qh"
 
+#include "../weapons/weaponsystem.qh"
+
 #include "../mutators/mutators_include.qh"
 
 // traces multiple trajectories to find one that will impact the target
index 00051cadb9cbdeee1b806ac9a7f8ec104a97f4ff..3b2af5d92c41141ed4f08cab410c20d6324b6abb 100644 (file)
@@ -1,5 +1,4 @@
 #include "bot.qh"
-#include "../_all.qh"
 
 #include "aim.qh"
 #include "navigation.qh"
@@ -9,6 +8,8 @@
 #include "havocbot/havocbot.qh"
 #include "havocbot/scripting.qh"
 
+#include "../teamplay.qh"
+
 #include "../antilag.qh"
 #include "../autocvars.qh"
 #include "../campaign.qh"
 
 #include "../../common/weapons/all.qh"
 
-#include "../../csqcmodellib/sv_model.qh"
-
-#include "../../dpdefs/dpextensions.qh"
-#include "../../dpdefs/progsdefs.qh"
+#include "../../lib/csqcmodel/sv_model.qh"
 
-#include "../../warpzonelib/common.qh"
-#include "../../warpzonelib/util_server.qh"
+#include "../../lib/warpzone/common.qh"
+#include "../../lib/warpzone/util_server.qh"
 
 entity bot_spawn()
 {SELFPARAM();
diff --git a/qcsrc/server/bot/havocbot/_all.inc b/qcsrc/server/bot/havocbot/_all.inc
new file mode 100644 (file)
index 0000000..fb73954
--- /dev/null
@@ -0,0 +1,3 @@
+#include "havocbot.qc"
+#include "role_keyhunt.qc"
+#include "roles.qc"
index f69527916ce512ad8c3d94ac61e798883716f459..ced6463c2ec7af55676390036fb3cbdc3030d56a 100644 (file)
@@ -1,5 +1,4 @@
 #include "havocbot.qh"
-#include "../../_all.qh"
 
 #include "../aim.qh"
 #include "../bot.qh"
@@ -8,10 +7,13 @@
 #include "../waypoints.qh"
 
 #include "../../../common/constants.qh"
+#include "../../../common/items/all.qh"
 
 #include "../../../common/triggers/trigger/jumppads.qh"
 
-#include "../../../warpzonelib/common.qh"
+#include "../../../lib/warpzone/common.qh"
+
+.float speed;
 
 void havocbot_ai()
 {SELFPARAM();
index b1603c792ac033806577bcd189016cac89040674..0059dc97a3d64a807d9a5837b89ca0666ded7df6 100644 (file)
@@ -1,5 +1,4 @@
 #include "role_keyhunt.qh"
-#include "../../_all.qh"
 
 #include "havocbot.qh"
 
index 037968f1367b30205fbeccad9ce569e401dcbb7d..a4357628eee88d6ae646e450f733e64f9363bd9c 100644 (file)
@@ -1,4 +1,3 @@
-#include "../../_all.qh"
 
 #include "havocbot.qh"
 #include "role_keyhunt.qh"
index 99e3901b2b3cb095b771a89286c9b5ac1bcae721..36171eddffb329ac84dc26fcad32b6cbffb750a4 100644 (file)
@@ -1,14 +1,17 @@
 #include "navigation.qh"
-#include "../_all.qh"
 
 #include "bot.qh"
 #include "waypoints.qh"
 
 #include "../t_items.qh"
 
+#include "../../common/items/all.qh"
+
 #include "../../common/constants.qh"
 #include "../../common/triggers/trigger/jumppads.qh"
 
+.float speed;
+
 void bot_debug(string input)
 {
        switch(autocvar_bot_debug)
index 72951cd6628b36e574d77b98abac0b2bfd2d6a0b..c3484e1d4c47e9c4bc1dc7753630dada4104b309 100644 (file)
@@ -1,8 +1,9 @@
 #include "scripting.qh"
-#include "../_all.qh"
 
 #include "bot.qh"
 
+.int state;
+
 .float bot_cmdqueuebuf_allocated;
 .float bot_cmdqueuebuf;
 .float bot_cmdqueuebuf_start;
index 8f50d0276a6efb67158ba9164649edbdec387c70..156ad79fc256fbbfd3dbd79fb5ee711e1598fc1b 100644 (file)
@@ -1,5 +1,4 @@
 #include "waypoints.qh"
-#include "../_all.qh"
 
 #include "bot.qh"
 #include "navigation.qh"
@@ -8,7 +7,8 @@
 
 #include "../../common/constants.qh"
 
-#include "../../warpzonelib/util_server.qh"
+#include "../../lib/warpzone/common.qh"
+#include "../../lib/warpzone/util_server.qh"
 
 // create a new spawnfunc_waypoint and automatically link it to other waypoints, and link
 // them back to it as well
index 7ecacb29a1f0828b7813c5956589138990ae3613..64c7cec19e17ea2627faf89f40ca8d91bd95710a 100644 (file)
@@ -1,5 +1,4 @@
 #include "cheats.qh"
-#include "_all.qh"
 
 #include "g_damage.qh"
 #include "race.qh"
@@ -11,7 +10,6 @@
 
 #include "../common/constants.qh"
 #include "../common/deathtypes/all.qh"
-#include "../common/effects/effects.qh"
 #include "../common/util.qh"
 
 #include "../common/monsters/all.qh"
 
 #include "../common/triggers/func/breakable.qh"
 
-#include "../csqcmodellib/sv_model.qh"
+#include "../lib/csqcmodel/sv_model.qh"
 
-#include "../warpzonelib/anglestransform.qh"
-#include "../warpzonelib/util_server.qh"
+#include "../lib/warpzone/anglestransform.qh"
+#include "../lib/warpzone/util_server.qh"
 
 void CopyBody(float keepvelocity);
 
index b798c7286000a094f9c91e4a53c867c1c2b7c4e1..c608c5b2c74a78325a2343556b1a679ff4137fd8 100644 (file)
@@ -24,6 +24,7 @@
 #include "bot/navigation.qh"
 
 #include "../common/vehicles/all.qh"
+#include "../common/triggers/teleporters.qh"
 
 #include "weapons/hitplot.qh"
 #include "weapons/weaponsystem.qh"
@@ -45,7 +46,7 @@
 
 #include "../common/monsters/sv_monsters.qh"
 
-#include "../warpzonelib/server.qh"
+#include "../lib/warpzone/server.qh"
 
 
 void send_CSQC_teamnagger() {
index a594c83c7c93b72876eb6fc3a24f6a47342945e3..8b36e17531c6a221d70d8ca2fa088b12b29c5f00 100644 (file)
@@ -1,4 +1,3 @@
-#include "_all.qh"
 #include "round_handler.qh"
 
 #include "bot/waypoints.qh"
 #include "../common/minigames/sv_minigames.qh"
 
 #include "../common/weapons/all.qh"
+#include "../common/vehicles/sv_vehicles.qh"
 
-/*
+#include "../common/mutators/mutator/waypoints/waypointsprites.qh"
+
+.entity vehicle;
+
+/**
  * Impulse map:
  *
  * 0 reserved (no input)
index 9e7f8a14b695e0f3c339c3db8d87568c9a3dc9c4..1b770121e8a8904b18ffe87312d271a8a885d741 100644 (file)
@@ -1,5 +1,4 @@
 #include "cl_player.qh"
-#include "_all.qh"
 
 #include "bot/bot.qh"
 #include "cheats.qh"
 #include "../common/deathtypes/all.qh"
 #include "../common/triggers/subs.qh"
 #include "../common/playerstats.qh"
-#include "../csqcmodellib/sv_model.qh"
+#include "../lib/csqcmodel/sv_model.qh"
 
 #include "../common/minigames/sv_minigames.qh"
 
+#include "../common/mutators/mutator/waypoints/waypointsprites.qh"
+#include "../common/triggers/include.qh"
+
 #include "weapons/weaponstats.qh"
 
 #include "../common/animdecide.qh"
index add929004c0cece3df6467b8f2ec64e931acbea8..f325dcd72c336c5f5c1ebfb86daec0802b968967 100644 (file)
@@ -1,6 +1,5 @@
 #include "../../common/command/command.qh"
 #include "banning.qh"
-#include "../_all.qh"
 
 #include "common.qh"
 
index c10518232bc8367f67ebd96daab2ac7b308ea7cb..ddfbe57950a0f46ff66ff83532dd89d9c1059bbd 100644 (file)
@@ -1,6 +1,5 @@
 #include "../../common/command/command.qh"
 #include "cmd.qh"
-#include "../_all.qh"
 
 #include "common.qh"
 #include "vote.qh"
 #include "../../common/deathtypes/all.qh"
 #include "../../common/mapinfo.qh"
 #include "../../common/notifications.qh"
+#include "../../common/physics.qh"
 #include "../../common/teams.qh"
 #include "../../common/util.qh"
+#include "../../common/triggers/triggers.qh"
+
+#include "../../common/minigames/sv_minigames.qh"
 
 #include "../../common/monsters/all.qc"
 #include "../../common/monsters/spawn.qh"
 #include "../../common/monsters/sv_monsters.qh"
 
-#include "../../warpzonelib/common.qh"
+#include "../../lib/warpzone/common.qh"
 
 void ClientKill_TeamChange (float targetteam); // 0 = don't change, -1 = auto, -2 = spec
 
index 0e04ce781cb2da5f570e192a614e5ebd8fe18ad5..1f2365822a4551ced188153991e3fa5045bb9a93 100644 (file)
@@ -10,9 +10,6 @@
 .float cmd_floodcount;
 .float lms_spectate_warning;
 
-// 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
index 56ad6445906b94578821d73ad2b291cc754468ec..fee82a7e4b5933a4263b191b4e3fb543b9e97e18 100644 (file)
@@ -1,10 +1,11 @@
 #include "../../common/command/command.qh"
 #include "common.qh"
-#include "../_all.qh"
 
 #include "../scores.qh"
 
+#include "../../common/monsters/all.qh"
 #include "../../common/notifications.qh"
+#include "../../lib/warpzone/common.qh"
 
 
 // ====================================================
index 1371e80100d24c792f626f91a3a5ce14c1945582..b3eeb1a69bdf2627042ceacb8daf94e107f7d55f 100644 (file)
@@ -1,6 +1,5 @@
 #include "../../common/command/command.qh"
 #include "getreplies.qh"
-#include "../_all.qh"
 
 #include "../race.qh"
 
index 8c15819e05ad174a0ea24f09e573b92061554048..60e6bde62db74433b8ee63b3a1b79a5da22ae780 100644 (file)
@@ -1,12 +1,12 @@
 #include "../../common/command/command.qh"
 #include "radarmap.qh"
-#include "../_all.qh"
 
 #include "../g_world.qh"
+#include "../g_subs.qh"
 
 #include "../../common/util.qh"
 
-#include "../../csqcmodellib/sv_model.qh"
+#include "../../lib/csqcmodel/sv_model.qh"
 
 // ===============================================
 //     Generates radar map images for use in the HUD
index d08588ff99c1a3501fe28992bee5329c1654b7c5..21255e5ddf50e91d4bc12f44168340fd56ad8e40 100644 (file)
@@ -1,6 +1,5 @@
 #include "../../common/command/command.qh"
 #include "sv_cmd.qh"
-#include "../_all.qh"
 
 #include "banning.qh"
 #include "cmd.qh"
index c92ffd3e82a31dd065d8bd288a97b4cb0f71febe..60faeb3c254c709009966df0ebe13a3b8c725860 100644 (file)
@@ -1,6 +1,5 @@
 #include "../../common/command/command.qh"
 #include "vote.qh"
-#include "../_all.qh"
 
 #include "common.qh"
 
index 7f17228fa23b0513b203f77a078bcc9dedd7205a..ceeb4f185b3fd846af054373f3c70ae5e7aa7c93 100644 (file)
@@ -1,5 +1,9 @@
 #include "controlpoint.qh"
 
+#include "command/common.qh"
+
+.bool iscaptured;
+
 bool cpicon_send(entity this, entity to, int sf)
 {
        WriteByte(MSG_ENTITY, ENT_CLIENT_CONTROLPOINT_ICON);
index 4ebe76b401fb0321724f6ed7b755d37d9da36e07..a26fa97aa8da334189dbc6c4e79e97416da6780c 100644 (file)
@@ -1,7 +1,6 @@
 #if defined(CSQC)
 #elif defined(MENUQC)
 #elif defined(SVQC)
-       #include "../dpdefs/progsdefs.qh"
     #include "../common/constants.qh"
 #endif
 
index 768eae30b2eb1a16493ae9bc74eaf51d0f8d0e58..548c60429b709b3064eb12491f4585d2a2b388be 100644 (file)
@@ -1,5 +1,6 @@
 #include "ent_cs.qh"
-#include "_all.qh"
+
+#include "mutators/gamemode_ca.qh"
 
 float entcs_customize()
 {
index ca715c722800f22787f164e7af18837fb5f6eb37..b005da47a24e48e7a5b70eaa7cd143273eb03f30 100644 (file)
@@ -1,12 +1,14 @@
 #include "g_damage.qh"
-#include "_all.qh"
 
+#include "bot/bot.qh"
 #include "g_hook.qh"
 #include "mutators/mutators_include.qh"
 #include "scores.qh"
 #include "spawnpoints.qh"
 #include "t_items.qh"
 #include "../common/vehicles/all.qh"
+#include "../common/items/all.qc"
+#include "../common/mutators/mutator/waypoints/waypointsprites.qh"
 #include "weapons/accuracy.qh"
 #include "weapons/csqcprojectile.qh"
 #include "weapons/selection.qh"
@@ -19,8 +21,8 @@
 #include "../common/teams.qh"
 #include "../common/util.qh"
 #include "../common/weapons/all.qh"
-#include "../csqcmodellib/sv_model.qh"
-#include "../warpzonelib/common.qh"
+#include "../lib/csqcmodel/sv_model.qh"
+#include "../lib/warpzone/common.qh"
 
 bool Damage_DamageInfo_SendEntity(entity this, entity to, int sf)
 {
index 4df5303b255eef04c5477d14e49669669bcb4b58..62a74be22d0289087b1fd1f45b6e689fb026e8a9 100644 (file)
@@ -4,9 +4,7 @@
 #if defined(CSQC)
 #elif defined(MENUQC)
 #elif defined(SVQC)
-       #include "../dpdefs/progsdefs.qh"
-    #include "../dpdefs/dpextensions.qh"
-    #include "../warpzonelib/common.qh"
+    #include "../lib/warpzone/common.qh"
     #include "../common/constants.qh"
     #include "../common/teams.qh"
     #include "../common/util.qh"
@@ -23,7 +21,7 @@
     #include "mutators/mutators_include.qh"
     #include "../common/turrets/sv_turrets.qh"
     #include "../common/vehicles/all.qh"
-    #include "../csqcmodellib/sv_model.qh"
+    #include "../lib/csqcmodel/sv_model.qh"
     #include "../common/playerstats.qh"
     #include "g_hook.qh"
     #include "scores.qh"
index ec66994280b9874c70af8ddd3cbcfc5e89e76671..7a77d4aff695a0a1fbfdb50ef10a838223c6d77c 100644 (file)
@@ -1,7 +1,7 @@
 #include "g_hook.qh"
-#include "_all.qh"
 
 #include "weapons/common.qh"
+#include "weapons/csqcprojectile.qh"
 #include "weapons/weaponsystem.qh"
 #include "weapons/selection.qh"
 #include "weapons/tracing.qh"
 #include "../common/constants.qh"
 #include "../common/util.qh"
 #include "../common/weapons/all.qh"
-#include "../warpzonelib/common.qh"
-#include "../warpzonelib/server.qh"
+#include "../lib/warpzone/common.qh"
+#include "../lib/warpzone/server.qh"
+
+.int state;
 
 /*============================================
 
index bd5232a1c93338c5de9e164531cd5296798b0730..8399b5fdb976d3c50f1fedf29bb117509c23bc96 100644 (file)
@@ -1,9 +1,10 @@
-#include "_all.qh"
 
 void train_next();
 
 const float LOOP = 1;
 
+.float speed;
+
 const float DNOSHADOW = 2;
 const float DFOLLOW = 4;
 .float light_lev;
index 781ecc612e7d3f2f968e524c954d6a766022b716..8bc5387367542162947a07b205be9b51b3db38a9 100644 (file)
@@ -1,11 +1,17 @@
-#include "_all.qh"
 
+#include "g_subs.qh"
 #include "../common/triggers/subs.qh"
+#include "../common/triggers/triggers.qh"
 
-#include "../client/bgmscript.qh"
+entityclass(BGMScript);
+class(BGMScript) .string bgmscript;
+class(BGMScript) .float bgmscriptattack;
+class(BGMScript) .float bgmscriptdecay;
+class(BGMScript) .float bgmscriptsustain;
+class(BGMScript) .float bgmscriptrelease;
 
 #include "../common/constants.qh"
-#include "../csqcmodellib/sv_model.qh"
+#include "../lib/csqcmodel/sv_model.qh"
 
 .float modelscale;
 
index 585ac42e085b56852be47ac023d9d11976e92404..af1cf7cc2e79d42e470926f8221847ef0d2f369e 100644 (file)
@@ -1,9 +1,9 @@
 #include "g_subs.qh"
-#include "_all.qh"
 
 #include "antilag.qh"
 #include "command/common.qh"
-#include "../warpzonelib/common.qh"
+#include "../lib/warpzone/common.qh"
+#include "../common/triggers/subs.qh"
 
 spawnfunc(info_null)
 {
index 2a885f901ab2f0b7100326430fa6963ea31c6855..b016acdd623383beda3c47e1b67658dcd3582a29 100644 (file)
@@ -1,5 +1,6 @@
 #include "g_violence.qh"
-#include "_all.qh"
+
+.int state;
 
 bool Violence_GibSplash_SendEntity(entity this, entity to, int sf)
 {
index 00a97d7ddae45a3359c11917d63e13c43d32207e..fc3eed45286cd110e4a697a050d40cbd0f3b63a3 100644 (file)
@@ -1,5 +1,4 @@
 #include "g_world.qh"
-#include "_all.qh"
 
 #include "anticheat.qh"
 #include "antilag.qh"
 #include "../common/buffs/all.qh"
 #include "../common/constants.qh"
 #include "../common/deathtypes/all.qh"
-#include "../common/effects/effects.qh"
 #include "../common/mapinfo.qh"
 #include "../common/monsters/all.qh"
 #include "../common/monsters/sv_monsters.qh"
 #include "../common/vehicles/all.qh"
 #include "../common/notifications.qh"
+#include "../common/physics.qh"
 #include "../common/playerstats.qh"
 #include "../common/stats.qh"
 #include "../common/teams.qh"
+#include "../common/triggers/trigger/secret.qh"
 #include "../common/util.qh"
 #include "../common/items/all.qh"
 #include "../common/weapons/all.qh"
@@ -601,7 +601,6 @@ spawnfunc(worldspawn)
 
        // needs to be done so early because of the constants they create
        static_init();
-       CALL_ACCUMULATED_FUNCTION(RegisterNotifications);
 
        ServerProgsDB = db_load(strcat("server.db", autocvar_sessionid));
 
index 5bf648a0b5995b7269e7e10ceb09af334088ba44..a60970d21af00b73d7d9fe72891ec2c60649cdca 100644 (file)
@@ -1,13 +1,10 @@
 #include "ipban.qh"
-#include "_all.qh"
 
 #include "autocvars.qh"
 #include "command/banning.qh"
 #include "defs.qh"
 #include "../common/constants.qh"
 #include "../common/util.qh"
-#include "../dpdefs/dpextensions.qh"
-#include "../dpdefs/progsdefs.qh"
 
 /*
  * Protocol of online ban list:
index 713fbf6c3df57e87a8c704e7916da1ba11e562b0..8df6e3b46e18c58e472dbe3aed21ecddd0dd4061 100644 (file)
@@ -1,11 +1,10 @@
 #include "item_key.qh"
-#include "_all.qh"
 
 #include "../common/triggers/subs.qh"
 #include "../common/monsters/all.qh"
 #include "../common/notifications.qh"
 #include "../common/util.qh"
-#include "../warpzonelib/util_server.qh"
+#include "../lib/warpzone/util_server.qh"
 
 /*
 TODO:
index a8e027df1e1769187e919842d46bac97e1c2005a..5a9f7e0765c85e5a66e6d4ada2da8048b02fd597 100644 (file)
@@ -1,5 +1,4 @@
 #include "mapvoting.qh"
-#include "_all.qh"
 
 #include "g_world.qh"
 #include "command/cmd.qh"
index 875cdc412d51943cdf3b7006256730e8d8e9d456..c864373ad8c6d17cd3320b6f2d061ee180ff43aa 100644 (file)
@@ -1,5 +1,4 @@
 #include "miscfunctions.qh"
-#include "_all.qh"
 #include "antilag.qh"
 #include "command/common.qh"
 #include "constants.qh"
 #include "../common/util.qh"
 #include "../common/turrets/sv_turrets.qh"
 #include "../common/weapons/all.qh"
-#include "../csqcmodellib/sv_model.qh"
-#include "../warpzonelib/anglestransform.qh"
-#include "../warpzonelib/server.qh"
+#include "../common/vehicles/sv_vehicles.qh"
+#include "../common/vehicles/vehicle.qh"
+#include "../common/items/all.qc"
+#include "../lib/csqcmodel/sv_model.qh"
+#include "../lib/warpzone/anglestransform.qh"
+#include "../lib/warpzone/server.qh"
 
 void crosshair_trace(entity pl)
 {
index 77b959ed7ee614b68aa4ad4f60e321e075521cde..da11aefeeb0fbad8b186f1650ae340caa09f5b01 100644 (file)
@@ -11,6 +11,7 @@
 #include "../round_handler.qh"
 #include "../scores.qh"
 #include "../scores_rules.qh"
+#include "../teamplay.qh"
 
 #include "../bot/bot.qh"
 #include "../bot/navigation.qh"
@@ -36,8 +37,8 @@
 #include "../../common/stats.qh"
 #include "../../common/teams.qh"
 
-#include "../../warpzonelib/server.qh"
-#include "../../warpzonelib/util_server.qh"
+#include "../../lib/warpzone/server.qh"
+#include "../../lib/warpzone/util_server.qh"
 
 .float lastground;
 float total_players;
index 1a10e3c6c9c789107fc0b80901f63bc7d941230f..85d975fbc60f7b89f26071138a0b081232b37b3f 100644 (file)
@@ -1,5 +1,4 @@
 #include "gamemode_assault.qh"
-#include "../_all.qh"
 
 #include "gamemode.qh"
 
@@ -296,6 +295,7 @@ spawnfunc(target_objective_decrease)
 }
 
 // destructible walls that can be used to trigger target_objective_decrease
+spawnfunc(func_breakable);
 spawnfunc(func_assault_destructible)
 {
        if (!g_assault) { remove(self); return; }
index a368fff7809eead10caa1d9c464ecd55420da1e7..42aa4a29e77f000832c406a49620331d9010c850 100644 (file)
@@ -1,5 +1,4 @@
 #include "gamemode_ca.qh"
-#include "../_all.qh"
 
 #include "gamemode.qh"
 
index da2e76f8b205047d3da6ee6c1d5349d31063697a..0c68bbfd0ff122aae3bc048ce595556d8dcf7dc6 100644 (file)
@@ -1,13 +1,13 @@
 #include "gamemode_ctf.qh"
-#include "../_all.qh"
 
 #include "gamemode.qh"
 
 #ifdef SVQC
 #include "../../common/vehicles/all.qh"
+#include "../teamplay.qh"
 #endif
 
-#include "../../warpzonelib/common.qh"
+#include "../../lib/warpzone/common.qh"
 
 void ctf_FakeTimeLimit(entity e, float t)
 {
@@ -2344,9 +2344,11 @@ spawnfunc(ctf_team)
 // compatibility for quake maps
 spawnfunc(team_CTF_redflag)    { spawnfunc_item_flag_team1(this);    }
 spawnfunc(team_CTF_blueflag)   { spawnfunc_item_flag_team2(this);    }
+spawnfunc(info_player_team1);
 spawnfunc(team_CTF_redplayer)  { spawnfunc_info_player_team1(this);  }
-spawnfunc(team_CTF_blueplayer) { spawnfunc_info_player_team2(this);  }
 spawnfunc(team_CTF_redspawn)   { spawnfunc_info_player_team1(this);  }
+spawnfunc(info_player_team2);
+spawnfunc(team_CTF_blueplayer) { spawnfunc_info_player_team2(this);  }
 spawnfunc(team_CTF_bluespawn)  { spawnfunc_info_player_team2(this);  }
 
 void team_CTF_neutralflag()                     { SELFPARAM(); spawnfunc_item_flag_neutral(self);  }
index 04357de9cc4d970cf1dea858da74044fecf0cfff..06e2ca3fa571ae6f6ec91694740f9a0c5a1b2ecf 100644 (file)
@@ -1,5 +1,4 @@
 #include "gamemode_cts.qh"
-#include "../_all.qh"
 
 #include "gamemode.qh"
 
index 06afc516ba3148e46abfe8591ff98e330418e87a..c3c8b0df5014072d8dfe91b5925e5bff3e742aad 100644 (file)
@@ -1,3 +1,5 @@
+#include "gamemode.qh"
+
 MUTATOR_HOOKFUNCTION(dm_CountFrags)
 {
        // announce remaining frags
index 34b2875105a6f404588ad6d05477c2920230c369..9e309f6e45eb8248a5baafd8b9d14a390de7ed82 100644 (file)
@@ -1,8 +1,9 @@
 #include "gamemode_domination.qh"
-#include "../_all.qh"
 
 #include "gamemode.qh"
 
+#include "../teamplay.qh"
+
 void dom_EventLog(string mode, float team_before, entity actor) // use an alias for easy changing and quick editing later
 {
        if(autocvar_sv_eventlog)
@@ -295,7 +296,7 @@ void dom_controlpoint_setup()
        WaypointSprite_SpawnFixed(WP_DomNeut, self.origin + '0 0 32', self, sprite, RADARICON_DOMPOINT);
 }
 
-float total_controlpoints, redowned, blueowned, yellowowned, pinkowned;
+float total_controlpoints;
 void Domination_count_controlpoints()
 {
        entity e;
index d8d792ad6c56f9a14c97d0a1fbbd4550b2233792..6eb2128f3bdaa0a96e6b02437e5947ef189a16cb 100644 (file)
@@ -1,5 +1,4 @@
 #include "gamemode_freezetag.qh"
-#include "../_all.qh"
 
 #include "gamemode.qh"
 
index 5209b225f1084629f085a6cf65b9cc0b86ef7a22..0929d93a5da643993687f1a105cdbe552d87d600 100644 (file)
@@ -1,11 +1,12 @@
 #include "gamemode_invasion.qh"
-#include "../_all.qh"
 
 #include "gamemode.qh"
 
 #include "../../common/monsters/spawn.qh"
 #include "../../common/monsters/sv_monsters.qh"
 
+#include "../teamplay.qh"
+
 spawnfunc(invasion_spawnpoint)
 {
        if(!g_invasion) { remove(self); return; }
index b265e41d3d5ae47a29097f683546e602da99e87a..b4951c6e70d21299a119cf27ef310e9ea53c4eac 100644 (file)
@@ -1,5 +1,4 @@
 #include "gamemode_keepaway.qh"
-#include "../_all.qh"
 
 #include "gamemode.qh"
 
@@ -356,6 +355,9 @@ MUTATOR_HOOKFUNCTION(ka_PlayerPowerups)
        return 0;
 }
 
+.float stat_sv_airspeedlimit_nonqw;
+.float stat_sv_maxspeed;
+
 MUTATOR_HOOKFUNCTION(ka_PlayerPhysics)
 {SELFPARAM();
        if(self.ballcarried)
index be45c3db0c3785f51f9d5f62744961b7c09ec117..68097755e8e23a5515e95845c9adb7201cbad047 100644 (file)
@@ -1,5 +1,4 @@
 #include "gamemode_keyhunt.qh"
-#include "../_all.qh"
 
 #include "gamemode.qh"
 
index b9395b913a2ad018feeca4540da7dc7adebb513d..b3cf0db6acd4464dddcb923871d47210944c3d54 100644 (file)
@@ -1,5 +1,4 @@
 #include "gamemode_lms.qh"
-#include "../_all.qh"
 
 #include "gamemode.qh"
 
diff --git a/qcsrc/server/mutators/gamemode_nexball.qc b/qcsrc/server/mutators/gamemode_nexball.qc
deleted file mode 100644 (file)
index f65e058..0000000
+++ /dev/null
@@ -1,1044 +0,0 @@
-#include "gamemode_nexball.qh"
-#include "../_all.qh"
-
-#include "gamemode.qh"
-
-float autocvar_g_nexball_basketball_bouncefactor;
-float autocvar_g_nexball_basketball_bouncestop;
-float autocvar_g_nexball_basketball_carrier_highspeed;
-bool autocvar_g_nexball_basketball_meter;
-float autocvar_g_nexball_basketball_meter_maxpower;
-float autocvar_g_nexball_basketball_meter_minpower;
-float autocvar_g_nexball_delay_collect;
-float autocvar_g_nexball_delay_goal;
-float autocvar_g_nexball_delay_start;
-float autocvar_g_nexball_football_bouncefactor;
-float autocvar_g_nexball_football_bouncestop;
-bool autocvar_g_nexball_radar_showallplayers;
-bool autocvar_g_nexball_sound_bounce;
-int autocvar_g_nexball_trail_color;
-
-float autocvar_g_nexball_safepass_turnrate;
-float autocvar_g_nexball_safepass_maxdist;
-float autocvar_g_nexball_safepass_holdtime;
-float autocvar_g_nexball_viewmodel_scale;
-float autocvar_g_nexball_tackling;
-vector autocvar_g_nexball_viewmodel_offset;
-
-void basketball_touch();
-void football_touch();
-void ResetBall();
-const float NBM_NONE = 0;
-const float NBM_FOOTBALL = 2;
-const float NBM_BASKETBALL = 4;
-float nexball_mode;
-
-float OtherTeam(float t)  //works only if there are two teams on the map!
-{
-       entity e;
-       e = find(world, classname, "nexball_team");
-       if(e.team == t)
-               e = find(e, classname, "nexball_team");
-       return e.team;
-}
-
-const float ST_NEXBALL_GOALS = 1;
-const float SP_NEXBALL_GOALS = 4;
-const float SP_NEXBALL_FAULTS = 5;
-void nb_ScoreRules(float teams)
-{
-       ScoreRules_basics(teams, 0, 0, true);
-       ScoreInfo_SetLabel_TeamScore(   ST_NEXBALL_GOALS,  "goals", SFL_SORT_PRIO_PRIMARY);
-       ScoreInfo_SetLabel_PlayerScore( SP_NEXBALL_GOALS,  "goals", SFL_SORT_PRIO_PRIMARY);
-       ScoreInfo_SetLabel_PlayerScore(SP_NEXBALL_FAULTS, "faults", SFL_SORT_PRIO_SECONDARY | SFL_LOWER_IS_BETTER);
-       ScoreRules_basics_end();
-}
-
-void LogNB(string mode, entity actor)
-{
-       string s;
-       if(!autocvar_sv_eventlog)
-               return;
-       s = strcat(":nexball:", mode);
-       if(actor != world)
-               s = strcat(s, ":", ftos(actor.playerid));
-       GameLogEcho(s);
-}
-
-void ball_restart(void)
-{SELFPARAM();
-       if(self.owner)
-               DropBall(self, self.owner.origin, '0 0 0');
-       ResetBall();
-}
-
-void nexball_setstatus(void)
-{SELFPARAM();
-       self.items &= ~IT_KEY1;
-       if(self.ballcarried)
-       {
-               if(self.ballcarried.teamtime && (self.ballcarried.teamtime < time))
-               {
-                       bprint("The ", Team_ColoredFullName(self.team), " held the ball for too long.\n");
-                       setself(self.ballcarried);
-                       DropBall(self, self.owner.origin, '0 0 0');
-                       ResetBall();
-                       setself(this);
-               }
-               else
-                       self.items |= IT_KEY1;
-       }
-}
-
-void relocate_nexball(void)
-{SELFPARAM();
-       tracebox(self.origin, BALL_MINS, BALL_MAXS, self.origin, true, self);
-       if(trace_startsolid)
-       {
-               vector o;
-               o = self.origin;
-               if(!move_out_of_solid(self))
-                       objerror("could not get out of solid at all!");
-               LOG_INFO("^1NOTE: this map needs FIXING. ", self.classname, " at ", vtos(o - '0 0 1'));
-               LOG_INFO(" needs to be moved out of solid, e.g. by '", ftos(self.origin.x - o.x));
-               LOG_INFO(" ", ftos(self.origin.y - o.y));
-               LOG_INFO(" ", ftos(self.origin.z - o.z), "'\n");
-               self.origin = o;
-       }
-}
-
-void DropOwner(void)
-{SELFPARAM();
-       entity ownr;
-       ownr = self.owner;
-       DropBall(self, ownr.origin, ownr.velocity);
-       makevectors(ownr.v_angle.y * '0 1 0');
-       ownr.velocity += ('0 0 0.75' - v_forward) * 1000;
-       ownr.flags &= ~FL_ONGROUND;
-}
-
-void GiveBall(entity plyr, entity ball)
-{SELFPARAM();
-       entity ownr;
-
-       if((ownr = ball.owner))
-       {
-               ownr.effects &= ~autocvar_g_nexball_basketball_effects_default;
-               ownr.ballcarried = world;
-               if(ownr.metertime)
-               {
-                       ownr.metertime = 0;
-                       ownr.weaponentity.state = WS_READY;
-               }
-               WaypointSprite_Kill(ownr.waypointsprite_attachedforcarrier);
-       }
-       else
-       {
-               WaypointSprite_Kill(ball.waypointsprite_attachedforcarrier);
-       }
-
-       //setattachment(ball, plyr, "");
-       setorigin(ball, plyr.origin + plyr.view_ofs);
-
-       if(ball.team != plyr.team)
-               ball.teamtime = time + autocvar_g_nexball_basketball_delay_hold_forteam;
-
-       ball.owner = ball.pusher = plyr; //"owner" is set to the player carrying, "pusher" to the last player who touched it
-       ball.team = plyr.team;
-       plyr.ballcarried = ball;
-       ball.nb_dropper = plyr;
-
-       plyr.effects |= autocvar_g_nexball_basketball_effects_default;
-       ball.effects &= ~autocvar_g_nexball_basketball_effects_default;
-
-       ball.velocity = '0 0 0';
-       ball.movetype = MOVETYPE_NONE;
-       ball.touch = func_null;
-       ball.effects |= EF_NOSHADOW;
-       ball.scale = 1; // scale down.
-
-       WaypointSprite_AttachCarrier(WP_NbBall, plyr, RADARICON_FLAGCARRIER);
-       WaypointSprite_UpdateRule(plyr.waypointsprite_attachedforcarrier, 0, SPRITERULE_DEFAULT);
-
-       if(autocvar_g_nexball_basketball_delay_hold)
-       {
-               ball.think = DropOwner;
-               ball.nextthink = time + autocvar_g_nexball_basketball_delay_hold;
-       }
-
-       plyr.weaponentity.weapons = plyr.weapons;
-       plyr.weaponentity.switchweapon = plyr.weapon;
-       plyr.weapons = WEPSET(NEXBALL);
-       setself(plyr);
-       Weapon w = WEP_NEXBALL;
-       w.wr_resetplayer(w);
-       plyr.switchweapon = WEP_NEXBALL.m_id;
-       W_SwitchWeapon(WEP_NEXBALL.m_id);
-       setself(this);
-}
-
-void DropBall(entity ball, vector org, vector vel)
-{
-       ball.effects |= autocvar_g_nexball_basketball_effects_default;
-       ball.effects &= ~EF_NOSHADOW;
-       ball.owner.effects &= ~autocvar_g_nexball_basketball_effects_default;
-
-       setattachment(ball, world, "");
-       setorigin(ball, org);
-       ball.movetype = MOVETYPE_BOUNCE;
-       ball.flags &= ~FL_ONGROUND;
-       ball.scale = ball_scale;
-       ball.velocity = vel;
-       ball.nb_droptime = time;
-       ball.touch = basketball_touch;
-       ball.think = ResetBall;
-       ball.nextthink = min(time + autocvar_g_nexball_delay_idle, ball.teamtime);
-
-       if(ball.owner.metertime)
-       {
-               ball.owner.metertime = 0;
-               ball.owner.weaponentity.state = WS_READY;
-       }
-
-       WaypointSprite_Kill(ball.owner.waypointsprite_attachedforcarrier);
-       WaypointSprite_Spawn(WP_NbBall, 0, 0, ball, '0 0 64', world, ball.team, ball, waypointsprite_attachedforcarrier, false, RADARICON_FLAGCARRIER); // no health bar please
-       WaypointSprite_UpdateRule(ball.waypointsprite_attachedforcarrier, 0, SPRITERULE_DEFAULT);
-
-       ball.owner.ballcarried = world;
-       ball.owner = world;
-}
-
-void InitBall(void)
-{SELFPARAM();
-       if(gameover) return;
-       self.flags &= ~FL_ONGROUND;
-       self.movetype = MOVETYPE_BOUNCE;
-       if(self.classname == "nexball_basketball")
-               self.touch = basketball_touch;
-       else if(self.classname == "nexball_football")
-               self.touch = football_touch;
-       self.cnt = 0;
-       self.think = ResetBall;
-       self.nextthink = time + autocvar_g_nexball_delay_idle + 3;
-       self.teamtime = 0;
-       self.pusher = world;
-       self.team = false;
-       _sound(self, CH_TRIGGER, self.noise1, VOL_BASE, ATTEN_NORM);
-       WaypointSprite_Ping(self.waypointsprite_attachedforcarrier);
-       LogNB("init", world);
-}
-
-void ResetBall(void)
-{SELFPARAM();
-       if(self.cnt < 2)        // step 1
-       {
-               if(time == self.teamtime)
-                       bprint("The ", Team_ColoredFullName(self.team), " held the ball for too long.\n");
-
-               self.touch = func_null;
-               self.movetype = MOVETYPE_NOCLIP;
-               self.velocity = '0 0 0'; // just in case?
-               if(!self.cnt)
-                       LogNB("resetidle", world);
-               self.cnt = 2;
-               self.nextthink = time;
-       }
-       else if(self.cnt < 4)     // step 2 and 3
-       {
-//             dprint("Step ", ftos(self.cnt), ": Calculated velocity: ", vtos(self.spawnorigin - self.origin), ", time: ", ftos(time), "\n");
-               self.velocity = (self.spawnorigin - self.origin) * (self.cnt - 1); // 1 or 0.5 second movement
-               self.nextthink = time + 0.5;
-               self.cnt += 1;
-       }
-       else     // step 4
-       {
-//             dprint("Step 4: time: ", ftos(time), "\n");
-               if(vlen(self.origin - self.spawnorigin) > 10)  // should not happen anymore
-                       LOG_TRACE("The ball moved too far away from its spawn origin.\nOffset: ",
-                                  vtos(self.origin - self.spawnorigin), " Velocity: ", vtos(self.velocity), "\n");
-               self.velocity = '0 0 0';
-               setorigin(self, self.spawnorigin); // make sure it's positioned correctly anyway
-               self.movetype = MOVETYPE_NONE;
-               self.think = InitBall;
-               self.nextthink = max(time, game_starttime) + autocvar_g_nexball_delay_start;
-       }
-}
-
-void football_touch(void)
-{SELFPARAM();
-       if(other.solid == SOLID_BSP)
-       {
-               if(time > self.lastground + 0.1)
-               {
-                       _sound(self, CH_TRIGGER, self.noise, VOL_BASE, ATTEN_NORM);
-                       self.lastground = time;
-               }
-               if(vlen(self.velocity) && !self.cnt)
-                       self.nextthink = time + autocvar_g_nexball_delay_idle;
-               return;
-       }
-       if (!IS_PLAYER(other))
-               return;
-       if(other.health < 1)
-               return;
-       if(!self.cnt)
-               self.nextthink = time + autocvar_g_nexball_delay_idle;
-
-       self.pusher = other;
-       self.team = other.team;
-
-       if(autocvar_g_nexball_football_physics == -1)   // MrBougo try 1, before decompiling Rev's original
-       {
-               if(vlen(other.velocity))
-                       self.velocity = other.velocity * 1.5 + '0 0 1' * autocvar_g_nexball_football_boost_up;
-       }
-       else if(autocvar_g_nexball_football_physics == 1)         // MrBougo's modded Rev style: partially independant of the height of the aiming point
-       {
-               makevectors(other.v_angle);
-               self.velocity = other.velocity + v_forward * autocvar_g_nexball_football_boost_forward + '0 0 1' * autocvar_g_nexball_football_boost_up;
-       }
-       else if(autocvar_g_nexball_football_physics == 2)         // 2nd mod try: totally independant. Really playable!
-       {
-               makevectors(other.v_angle.y * '0 1 0');
-               self.velocity = other.velocity + v_forward * autocvar_g_nexball_football_boost_forward + v_up * autocvar_g_nexball_football_boost_up;
-       }
-       else     // Revenant's original style (from the original mod's disassembly, acknowledged by Revenant)
-       {
-               makevectors(other.v_angle);
-               self.velocity = other.velocity + v_forward * autocvar_g_nexball_football_boost_forward + v_up * autocvar_g_nexball_football_boost_up;
-       }
-       self.avelocity = -250 * v_forward;  // maybe there is a way to make it look better?
-}
-
-void basketball_touch(void)
-{SELFPARAM();
-       if(other.ballcarried)
-       {
-               football_touch();
-               return;
-       }
-       if(!self.cnt && IS_PLAYER(other) && !other.frozen && !other.deadflag && (other != self.nb_dropper || time > self.nb_droptime + autocvar_g_nexball_delay_collect))
-       {
-               if(other.health <= 0)
-                       return;
-               LogNB("caught", other);
-               GiveBall(other, self);
-       }
-       else if(other.solid == SOLID_BSP)
-       {
-               _sound(self, CH_TRIGGER, self.noise, VOL_BASE, ATTEN_NORM);
-               if(vlen(self.velocity) && !self.cnt)
-                       self.nextthink = min(time + autocvar_g_nexball_delay_idle, self.teamtime);
-       }
-}
-
-void GoalTouch(void)
-{SELFPARAM();
-       entity ball;
-       float isclient, pscore, otherteam;
-       string pname;
-
-       if(gameover) return;
-       if((self.spawnflags & GOAL_TOUCHPLAYER) && other.ballcarried)
-               ball = other.ballcarried;
-       else
-               ball = other;
-       if(ball.classname != "nexball_basketball")
-               if(ball.classname != "nexball_football")
-                       return;
-       if((!ball.pusher && self.team != GOAL_OUT) || ball.cnt)
-               return;
-       EXACTTRIGGER_TOUCH;
-
-
-       if(nb_teams == 2)
-               otherteam = OtherTeam(ball.team);
-       else
-               otherteam = 0;
-
-       if((isclient = IS_CLIENT(ball.pusher)))
-               pname = ball.pusher.netname;
-       else
-               pname = "Someone (?)";
-
-       if(ball.team == self.team)               //owngoal (regular goals)
-       {
-               LogNB("owngoal", ball.pusher);
-               bprint("Boo! ", pname, "^7 scored a goal against their own team!\n");
-               pscore = -1;
-       }
-       else if(self.team == GOAL_FAULT)
-       {
-               LogNB("fault", ball.pusher);
-               if(nb_teams == 2)
-                       bprint(Team_ColoredFullName(otherteam), " gets a point due to ", pname, "^7's silliness.\n");
-               else
-                       bprint(Team_ColoredFullName(ball.team), " loses a point due to ", pname, "^7's silliness.\n");
-               pscore = -1;
-       }
-       else if(self.team == GOAL_OUT)
-       {
-               LogNB("out", ball.pusher);
-               if((self.spawnflags & GOAL_TOUCHPLAYER) && ball.owner)
-                       bprint(pname, "^7 went out of bounds.\n");
-               else
-                       bprint("The ball was returned.\n");
-               pscore = 0;
-       }
-       else                                                       //score
-       {
-               LogNB(strcat("goal:", ftos(self.team)), ball.pusher);
-               bprint("Goaaaaal! ", pname, "^7 scored a point for the ", Team_ColoredFullName(ball.team), ".\n");
-               pscore = 1;
-       }
-
-       _sound(ball, CH_TRIGGER, self.noise, VOL_BASE, ATTEN_NONE);
-
-       if(ball.team && pscore)
-       {
-               if(nb_teams == 2 && pscore < 0)
-                       TeamScore_AddToTeam(otherteam, ST_NEXBALL_GOALS, -pscore);
-               else
-                       TeamScore_AddToTeam(ball.team, ST_NEXBALL_GOALS, pscore);
-       }
-       if(isclient)
-       {
-               if(pscore > 0)
-                       PlayerScore_Add(ball.pusher, SP_NEXBALL_GOALS, pscore);
-               else if(pscore < 0)
-                       PlayerScore_Add(ball.pusher, SP_NEXBALL_FAULTS, -pscore);
-       }
-
-       if(ball.owner)  // Happens on spawnflag GOAL_TOUCHPLAYER
-               DropBall(ball, ball.owner.origin, ball.owner.velocity);
-
-       WaypointSprite_Ping(ball.waypointsprite_attachedforcarrier);
-
-       ball.cnt = 1;
-       ball.think = ResetBall;
-       if(ball.classname == "nexball_basketball")
-               ball.touch = football_touch; // better than func_null: football control until the ball gets reset
-       ball.nextthink = time + autocvar_g_nexball_delay_goal * (self.team != GOAL_OUT);
-}
-
-//=======================//
-//        team ents       //
-//=======================//
-spawnfunc(nexball_team)
-{
-       if(!g_nexball)
-       {
-               remove(self);
-               return;
-       }
-       self.team = self.cnt + 1;
-}
-
-void nb_spawnteam(string teamname, float teamcolor)
-{
-       LOG_TRACE("^2spawned team ", teamname, "\n");
-       entity e;
-       e = spawn();
-       e.classname = "nexball_team";
-       e.netname = teamname;
-       e.cnt = teamcolor;
-       e.team = e.cnt + 1;
-       nb_teams += 1;
-}
-
-void nb_spawnteams(void)
-{
-       bool t_red = false, t_blue = false, t_yellow = false, t_pink = false;
-       entity e;
-       for(e = world; (e = find(e, classname, "nexball_goal"));)
-       {
-               switch(e.team)
-               {
-               case NUM_TEAM_1:
-                       if(!t_red)
-                       {
-                               nb_spawnteam("Red", e.team-1)   ;
-                               t_red = true;
-                       }
-                       break;
-               case NUM_TEAM_2:
-                       if(!t_blue)
-                       {
-                               nb_spawnteam("Blue", e.team-1)  ;
-                               t_blue = true;
-                       }
-                       break;
-               case NUM_TEAM_3:
-                       if(!t_yellow)
-                       {
-                               nb_spawnteam("Yellow", e.team-1);
-                               t_yellow = true;
-                       }
-                       break;
-               case NUM_TEAM_4:
-                       if(!t_pink)
-                       {
-                               nb_spawnteam("Pink", e.team-1)  ;
-                               t_pink = true;
-                       }
-                       break;
-               }
-       }
-}
-
-void nb_delayedinit(void)
-{
-       if(find(world, classname, "nexball_team") == world)
-               nb_spawnteams();
-       nb_ScoreRules(nb_teams);
-}
-
-
-//=======================//
-//       spawnfuncs       //
-//=======================//
-
-void SpawnBall(void)
-{SELFPARAM();
-       if(!g_nexball) { remove(self); return; }
-
-//     balls += 4; // using the remaining bits to count balls will leave more than the max edict count, so it's fine
-
-       if(self.model == "")
-       {
-               self.model = "models/nexball/ball.md3";
-               self.scale = 1.3;
-       }
-
-       precache_model(self.model);
-       _setmodel(self, self.model);
-       setsize(self, BALL_MINS, BALL_MAXS);
-       ball_scale = self.scale;
-
-       relocate_nexball();
-       self.spawnorigin = self.origin;
-
-       self.effects = self.effects | EF_LOWPRECISION;
-
-       if(cvar(strcat("g_", self.classname, "_trail")))  //nexball_basketball :p
-       {
-               self.glow_color = autocvar_g_nexball_trail_color;
-               self.glow_trail = true;
-       }
-
-       self.movetype = MOVETYPE_FLY;
-
-       if(!autocvar_g_nexball_sound_bounce)
-               self.noise = "";
-       else if(self.noise == "")
-               self.noise = SND(NB_BOUNCE);
-       //bounce sound placeholder (FIXME)
-       if(self.noise1 == "")
-               self.noise1 = SND(NB_DROP);
-       //ball drop sound placeholder (FIXME)
-       if(self.noise2 == "")
-               self.noise2 = SND(NB_STEAL);
-       //stealing sound placeholder (FIXME)
-       if(self.noise) precache_sound(self.noise);
-       precache_sound(self.noise1);
-       precache_sound(self.noise2);
-
-       WaypointSprite_AttachCarrier(WP_NbBall, self, RADARICON_FLAGCARRIER); // the ball's team is not set yet, no rule update needed
-
-       self.reset = ball_restart;
-       self.think = InitBall;
-       self.nextthink = game_starttime + autocvar_g_nexball_delay_start;
-}
-
-spawnfunc(nexball_basketball)
-{
-       nexball_mode |= NBM_BASKETBALL;
-       self.classname = "nexball_basketball";
-       if (!(balls & BALL_BASKET))
-       {
-               /*
-               CVTOV(g_nexball_basketball_effects_default);
-               CVTOV(g_nexball_basketball_delay_hold);
-               CVTOV(g_nexball_basketball_delay_hold_forteam);
-               CVTOV(g_nexball_basketball_teamsteal);
-               */
-               autocvar_g_nexball_basketball_effects_default = autocvar_g_nexball_basketball_effects_default & BALL_EFFECTMASK;
-       }
-       if(!self.effects)
-               self.effects = autocvar_g_nexball_basketball_effects_default;
-       self.solid = SOLID_TRIGGER;
-       balls |= BALL_BASKET;
-       self.bouncefactor = autocvar_g_nexball_basketball_bouncefactor;
-       self.bouncestop = autocvar_g_nexball_basketball_bouncestop;
-       SpawnBall();
-}
-
-spawnfunc(nexball_football)
-{
-       nexball_mode |= NBM_FOOTBALL;
-       self.classname = "nexball_football";
-       self.solid = SOLID_TRIGGER;
-       balls |= BALL_FOOT;
-       self.bouncefactor = autocvar_g_nexball_football_bouncefactor;
-       self.bouncestop = autocvar_g_nexball_football_bouncestop;
-       SpawnBall();
-}
-
-float nb_Goal_Customize()
-{SELFPARAM();
-       entity e, wp_owner;
-       e = WaypointSprite_getviewentity(other);
-       wp_owner = self.owner;
-       if(SAME_TEAM(e, wp_owner)) { return false; }
-
-       return true;
-}
-
-void SpawnGoal(void)
-{SELFPARAM();
-       if(!g_nexball) { remove(self); return; }
-
-       EXACTTRIGGER_INIT;
-
-       if(self.team != GOAL_OUT && Team_TeamToNumber(self.team) != -1)
-       {
-               entity wp = WaypointSprite_SpawnFixed(WP_NbGoal, (self.absmin + self.absmax) * 0.5, self, sprite, RADARICON_NONE);
-               wp.colormod = ((self.team) ? Team_ColorRGB(self.team) : '1 0.5 0');
-               self.sprite.customizeentityforclient = nb_Goal_Customize;
-       }
-
-       self.classname = "nexball_goal";
-       if(self.noise == "")
-               self.noise = "ctf/respawn.wav";
-       precache_sound(self.noise);
-       self.touch = GoalTouch;
-}
-
-spawnfunc(nexball_redgoal)
-{
-       self.team = NUM_TEAM_1;
-       SpawnGoal();
-}
-spawnfunc(nexball_bluegoal)
-{
-       self.team = NUM_TEAM_2;
-       SpawnGoal();
-}
-spawnfunc(nexball_yellowgoal)
-{
-       self.team = NUM_TEAM_3;
-       SpawnGoal();
-}
-spawnfunc(nexball_pinkgoal)
-{
-       self.team = NUM_TEAM_4;
-       SpawnGoal();
-}
-
-spawnfunc(nexball_fault)
-{
-       self.team = GOAL_FAULT;
-       if(self.noise == "")
-               self.noise = SND(TYPEHIT);
-       SpawnGoal();
-}
-
-spawnfunc(nexball_out)
-{
-       self.team = GOAL_OUT;
-       if(self.noise == "")
-               self.noise = SND(TYPEHIT);
-       SpawnGoal();
-}
-
-//
-//Spawnfuncs preserved for compatibility
-//
-
-spawnfunc(ball)
-{
-       spawnfunc_nexball_football(this);
-}
-spawnfunc(ball_football)
-{
-       spawnfunc_nexball_football(this);
-}
-spawnfunc(ball_basketball)
-{
-       spawnfunc_nexball_basketball(this);
-}
-// The "red goal" is defended by blue team. A ball in there counts as a point for red.
-spawnfunc(ball_redgoal)
-{
-       spawnfunc_nexball_bluegoal(this);       // I blame Revenant
-}
-spawnfunc(ball_bluegoal)
-{
-       spawnfunc_nexball_redgoal(this);        // but he didn't mean to cause trouble :p
-}
-spawnfunc(ball_fault)
-{
-       spawnfunc_nexball_fault(this);
-}
-spawnfunc(ball_bound)
-{
-       spawnfunc_nexball_out(this);
-}
-
-//=======================//
-//       Weapon code     //
-//=======================//
-
-
-void W_Nexball_Think()
-{SELFPARAM();
-       //dprint("W_Nexball_Think\n");
-       //vector new_dir = steerlib_arrive(self.enemy.origin, 2500);
-       vector new_dir = normalize(self.enemy.origin + '0 0 50' - self.origin);
-       vector old_dir = normalize(self.velocity);
-       float _speed = vlen(self.velocity);
-       vector new_vel = normalize(old_dir + (new_dir * autocvar_g_nexball_safepass_turnrate)) * _speed;
-       //vector new_vel = (new_dir * autocvar_g_nexball_safepass_turnrate
-
-       self.velocity = new_vel;
-
-       self.nextthink = time;
-}
-
-void W_Nexball_Touch(void)
-{SELFPARAM();
-       entity ball, attacker;
-       attacker = self.owner;
-       //self.think = func_null;
-       //self.enemy = world;
-
-       PROJECTILE_TOUCH;
-       if(attacker.team != other.team || autocvar_g_nexball_basketball_teamsteal)
-               if((ball = other.ballcarried) && !other.frozen && !other.deadflag && (IS_PLAYER(attacker)))
-               {
-                       other.velocity = other.velocity + normalize(self.velocity) * other.damageforcescale * autocvar_g_balance_nexball_secondary_force;
-                       other.flags &= ~FL_ONGROUND;
-                       if(!attacker.ballcarried)
-                       {
-                               LogNB("stole", attacker);
-                               _sound(other, CH_TRIGGER, ball.noise2, VOL_BASE, ATTEN_NORM);
-
-                               if(SAME_TEAM(attacker, other) && time > attacker.teamkill_complain)
-                               {
-                                       attacker.teamkill_complain = time + 5;
-                                       attacker.teamkill_soundtime = time + 0.4;
-                                       attacker.teamkill_soundsource = other;
-                               }
-
-                               GiveBall(attacker, other.ballcarried);
-                       }
-               }
-       remove(self);
-}
-
-void W_Nexball_Attack(float t)
-{SELFPARAM();
-       entity ball;
-       float mul, mi, ma;
-       if(!(ball = self.ballcarried))
-               return;
-
-       W_SetupShot(self, false, 4, SND(NB_SHOOT1), CH_WEAPON_A, 0);
-       tracebox(w_shotorg, BALL_MINS, BALL_MAXS, w_shotorg, MOVE_WORLDONLY, world);
-       if(trace_startsolid)
-       {
-               if(self.metertime)
-                       self.metertime = 0; // Shot failed, hide the power meter
-               return;
-       }
-
-       //Calculate multiplier
-       if(t < 0)
-               mul = 1;
-       else
-       {
-               mi = autocvar_g_nexball_basketball_meter_minpower;
-               ma = max(mi, autocvar_g_nexball_basketball_meter_maxpower); // avoid confusion
-               //One triangle wave period with 1 as max
-               mul = 2 * (t % g_nexball_meter_period) / g_nexball_meter_period;
-               if(mul > 1)
-                       mul = 2 - mul;
-               mul = mi + (ma - mi) * mul; // range from the minimal power to the maximal power
-       }
-
-       DropBall(ball, w_shotorg, W_CalculateProjectileVelocity(self.velocity, w_shotdir * autocvar_g_balance_nexball_primary_speed * mul, false));
-
-
-       //TODO: use the speed_up cvar too ??
-}
-
-void W_Nexball_Attack2(void)
-{SELFPARAM();
-       if(self.ballcarried.enemy)
-       {
-               entity _ball = self.ballcarried;
-               W_SetupShot(self, false, 4, SND(NB_SHOOT1), CH_WEAPON_A, 0);
-               DropBall(_ball, w_shotorg, trigger_push_calculatevelocity(_ball.origin, _ball.enemy, 32));
-               _ball.think = W_Nexball_Think;
-               _ball.nextthink = time;
-               return;
-       }
-
-       if(!autocvar_g_nexball_tackling)
-               return;
-
-       W_SetupShot(self, false, 2, SND(NB_SHOOT2), CH_WEAPON_A, 0);
-       entity missile = spawn();
-
-       missile.owner = self;
-       missile.classname = "ballstealer";
-
-       missile.movetype = MOVETYPE_FLY;
-       PROJECTILE_MAKETRIGGER(missile);
-
-       //setmodel(missile, "models/elaser.mdl");  // precision set below
-       setsize(missile, '0 0 0', '0 0 0');
-       setorigin(missile, w_shotorg);
-
-       W_SetupProjVelocity_Basic(missile, autocvar_g_balance_nexball_secondary_speed, 0);
-       missile.angles = vectoangles(missile.velocity);
-       missile.touch = W_Nexball_Touch;
-       missile.think = SUB_Remove;
-       missile.nextthink = time + autocvar_g_balance_nexball_secondary_lifetime; //FIXME: use a distance instead?
-
-       missile.effects = EF_BRIGHTFIELD | EF_LOWPRECISION;
-       missile.flags = FL_PROJECTILE;
-
-       CSQCProjectile(missile, true, PROJECTILE_ELECTRO, true);
-}
-
-float ball_customize()
-{SELFPARAM();
-       if(!self.owner)
-       {
-               self.effects &= ~EF_FLAME;
-               self.scale = 1;
-               self.customizeentityforclient = func_null;
-               return true;
-       }
-
-       if(other == self.owner)
-       {
-               self.scale = autocvar_g_nexball_viewmodel_scale;
-               if(self.enemy)
-                       self.effects |= EF_FLAME;
-               else
-                       self.effects &= ~EF_FLAME;
-       }
-       else
-       {
-               self.effects &= ~EF_FLAME;
-               self.scale = 1;
-       }
-
-       return true;
-}
-
-       METHOD(BallStealer, wr_think, void(BallStealer thiswep, entity actor, bool fire1, bool fire2))
-       {
-               if(fire1)
-                       if(weapon_prepareattack(thiswep, actor, false, autocvar_g_balance_nexball_primary_refire))
-                               if(autocvar_g_nexball_basketball_meter)
-                               {
-                                       if(self.ballcarried && !self.metertime)
-                                               self.metertime = time;
-                                       else
-                                               weapon_thinkf(actor, WFRAME_FIRE1, autocvar_g_balance_nexball_primary_animtime, w_ready);
-                               }
-                               else
-                               {
-                                       W_Nexball_Attack(-1);
-                                       weapon_thinkf(actor, WFRAME_FIRE1, autocvar_g_balance_nexball_primary_animtime, w_ready);
-                               }
-               if(fire2)
-                       if(weapon_prepareattack(thiswep, actor, true, autocvar_g_balance_nexball_secondary_refire))
-                       {
-                               W_Nexball_Attack2();
-                               weapon_thinkf(actor, WFRAME_FIRE2, autocvar_g_balance_nexball_secondary_animtime, w_ready);
-                       }
-
-               if(!fire1 && self.metertime && self.ballcarried)
-               {
-                       W_Nexball_Attack(time - self.metertime);
-                       // DropBall or stealing will set metertime back to 0
-                       weapon_thinkf(actor, WFRAME_FIRE1, autocvar_g_balance_nexball_primary_animtime, w_ready);
-               }
-       }
-       METHOD(BallStealer, wr_setup, void(BallStealer thiswep))
-       {
-               //weapon_setup(WEP_PORTO.m_id);
-       }
-       METHOD(BallStealer, wr_checkammo1, bool(BallStealer thiswep))
-       {
-               return true;
-       }
-       METHOD(BallStealer, wr_checkammo2, bool(BallStealer thiswep))
-       {
-               return true;
-       }
-
-MUTATOR_HOOKFUNCTION(nexball_BallDrop)
-{SELFPARAM();
-       if(self.ballcarried && g_nexball)
-               DropBall(self.ballcarried, self.origin, self.velocity);
-
-       return 0;
-}
-
-MUTATOR_HOOKFUNCTION(nexball_PlayerPreThink)
-{SELFPARAM();
-       makevectors(self.v_angle);
-       if(nexball_mode & NBM_BASKETBALL)
-       {
-               if(self.ballcarried)
-               {
-                       // 'view ball'
-                       self.ballcarried.velocity = self.velocity;
-                       self.ballcarried.customizeentityforclient = ball_customize;
-
-                       setorigin(self.ballcarried, self.origin + self.view_ofs +
-                                         v_forward * autocvar_g_nexball_viewmodel_offset.x +
-                                         v_right * autocvar_g_nexball_viewmodel_offset.y +
-                                         v_up * autocvar_g_nexball_viewmodel_offset.z);
-
-                       // 'safe passing'
-                       if(autocvar_g_nexball_safepass_maxdist)
-                       {
-                               if(self.ballcarried.wait < time && self.ballcarried.enemy)
-                               {
-                                       //centerprint(self, sprintf("Lost lock on %s", self.ballcarried.enemy.netname));
-                                       self.ballcarried.enemy = world;
-                               }
-
-
-                               //tracebox(self.origin + self.view_ofs, '-2 -2 -2', '2 2 2', self.origin + self.view_ofs + v_forward * autocvar_g_nexball_safepass_maxdist);
-                               crosshair_trace(self);
-                               if( trace_ent &&
-                                       IS_CLIENT(trace_ent) &&
-                                       trace_ent.deadflag == DEAD_NO &&
-                                       trace_ent.team == self.team &&
-                                       vlen(trace_ent.origin - self.origin) <= autocvar_g_nexball_safepass_maxdist )
-                               {
-
-                                       //if(self.ballcarried.enemy != trace_ent)
-                                       //      centerprint(self, sprintf("Locked to %s", trace_ent.netname));
-                                       self.ballcarried.enemy = trace_ent;
-                                       self.ballcarried.wait = time + autocvar_g_nexball_safepass_holdtime;
-
-
-                               }
-                       }
-               }
-               else
-               {
-                       if(self.weaponentity.weapons)
-                       {
-                               self.weapons = self.weaponentity.weapons;
-                               Weapon w = WEP_NEXBALL;
-                               w.wr_resetplayer(w);
-                               self.switchweapon = self.weaponentity.switchweapon;
-                               W_SwitchWeapon(self.switchweapon);
-
-               self.weaponentity.weapons = '0 0 0';
-                       }
-               }
-
-       }
-
-       nexball_setstatus();
-
-       return false;
-}
-
-MUTATOR_HOOKFUNCTION(nexball_PlayerSpawn)
-{SELFPARAM();
-       self.weaponentity.weapons = '0 0 0';
-
-       if(nexball_mode & NBM_BASKETBALL)
-               self.weapons |= WEPSET(NEXBALL);
-       else
-               self.weapons = '0 0 0';
-
-       return false;
-}
-
-MUTATOR_HOOKFUNCTION(nexball_PlayerPhysics)
-{SELFPARAM();
-       if(self.ballcarried)
-       {
-               self.stat_sv_airspeedlimit_nonqw *= autocvar_g_nexball_basketball_carrier_highspeed;
-               self.stat_sv_maxspeed *= autocvar_g_nexball_basketball_carrier_highspeed;
-       }
-       return false;
-}
-
-MUTATOR_HOOKFUNCTION(nexball_ForbidThrowing)
-{SELFPARAM();
-       if(self.weapon == WEP_NEXBALL.m_id)
-               return true;
-
-       return false;
-}
-
-MUTATOR_HOOKFUNCTION(nexball_FilterItem)
-{SELFPARAM();
-       if(self.classname == "droppedweapon")
-       if(self.weapon == WEP_NEXBALL.m_id)
-               return true;
-
-       return false;
-}
-
-MUTATOR_DEFINITION(gamemode_nexball)
-{
-       MUTATOR_HOOK(PlayerDies, nexball_BallDrop, CBC_ORDER_ANY);
-       MUTATOR_HOOK(MakePlayerObserver, nexball_BallDrop, CBC_ORDER_ANY);
-       MUTATOR_HOOK(ClientDisconnect, nexball_BallDrop, CBC_ORDER_ANY);
-       MUTATOR_HOOK(PlayerSpawn, nexball_PlayerSpawn, CBC_ORDER_ANY);
-       MUTATOR_HOOK(PlayerPreThink, nexball_PlayerPreThink, CBC_ORDER_ANY);
-       MUTATOR_HOOK(PlayerPhysics, nexball_PlayerPhysics, CBC_ORDER_ANY);
-       MUTATOR_HOOK(ForbidThrowCurrentWeapon, nexball_ForbidThrowing, CBC_ORDER_ANY);
-       MUTATOR_HOOK(FilterItem, nexball_FilterItem, CBC_ORDER_ANY);
-
-       MUTATOR_ONADD
-       {
-               g_nexball_meter_period = autocvar_g_nexball_meter_period;
-               if(g_nexball_meter_period <= 0)
-                       g_nexball_meter_period = 2; // avoid division by zero etc. due to silly users
-               g_nexball_meter_period = rint(g_nexball_meter_period * 32) / 32; //Round to 1/32ths to send as a byte multiplied by 32
-               addstat(STAT_NB_METERSTART, AS_FLOAT, metertime);
-
-               // General settings
-               /*
-               CVTOV(g_nexball_football_boost_forward);   //100
-               CVTOV(g_nexball_football_boost_up);             //200
-               CVTOV(g_nexball_delay_idle);                       //10
-               CVTOV(g_nexball_football_physics);               //0
-               */
-               radar_showennemies = autocvar_g_nexball_radar_showallplayers;
-
-               InitializeEntity(world, nb_delayedinit, INITPRIO_GAMETYPE);
-               WEP_NEXBALL.spawnflags &= ~WEP_FLAG_MUTATORBLOCKED;
-       }
-
-       MUTATOR_ONROLLBACK_OR_REMOVE
-       {
-               WEP_NEXBALL.spawnflags |= WEP_FLAG_MUTATORBLOCKED;
-               // we actually cannot roll back nb_delayedinit here
-               // BUT: we don't need to! If this gets called, adding always
-               // succeeds.
-       }
-
-       MUTATOR_ONREMOVE
-       {
-               LOG_INFO("This is a game type and it cannot be removed at runtime.");
-               return -1;
-       }
-
-       return 0;
-}
diff --git a/qcsrc/server/mutators/gamemode_nexball.qh b/qcsrc/server/mutators/gamemode_nexball.qh
deleted file mode 100644 (file)
index e28fad8..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-#ifndef GAMEMODE_NEXBALL_H
-#define GAMEMODE_NEXBALL_H
-
-//EF_BRIGHTFIELD|EF_BRIGHTLIGHT|EF_DIMLIGHT|EF_BLUE|EF_RED|EF_FLAME
-const float BALL_EFFECTMASK = 1229;
-const vector BALL_MINS = '-16 -16 -16'; // The model is 24*24*24
-const vector BALL_MAXS = '16 16 16';
-const vector BALL_ATTACHORG = '3 0 16';
-const float BALL_FOOT = 1;
-const float BALL_BASKET = 2;
-//spawnflags
-const float GOAL_TOUCHPLAYER = 1;
-//goal types
-const float GOAL_FAULT = -1;
-const float GOAL_OUT = -2;
-
-void DropBall(entity ball, vector org, vector vel);
-float autocvar_g_nexball_football_boost_forward;
-float autocvar_g_nexball_football_boost_up;
-float autocvar_g_nexball_football_physics;
-float autocvar_g_nexball_delay_idle;
-float autocvar_g_nexball_basketball_delay_hold;
-float autocvar_g_nexball_basketball_delay_hold_forteam;
-float autocvar_g_nexball_basketball_effects_default;
-float autocvar_g_nexball_basketball_teamsteal;
-float autocvar_g_nexball_meter_period;
-
-float balls;
-float ball_scale;
-float nb_teams;
-
-.entity nb_dropper;
-.float nb_droptime;
-
-.float teamtime;
-#endif
diff --git a/qcsrc/server/mutators/gamemode_nexball_weapon.qc b/qcsrc/server/mutators/gamemode_nexball_weapon.qc
deleted file mode 100644 (file)
index ae882bb..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef GAMEMODE_NEXBALL_WEAPON_H
-#define GAMEMODE_NEXBALL_WEAPON_H
-
-CLASS(BallStealer, PortoLaunch)
-/* flags     */ ATTRIB(BallStealer, spawnflags, int, WEP_TYPE_OTHER | WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
-/* impulse   */ ATTRIB(BallStealer, impulse, int, 0);
-/* refname   */ ATTRIB(BallStealer, netname, string, "ballstealer");
-/* wepname   */ ATTRIB(BallStealer, message, string, _("Ball Stealer"));
-ENDCLASS(BallStealer)
-REGISTER_WEAPON(NEXBALL, NEW(BallStealer));
-
-#endif
index e0415af3c18df308a986b9afc3454714812e235e..8b2e223c041fe0756db6072621e04e73dccb162a 100644 (file)
@@ -1,9 +1,10 @@
-#include "../_all.qh"
 
 #include "gamemode.qh"
 #include "../controlpoint.qh"
 #include "../generator.qh"
 
+void FixSize(entity e);
+
 // =======================
 // CaptureShield Functions
 // =======================
@@ -553,6 +554,8 @@ void ons_ControlPoint_Icon_BuildThink()
                Send_Effect(EFFECT_RAGE, self.origin + 10 * randomvec(), '0 0 -1', 1);
 }
 
+void onslaught_controlpoint_icon_link(entity e, void() spawnproc);
+
 void ons_ControlPoint_Icon_Spawn(entity cp, entity player)
 {
        entity e = spawn();
index d51b33ec2f3eb048de0bafd1a809398e664d26e0..271456986d393461bbd21f00030bff8092abda33 100644 (file)
@@ -1,5 +1,4 @@
 #include "gamemode_race.qh"
-#include "../_all.qh"
 
 #include "gamemode.qh"
 
index 451e4a55c32536d35ac84ec33b1b0add8dde0bec..2ff647db0ac0d0b202da97fb9f0dc8dc6ab28f11 100644 (file)
@@ -1,4 +1,3 @@
-#include "../_all.qh"
 
 #include "gamemode.qh"
 
index 8721a2d678bf3571f67d22283878c777c7879526..e8054bc0442bc3efa2ae451298c9bacaaa23c8f4 100644 (file)
@@ -38,8 +38,8 @@
 
 #include "../../common/monsters/all.qh"
 
-#include "../../warpzonelib/anglestransform.qh"
-#include "../../warpzonelib/server.qh"
-#include "../../warpzonelib/util_server.qh"
+#include "../../lib/warpzone/anglestransform.qh"
+#include "../../lib/warpzone/server.qh"
+#include "../../lib/warpzone/util_server.qh"
 
 #endif
index 6c50612a91a8e96ae409b1e66923ca2cb1ac4230..1e54218840ca09679af39d9108c80c27ff9b8d6c 100644 (file)
@@ -1,4 +1,3 @@
-#include "../_all.qh"
 
 #include "mutator.qh"
 
index 149b3d761da4b3e7bf0d7aedcb962529836f0455..3f75e3f9946f42cf9418c6f1bc8c6190ab4ad56a 100644 (file)
@@ -1,3 +1,6 @@
+#include "../../common/deathtypes/all.qh"
+#include "../g_hook.qh"
+
 REGISTER_MUTATOR(bh, cvar("g_breakablehook"));
 
 bool autocvar_g_breakablehook; // allow toggling mid match?
index cc176b27af4166050da1c6ed6fd396d9fd9498f4..7c24ea14f205bfc76ccee0e2213ec4fd2b5a2a21 100644 (file)
@@ -1,9 +1,9 @@
 #include "../../common/triggers/target/music.qh"
 #include "mutator_buffs.qh"
-#include "../_all.qh"
 
 #include "mutator.qh"
 
+#include "../../common/gamemodes/all.qh"
 #include "../../common/buffs/all.qh"
 
 entity buff_FirstFromFlags(int _buffs)
@@ -527,6 +527,10 @@ MUTATOR_HOOKFUNCTION(buffs_PlayerSpawn)
        return false;
 }
 
+.float stat_sv_maxspeed;
+.float stat_sv_airspeedlimit_nonqw;
+.float stat_sv_jumpvelocity;
+
 MUTATOR_HOOKFUNCTION(buffs_PlayerPhysics)
 {SELFPARAM();
        if(self.buffs & BUFF_SPEED.m_itemid)
index 3b04c43cc132a2b53259610c9b1e509ae35a84b9..4acc7540502ef433d30e830c6c2ee3ce529ca0d1 100644 (file)
@@ -1,4 +1,3 @@
-#include "../_all.qh"
 
 #include "mutator.qh"
 
index b5dc32fdfe0d924a233b099ab47f802eaceba6e3..e9dd6fd73ca75e0da2cc44c7a5d1fdeee588f338 100644 (file)
 
 #ifdef SVQC
 #include "mutator_dodging.qh"
-#include "../_all.qh"
 
 #include "mutator.qh"
 
 #include "../../common/animdecide.qh"
+#include "../../common/physics.qh"
 
 .float cvar_cl_dodging_timeout;
 
diff --git a/qcsrc/server/mutators/mutator_instagib.qc b/qcsrc/server/mutators/mutator_instagib.qc
deleted file mode 100644 (file)
index f6c85d9..0000000
+++ /dev/null
@@ -1,495 +0,0 @@
-#include "../_all.qh"
-
-#include "mutator.qh"
-
-#include "../cl_client.qh"
-#include "../../common/buffs/all.qh"
-
-#include "../../common/items/all.qc"
-
-spawnfunc(item_minst_cells)
-{
-       if (!g_instagib) { remove(self); return; }
-       if (!self.ammo_cells) self.ammo_cells = autocvar_g_instagib_ammo_drop;
-       StartItemA(ITEM_VaporizerCells);
-}
-
-void instagib_invisibility()
-{SELFPARAM();
-       self.strength_finished = autocvar_g_balance_powerup_strength_time;
-       StartItemA(ITEM_Invisibility);
-}
-
-void instagib_extralife()
-{SELFPARAM();
-       self.max_health = 1;
-       StartItemA(ITEM_ExtraLife);
-}
-
-void instagib_speed()
-{SELFPARAM();
-       self.invincible_finished = autocvar_g_balance_powerup_invincible_time;
-       StartItemA(ITEM_Speed);
-}
-
-.float instagib_nextthink;
-.float instagib_needammo;
-void instagib_stop_countdown(entity e)
-{
-       if (!e.instagib_needammo)
-               return;
-       Kill_Notification(NOTIF_ONE_ONLY, e, MSG_CENTER_CPID, CPID_INSTAGIB_FINDAMMO);
-       e.instagib_needammo = false;
-}
-void instagib_ammocheck()
-{SELFPARAM();
-       if(time < self.instagib_nextthink)
-               return;
-       if(!IS_PLAYER(self))
-               return; // not a player
-
-       if(self.deadflag || gameover)
-               instagib_stop_countdown(self);
-       else if (self.ammo_cells > 0 || (self.items & IT_UNLIMITED_WEAPON_AMMO) || (self.flags & FL_GODMODE))
-               instagib_stop_countdown(self);
-       else if(autocvar_g_rm && autocvar_g_rm_laser)
-       {
-               if(!self.instagib_needammo)
-               {
-                       Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_INSTAGIB_DOWNGRADE);
-                       self.instagib_needammo = true;
-               }
-       }
-       else
-       {
-               self.instagib_needammo = true;
-               if (self.health <= 5)
-               {
-                       Damage(self, self, self, 5, DEATH_NOAMMO.m_id, self.origin, '0 0 0');
-                       Send_Notification(NOTIF_ONE, self, MSG_ANNCE, ANNCE_INSTAGIB_TERMINATED);
-               }
-               else if (self.health <= 10)
-               {
-                       Damage(self, self, self, 5, DEATH_NOAMMO.m_id, self.origin, '0 0 0');
-                       Send_Notification(NOTIF_ONE, self, MSG_ANNCE, ANNCE_NUM_1);
-               }
-               else if (self.health <= 20)
-               {
-                       Damage(self, self, self, 10, DEATH_NOAMMO.m_id, self.origin, '0 0 0');
-                       Send_Notification(NOTIF_ONE, self, MSG_ANNCE, ANNCE_NUM_2);
-               }
-               else if (self.health <= 30)
-               {
-                       Damage(self, self, self, 10, DEATH_NOAMMO.m_id, self.origin, '0 0 0');
-                       Send_Notification(NOTIF_ONE, self, MSG_ANNCE, ANNCE_NUM_3);
-               }
-               else if (self.health <= 40)
-               {
-                       Damage(self, self, self, 10, DEATH_NOAMMO.m_id, self.origin, '0 0 0');
-                       Send_Notification(NOTIF_ONE, self, MSG_ANNCE, ANNCE_NUM_4);
-               }
-               else if (self.health <= 50)
-               {
-                       Damage(self, self, self, 10, DEATH_NOAMMO.m_id, self.origin, '0 0 0');
-                       Send_Notification(NOTIF_ONE, self, MSG_ANNCE, ANNCE_NUM_5);
-               }
-               else if (self.health <= 60)
-               {
-                       Damage(self, self, self, 10, DEATH_NOAMMO.m_id, self.origin, '0 0 0');
-                       Send_Notification(NOTIF_ONE, self, MSG_ANNCE, ANNCE_NUM_6);
-               }
-               else if (self.health <= 70)
-               {
-                       Damage(self, self, self, 10, DEATH_NOAMMO.m_id, self.origin, '0 0 0');
-                       Send_Notification(NOTIF_ONE, self, MSG_ANNCE, ANNCE_NUM_7);
-               }
-               else if (self.health <= 80)
-               {
-                       Damage(self, self, self, 10, DEATH_NOAMMO.m_id, self.origin, '0 0 0');
-                       Send_Notification(NOTIF_ONE, self, MSG_ANNCE, ANNCE_NUM_8);
-               }
-               else if (self.health <= 90)
-               {
-                       Send_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER, CENTER_INSTAGIB_FINDAMMO);
-                       Damage(self, self, self, 10, DEATH_NOAMMO.m_id, self.origin, '0 0 0');
-                       Send_Notification(NOTIF_ONE, self, MSG_ANNCE, ANNCE_NUM_9);
-               }
-               else
-               {
-                       Send_Notification(NOTIF_ONE_ONLY, self, MSG_MULTI, MULTI_INSTAGIB_FINDAMMO);
-                       Damage(self, self, self, 10, DEATH_NOAMMO.m_id, self.origin, '0 0 0');
-               }
-       }
-       self.instagib_nextthink = time + 1;
-}
-
-MUTATOR_HOOKFUNCTION(instagib_MatchEnd)
-{
-       entity head;
-       FOR_EACH_PLAYER(head)
-               instagib_stop_countdown(head);
-
-       return false;
-}
-
-MUTATOR_HOOKFUNCTION(instagib_MonsterLoot)
-{
-       other.monster_loot = spawnfunc_item_minst_cells;
-
-       return false;
-}
-
-MUTATOR_HOOKFUNCTION(instagib_MonsterSpawn)
-{SELFPARAM();
-       // always refill ammo
-       if(self.monsterid == MON_MAGE.monsterid)
-               self.skin = 1;
-
-       return false;
-}
-
-MUTATOR_HOOKFUNCTION(instagib_BotShouldAttack)
-{
-       if (checkentity.items & ITEM_Invisibility.m_itemid)
-               return true;
-
-       return false;
-}
-
-MUTATOR_HOOKFUNCTION(instagib_MakePlayerObserver)
-{SELFPARAM();
-       instagib_stop_countdown(self);
-       return false;
-}
-
-MUTATOR_HOOKFUNCTION(instagib_PlayerSpawn)
-{SELFPARAM();
-       self.effects |= EF_FULLBRIGHT;
-       return false;
-}
-
-MUTATOR_HOOKFUNCTION(instagib_PlayerPreThink)
-{
-       instagib_ammocheck();
-       return false;
-}
-
-MUTATOR_HOOKFUNCTION(instagib_PlayerRegen)
-{
-       // no regeneration in instagib
-       return true;
-}
-
-MUTATOR_HOOKFUNCTION(instagib_PlayerPowerups)
-{SELFPARAM();
-       if (!(self.effects & EF_FULLBRIGHT))
-               self.effects |= EF_FULLBRIGHT;
-
-       if (self.items & ITEM_Invisibility.m_itemid)
-       {
-               play_countdown(self.strength_finished, SND(POWEROFF));
-               if (time > self.strength_finished)
-               {
-                       self.alpha = default_player_alpha;
-                       self.exteriorweaponentity.alpha = default_weapon_alpha;
-                       self.items &= ~ITEM_Invisibility.m_itemid;
-                       Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_POWERDOWN_INVISIBILITY);
-               }
-       }
-       else
-       {
-               if (time < self.strength_finished)
-               {
-                       self.alpha = autocvar_g_instagib_invis_alpha;
-                       self.exteriorweaponentity.alpha = autocvar_g_instagib_invis_alpha;
-                       self.items |= ITEM_Invisibility.m_itemid;
-                       Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_POWERUP_INVISIBILITY, self.netname);
-                       Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_POWERUP_INVISIBILITY);
-               }
-       }
-
-       if (self.items & ITEM_Speed.m_itemid)
-       {
-               play_countdown(self.invincible_finished, SND(POWEROFF));
-               if (time > self.invincible_finished)
-               {
-                       self.items &= ~ITEM_Speed.m_itemid;
-                       Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_POWERDOWN_SPEED);
-               }
-       }
-       else
-       {
-               if (time < self.invincible_finished)
-               {
-                       self.items |= ITEM_Speed.m_itemid;
-                       Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_POWERUP_SPEED, self.netname);
-                       Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_POWERUP_SPEED);
-               }
-       }
-       return false;
-}
-
-MUTATOR_HOOKFUNCTION(instagib_PlayerPhysics)
-{SELFPARAM();
-       if(self.items & ITEM_Speed.m_itemid)
-               self.stat_sv_maxspeed = self.stat_sv_maxspeed * autocvar_g_instagib_speed_highspeed;
-
-       return false;
-}
-
-MUTATOR_HOOKFUNCTION(instagib_SplitHealthArmor)
-{
-       damage_save = 0;
-       damage_take = frag_damage;
-
-       return false;
-}
-
-MUTATOR_HOOKFUNCTION(instagib_ForbidThrowing)
-{
-       // weapon dropping on death handled by FilterItem
-
-       return true;
-}
-
-MUTATOR_HOOKFUNCTION(instagib_PlayerDamage)
-{
-       if(autocvar_g_friendlyfire == 0 && SAME_TEAM(frag_target, frag_attacker) && IS_PLAYER(frag_target) && IS_PLAYER(frag_attacker))
-               frag_damage = 0;
-
-       if(IS_PLAYER(frag_target))
-       {
-               if(frag_deathtype == DEATH_FALL.m_id)
-                       frag_damage = 0; // never count fall damage
-
-               if(!autocvar_g_instagib_damagedbycontents)
-               switch(DEATH_ENT(frag_deathtype))
-               {
-                       case DEATH_DROWN:
-                       case DEATH_SLIME:
-                       case DEATH_LAVA:
-                               frag_damage = 0;
-                               break;
-               }
-
-               if(IS_PLAYER(frag_attacker))
-               if(DEATH_ISWEAPON(frag_deathtype, WEP_VAPORIZER))
-               {
-                       if(frag_target.armorvalue)
-                       {
-                               frag_target.armorvalue -= 1;
-                               frag_damage = 0;
-                               frag_target.damage_dealt += 1;
-                               frag_attacker.damage_dealt += 1; // TODO: change this to a specific hitsound for armor hit
-                               Send_Notification(NOTIF_ONE, frag_target, MSG_CENTER, CENTER_INSTAGIB_LIVES_REMAINING, frag_target.armorvalue);
-                       }
-               }
-
-               if(IS_PLAYER(frag_attacker) && DEATH_ISWEAPON(frag_deathtype, WEP_BLASTER))
-               {
-                       if(frag_deathtype & HITTYPE_SECONDARY)
-                       {
-                               if(!autocvar_g_instagib_blaster_keepdamage)
-                                       frag_damage = frag_mirrordamage = 0;
-
-                               if(frag_target != frag_attacker)
-                               {
-                                       if(frag_damage <= 0 && frag_target.health > 0) { Send_Notification(NOTIF_ONE, frag_attacker, MSG_CENTER, CENTER_SECONDARY_NODAMAGE); }
-                                       if(!autocvar_g_instagib_blaster_keepforce)
-                                               frag_force = '0 0 0';
-                               }
-                       }
-               }
-       }
-
-       if(IS_PLAYER(frag_attacker))
-       if(frag_mirrordamage > 0)
-       {
-               // just lose extra LIVES, don't kill the player for mirror damage
-               if(frag_attacker.armorvalue > 0)
-               {
-                       frag_attacker.armorvalue -= 1;
-                       Send_Notification(NOTIF_ONE, frag_attacker, MSG_CENTER, CENTER_INSTAGIB_LIVES_REMAINING, frag_attacker.armorvalue);
-                       frag_attacker.damage_dealt += frag_mirrordamage;
-               }
-               frag_mirrordamage = 0;
-       }
-
-       if((frag_target.buffs & BUFF_INVISIBLE.m_itemid) || (frag_target.items & ITEM_Invisibility.m_itemid))
-               yoda = 1;
-
-       return false;
-}
-
-MUTATOR_HOOKFUNCTION(instagib_SetStartItems)
-{
-       start_health       = warmup_start_health       = 100;
-       start_armorvalue   = warmup_start_armorvalue   = 0;
-
-       start_ammo_shells  = warmup_start_ammo_shells  = 0;
-       start_ammo_nails   = warmup_start_ammo_nails   = 0;
-       start_ammo_cells   = warmup_start_ammo_cells   = cvar("g_instagib_ammo_start");
-       start_ammo_plasma  = warmup_start_ammo_plasma  = 0;
-       start_ammo_rockets = warmup_start_ammo_rockets = 0;
-       start_ammo_fuel    = warmup_start_ammo_fuel    = 0;
-
-       start_weapons = warmup_start_weapons = WEPSET(VAPORIZER);
-       start_items |= IT_UNLIMITED_SUPERWEAPONS;
-
-       return false;
-}
-
-MUTATOR_HOOKFUNCTION(instagib_FilterItem)
-{SELFPARAM();
-       if(self.classname == "item_cells")
-               return true; // no normal cells?
-
-       if(self.weapon == WEP_VAPORIZER.m_id && self.classname == "droppedweapon")
-       {
-               self.ammo_cells = autocvar_g_instagib_ammo_drop;
-               return false;
-       }
-
-       if(self.weapon == WEP_DEVASTATOR.m_id || self.weapon == WEP_VORTEX.m_id)
-       {
-               entity e = spawn();
-               setorigin(e, self.origin);
-               e.noalign = self.noalign;
-        e.cnt = self.cnt;
-        e.team = self.team;
-               WITH(entity, self, e, spawnfunc_item_minst_cells(e));
-               return true;
-       }
-
-       if(self.flags & FL_POWERUP)
-               return false;
-
-       if(self.ammo_cells > autocvar_g_instagib_ammo_drop && self.classname != "item_minst_cells")
-               self.ammo_cells = autocvar_g_instagib_ammo_drop;
-
-       if(self.ammo_cells && !self.weapon)
-               return false;
-
-       return true;
-}
-
-MUTATOR_HOOKFUNCTION(instagib_CustomizeWaypoint)
-{SELFPARAM();
-       entity e = WaypointSprite_getviewentity(other);
-
-       // if you have the invisibility powerup, sprites ALWAYS are restricted to your team
-       // but only apply this to real players, not to spectators
-       if((self.owner.flags & FL_CLIENT) && (self.owner.items & ITEM_Invisibility.m_itemid) && (e == other))
-       if(DIFF_TEAM(self.owner, e))
-               return true;
-
-       return false;
-}
-
-MUTATOR_HOOKFUNCTION(instagib_PlayerDies)
-{
-       if(DEATH_ISWEAPON(frag_deathtype, WEP_VAPORIZER))
-               frag_damage = 1000; // always gib if it was a vaporizer death
-
-       return FALSE;
-}
-
-MUTATOR_HOOKFUNCTION(instagib_ItemTouch)
-{SELFPARAM();
-       if(self.ammo_cells)
-       {
-               // play some cool sounds ;)
-               if (IS_CLIENT(other))
-               {
-                       if(other.health <= 5)
-                               Send_Notification(NOTIF_ONE, other, MSG_ANNCE, ANNCE_INSTAGIB_LASTSECOND);
-                       else if(other.health < 50)
-                               Send_Notification(NOTIF_ONE, other, MSG_ANNCE, ANNCE_INSTAGIB_NARROWLY);
-               }
-
-               if(other.health < 100)
-                       other.health = 100;
-
-               return MUT_ITEMTOUCH_CONTINUE;
-       }
-
-       if(self.max_health)
-       {
-               other.armorvalue = bound(other.armorvalue, 999, other.armorvalue + autocvar_g_instagib_extralives);
-               Send_Notification(NOTIF_ONE, other, MSG_CENTER, CENTER_EXTRALIVES);
-               return MUT_ITEMTOUCH_PICKUP;
-       }
-
-       return MUT_ITEMTOUCH_CONTINUE;
-}
-
-MUTATOR_HOOKFUNCTION(instagib_OnEntityPreSpawn)
-{SELFPARAM();
-       if (!autocvar_g_powerups) { return false; }
-       // Can't use .itemdef here
-       if (!(self.classname == "item_strength" || self.classname == "item_invincible" || self.classname == "item_health_mega"))
-               return false;
-
-       entity e = spawn();
-
-       float r = random();
-       if (r < 0.3)
-               e.think = instagib_invisibility;
-       else if (r < 0.6)
-               e.think = instagib_extralife;
-       else
-               e.think = instagib_speed;
-
-       e.nextthink = time + 0.1;
-       e.spawnflags = self.spawnflags;
-       e.noalign = self.noalign;
-       setorigin(e, self.origin);
-
-       return true;
-}
-
-MUTATOR_HOOKFUNCTION(instagib_BuildMutatorsString)
-{
-       ret_string = strcat(ret_string, ":instagib");
-       return false;
-}
-
-MUTATOR_HOOKFUNCTION(instagib_BuildMutatorsPrettyString)
-{
-       ret_string = strcat(ret_string, ", instagib");
-       return false;
-}
-
-MUTATOR_HOOKFUNCTION(instagib_SetModname)
-{
-       modname = "instagib";
-       return true;
-}
-
-MUTATOR_DEFINITION(mutator_instagib)
-{
-       MUTATOR_HOOK(MatchEnd, instagib_MatchEnd, CBC_ORDER_ANY);
-       MUTATOR_HOOK(MonsterDropItem, instagib_MonsterLoot, CBC_ORDER_ANY);
-       MUTATOR_HOOK(MonsterSpawn, instagib_MonsterSpawn, CBC_ORDER_ANY);
-       MUTATOR_HOOK(BotShouldAttack, instagib_BotShouldAttack, CBC_ORDER_ANY);
-       MUTATOR_HOOK(PlayerPhysics, instagib_PlayerPhysics, CBC_ORDER_ANY);
-       MUTATOR_HOOK(PlayerSpawn, instagib_PlayerSpawn, CBC_ORDER_ANY);
-       MUTATOR_HOOK(PlayerDamage_Calculate, instagib_PlayerDamage, CBC_ORDER_ANY);
-       MUTATOR_HOOK(MakePlayerObserver, instagib_MakePlayerObserver, CBC_ORDER_ANY);
-       MUTATOR_HOOK(SetStartItems, instagib_SetStartItems, CBC_ORDER_ANY);
-       MUTATOR_HOOK(ItemTouch, instagib_ItemTouch, CBC_ORDER_ANY);
-       MUTATOR_HOOK(FilterItem, instagib_FilterItem, CBC_ORDER_ANY);
-       MUTATOR_HOOK(CustomizeWaypoint, instagib_CustomizeWaypoint, CBC_ORDER_ANY);
-       MUTATOR_HOOK(PlayerDies, instagib_PlayerDies, CBC_ORDER_ANY);
-       MUTATOR_HOOK(PlayerDamage_SplitHealthArmor, instagib_SplitHealthArmor, CBC_ORDER_ANY);
-       MUTATOR_HOOK(PlayerPowerups, instagib_PlayerPowerups, CBC_ORDER_ANY);
-       MUTATOR_HOOK(ForbidThrowCurrentWeapon, instagib_ForbidThrowing, CBC_ORDER_ANY);
-       MUTATOR_HOOK(PlayerPreThink, instagib_PlayerPreThink, CBC_ORDER_ANY);
-       MUTATOR_HOOK(PlayerRegen, instagib_PlayerRegen, CBC_ORDER_ANY);
-       MUTATOR_HOOK(OnEntityPreSpawn, instagib_OnEntityPreSpawn, CBC_ORDER_ANY);
-       MUTATOR_HOOK(BuildMutatorsString, instagib_BuildMutatorsString, CBC_ORDER_ANY);
-       MUTATOR_HOOK(BuildMutatorsPrettyString, instagib_BuildMutatorsPrettyString, CBC_ORDER_ANY);
-       MUTATOR_HOOK(SetModname, instagib_SetModname, CBC_ORDER_ANY);
-
-       return false;
-}
diff --git a/qcsrc/server/mutators/mutator_instagib_items.qc b/qcsrc/server/mutators/mutator_instagib_items.qc
deleted file mode 100644 (file)
index 87abd78..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-#include "../../common/items/item.qh"
-
-float instagib_respawntime_ammo = 45;
-float instagib_respawntimejitter_ammo = 0;
-GETTER(float, instagib_respawntime_ammo)
-GETTER(float, instagib_respawntimejitter_ammo)
-
-#ifndef MENUQC
-MODEL(VaporizerCells_ITEM, Item_Model("a_cells.md3"));
-#endif
-
-REGISTER_ITEM(VaporizerCells, Ammo) {
-#ifndef MENUQC
-    this.m_model                =   MDL_VaporizerCells_ITEM;
-#endif
-    this.m_sound                =   "misc/itempickup.wav";
-    this.m_name                 =   "Vaporizer Ammo";
-    this.m_icon                 =   "ammo_supercells";
-#ifdef SVQC
-    this.m_botvalue             =   100;
-    this.m_itemid               =   IT_CELLS;
-    this.m_respawntime          =   GET(instagib_respawntime_ammo);
-    this.m_respawntimejitter    =   GET(instagib_respawntimejitter_ammo);
-#endif
-}
-
-#ifndef MENUQC
-MODEL(ExtraLife_ITEM, Item_Model("g_h100.md3"));
-#endif
-
-REGISTER_ITEM(ExtraLife, Powerup) {
-#ifndef MENUQC
-    this.m_model                =   MDL_ExtraLife_ITEM;
-#endif
-    this.m_sound                =   "misc/megahealth.wav";
-    this.m_name                 =   "Extra life";
-    this.m_icon                 =   "item_mega_health";
-    this.m_color                =   '1 0 0';
-    this.m_waypoint             =   _("Extra life");
-    this.m_waypointblink        =   2;
-    this.m_itemid               =   IT_NAILS;
-}
-
-#ifndef MENUQC
-MODEL(Invisibility_ITEM, Item_Model("g_strength.md3"));
-#endif
-
-REGISTER_ITEM(Invisibility, Powerup) {
-#ifndef MENUQC
-    this.m_model            =   MDL_Invisibility_ITEM;
-#endif
-    this.m_sound            =   "misc/powerup.wav";
-    this.m_name             =   "Invisibility";
-    this.m_icon             =   "strength";
-    this.m_color            =   '0 0 1';
-    this.m_waypoint         =   _("Invisibility");
-    this.m_waypointblink    =   2;
-    this.m_itemid           =   IT_STRENGTH;
-}
-
-#ifndef MENUQC
-MODEL(Speed_ITEM, Item_Model("g_invincible.md3"));
-#endif
-
-REGISTER_ITEM(Speed, Powerup) {
-#ifndef MENUQC
-    this.m_model            =   MDL_Speed_ITEM;
-#endif
-    this.m_sound            =   "misc/powerup_shield.wav";
-    this.m_name             =   "Speed";
-    this.m_icon             =   "shield";
-    this.m_color            =   '1 0 1';
-    this.m_waypoint         =   _("Speed");
-    this.m_waypointblink    =   2;
-    this.m_itemid           =   IT_INVINCIBLE;
-}
index e7c066afc3030117e399628344e43f45acc74c96..2855a074f765a07d16f842d357b39332046c3278 100644 (file)
@@ -1,4 +1,3 @@
-#include "../_all.qh"
 
 #include "mutator.qh"
 
index fb8aac419f881c97b3e453122c36ad7ebb77de76..019eeb8017af87f196e5c100a9fdb0f0f50e44c2 100644 (file)
@@ -1,4 +1,3 @@
-#include "../_all.qh"
 
 #include "mutator.qh"
 
index 3ac73031713d92d47be9d605f5472cf1bbd3ea3b..33ae58f4dd0fefb485d01b03f6bd9208c93af2c8 100644 (file)
@@ -1,4 +1,3 @@
-#include "../_all.qh"
 
 #include "mutator.qh"
 
index 04e60bb83ec490cc6ebad1483a0642dfefff4fef..de6296d820dbb9996891ee4541b8f29ab3b57feb 100644 (file)
@@ -1,8 +1,8 @@
 #ifdef SVQC
-       #include "../_all.qh"
        #include "mutator.qh"
        #include "../antilag.qh"
 #endif
+#include "../../common/physics.qh"
 
 .int multijump_count;
 .bool multijump_ready;
index ec5a649ddf02d5fe4b73767de5cca972e1e52974..40e07b1ea81a387fcfc0e2a04964cb87fab529b0 100644 (file)
@@ -1,13 +1,14 @@
 #include "mutator_nades.qh"
-#include "../_all.qh"
 
 #include "mutator.qh"
 
 #include "gamemode_keyhunt.qh"
 #include "gamemode_freezetag.qh"
 #include "../../common/nades/all.qh"
+#include "../../common/gamemodes/all.qh"
 #include "../../common/monsters/spawn.qh"
 #include "../../common/monsters/sv_monsters.qh"
+#include "../g_subs.qh"
 
 .float nade_time_primed;
 
index 9b51d9abb8640fbcaf4f3bbcf5ef83d5f652f760..93b64ebcc69258094d5b29dfe02b848f33362b4a 100644 (file)
@@ -1,4 +1,3 @@
-#include "../_all.qh"
 
 #include "mutator.qh"
 
index 5339d319ec558c63aab46f745fe68dcb7bdd0031..2a26d9326be9a15742479ad9337ce3b04cd409f5 100644 (file)
@@ -1,4 +1,3 @@
-#include "../_all.qh"
 
 #include "mutator.qh"
 
index d5b59d26ad9b31cc940d023c63abfb5563592db4..5d1a9cd06dac86590ea3c94940ca29ae5210c5a9 100644 (file)
@@ -1,5 +1,4 @@
 #include "mutator_overkill.qh"
-#include "../_all.qh"
 
 #include "mutator.qh"
 
index 144a8d2eaa099871a0ff8b62431463cd68045896..d1272319ee2959d690dfd1dd0472904bf629b80c 100644 (file)
@@ -1,4 +1,3 @@
-#include "../_all.qh"
 
 #include "mutator.qh"
 
index 71262b923df8ca18e4ff4a6b36ab7d18cb46f30f..4c450a85cd392136f4305ec838dabfb0d860a7e5 100644 (file)
@@ -1,4 +1,3 @@
-#include "../_all.qh"
 
 #include "mutator.qh"
 
index 060ed74f831dfe53cbe47ab6fe500b2450b9d28f..ff85f29059d01c892d1f7ae7c2fe3a0211ffd02e 100644 (file)
@@ -1,4 +1,3 @@
-#include "../_all.qh"
 
 #include "mutator.qh"
 
index 5f684b353191f84bc45a150fb34b3609974b24e1..c403e9f9ca47d1335d39de0ee05f67cc9204357d 100644 (file)
@@ -1,4 +1,3 @@
-#include "../_all.qh"
 
 #include "mutator.qh"
 
index 7f333d9dfc30e2fce6d7b5007cc8984b3b54e416..b7319cf3e9e510f1d320360213623b0df29bc136 100644 (file)
@@ -1,3 +1,6 @@
+#include "../../common/deathtypes/all.qh"
+#include "../round_handler.qh"
+
 REGISTER_MUTATOR(rm, cvar("g_instagib"));
 
 MUTATOR_HOOKFUNCTION(rm, PlayerDamage_Calculate)
index e3178b338874f9892eb174afdffa6800e2c3c8a7..c996f1a12c0146112a1f51eb04aa094da34def6b 100644 (file)
@@ -1,4 +1,3 @@
-#include "../_all.qh"
 
 #include "mutator.qh"
 
index 32e81319dfe87dda5d6eeaa680aed00836bd77ae..e0b5ad35dc63387a86d2c57ff993808d8be90910 100644 (file)
@@ -1,4 +1,3 @@
-#include "../_all.qh"
 
 #include "mutator.qh"
 
index baf41dedbf8414003fd5c002539c642f4060897f..e0dd4cd67e8dc434036ca04cf51b579aa53a59bf 100644 (file)
@@ -1,4 +1,3 @@
-#include "../_all.qh"
 
 #include "mutator.qh"
 
index 6b2859f440b17ec46b042e8d850c51f0fb231eb1..b5cad57aefbd37e854ebf37fdbeb5fe79b96a83e 100644 (file)
@@ -1,4 +1,3 @@
-#include "../_all.qh"
 
 #include "mutator.qh"
 
index 0c63015320dc2c2d0b217a8c7aad403cf3ce4f48..93fc4cf70e52540512250f8f1822bed5cbc32a4b 100644 (file)
@@ -1,7 +1,6 @@
 #if defined(CSQC)
 #elif defined(MENUQC)
 #elif defined(SVQC)
-       #include "../../dpdefs/progsdefs.qh"
     #include "mutators_include.qh"
     #include "../../common/mapinfo.qh"
 #endif
@@ -15,7 +14,6 @@ void mutators_add()
        CHECK_MUTATOR_ADD("g_spawn_near_teammate", mutator_spawn_near_teammate, teamplay);
        CHECK_MUTATOR_ADD("g_physical_items", mutator_physical_items, 1);
        CHECK_MUTATOR_ADD("g_touchexplode", mutator_touchexplode, 1);
-       CHECK_MUTATOR_ADD("g_instagib", mutator_instagib, !g_nexball);
        CHECK_MUTATOR_ADD("g_invincible_projectiles", mutator_invincibleprojectiles, 1);
        CHECK_MUTATOR_ADD("g_new_toys", mutator_new_toys, !cvar("g_instagib") && !cvar("g_overkill"));
        CHECK_MUTATOR_ADD("g_nix", mutator_nix, !cvar("g_instagib") && !cvar("g_overkill"));
index e1355a447b63087ab9f96716a865574900008ab5..b65cbd2e78af93afb62de4774398faef922b2f2d 100644 (file)
@@ -7,7 +7,6 @@ MUTATOR_DECLARATION(gamemode_keyhunt);
 MUTATOR_DECLARATION(gamemode_freezetag);
 MUTATOR_DECLARATION(gamemode_keepaway);
 MUTATOR_DECLARATION(gamemode_ctf);
-MUTATOR_DECLARATION(gamemode_nexball);
 MUTATOR_DECLARATION(gamemode_onslaught);
 MUTATOR_DECLARATION(gamemode_domination);
 MUTATOR_DECLARATION(gamemode_lms);
@@ -26,7 +25,6 @@ MUTATOR_DECLARATION(mutator_spawn_near_teammate);
 MUTATOR_DECLARATION(mutator_physical_items);
 MUTATOR_DECLARATION(mutator_vampire);
 MUTATOR_DECLARATION(mutator_superspec);
-MUTATOR_DECLARATION(mutator_instagib);
 MUTATOR_DECLARATION(mutator_touchexplode);
 MUTATOR_DECLARATION(mutator_pinata);
 MUTATOR_DECLARATION(mutator_midair);
index d5e47c62f845cecd29cff0afd1de0e151a6c21e3..d2ea4688f0a06ccfcf534882a532df7f5e877bf9 100644 (file)
@@ -1,12 +1,10 @@
 #if defined(CSQC)
 #elif defined(MENUQC)
 #elif defined(SVQC)
-    #include "../../dpdefs/progsdefs.qh"
-    #include "../../dpdefs/dpextensions.qh"
-    #include "../../warpzonelib/anglestransform.qh"
-    #include "../../warpzonelib/common.qh"
-    #include "../../warpzonelib/util_server.qh"
-    #include "../../warpzonelib/server.qh"
+    #include "../../lib/warpzone/anglestransform.qh"
+    #include "../../lib/warpzone/common.qh"
+    #include "../../lib/warpzone/util_server.qh"
+    #include "../../lib/warpzone/server.qh"
     #include "../../common/constants.qh"
     #include "../../common/stats.qh"
     #include "../../common/teams.qh"
@@ -54,8 +52,8 @@
     #include "../command/cmd.qh"
     #include "../command/sv_cmd.qh"
     #include "../../common/csqcmodel_settings.qh"
-    #include "../../csqcmodellib/common.qh"
-    #include "../../csqcmodellib/sv_model.qh"
+    #include "../../lib/csqcmodel/common.qh"
+    #include "../../lib/csqcmodel/sv_model.qh"
     #include "../anticheat.qh"
     #include "../cheats.qh"
     #include "../../common/playerstats.qh"
@@ -87,7 +85,6 @@
 #include "gamemode_keepaway.qc"
 #include "gamemode_keyhunt.qc"
 #include "gamemode_lms.qc"
-#include "gamemode_nexball.qc"
 #include "gamemode_onslaught.qc"
 #include "gamemode_race.qc"
 #include "gamemode_tdm.qc"
@@ -98,7 +95,6 @@
 #include "mutator_campcheck.qc"
 #include "mutator_dodging.qc"
 #include "mutator_hook.qc"
-#include "mutator_instagib.qc"
 #include "mutator_invincibleproj.qc"
 #include "mutator_melee_only.qc"
 #include "mutator_midair.qc"
index dcd29447637062b42eb156c2de525bf5f934b29c..e7144bcd3ef5194fa26793d39d422f98b5536cb3 100644 (file)
@@ -13,7 +13,6 @@
 #include "gamemode_keepaway.qh"
 #include "gamemode_keyhunt.qh"
 #include "gamemode_lms.qh"
-#include "gamemode_nexball.qh"
 #include "gamemode_onslaught.qh"
 #include "gamemode_race.qh"
 
index ed3ffc5e77dfe6c3cd90afdcdad0e8bf2475a3d4..7a52f0c6961d9531b7f25cbc0ffbddd9e21b3f62 100644 (file)
@@ -1,4 +1,3 @@
-#include "../_all.qh"
 
 #include "mutator.qh"
 
diff --git a/qcsrc/server/pathlib/_all.inc b/qcsrc/server/pathlib/_all.inc
new file mode 100644 (file)
index 0000000..1b15654
--- /dev/null
@@ -0,0 +1,11 @@
+#define DEBUGPATHING
+
+#include "costs.qc"
+#include "expandnode.qc"
+#include "main.qc"
+#include "movenode.qc"
+#include "path_waypoint.qc"
+#include "utility.qc"
+#ifdef DEBUGPATHING
+       #include "debug.qc"
+#endif
index 37e167aae71064e0b87c927aaf8f730058b92e0b..434f50b8641bcb3aeeb3f8a76efc1e0ee17c4b13 100644 (file)
@@ -51,7 +51,6 @@ void pathlib_showpath2(entity path)
     path.nextthink = time;
 }
 
-
 void pathlib_showsquare2(entity node ,vector ncolor,float align)
 {
 
index f097e8a0fec8199dabff0c0501307ab768bfe703..800f0335ef85ea3305b6ec1f60ccfb824ac67540 100644 (file)
@@ -1,4 +1,3 @@
-#include "../_all.qh"
 
 #include "pathlib.qh"
 #include "utility.qh"
@@ -27,6 +26,14 @@ void dumpnode(entity n)
     n.nextthink    = time;
 }
 
+#ifdef DEBUGPATHING
+void pathlib_showpath(entity start);
+void pathlib_showpath2(entity path);
+#endif
+
+void pathlib_showsquare(vector where,float goodsquare,float _lifetime);
+void pathlib_showsquare2(entity node ,vector ncolor,float align);
+
 entity pathlib_mknode(vector where,entity parent)
 {
     entity node;
index 6645d712661d9a08e5c95be125f41073d526f783..e3bcac61e4f289d2b54d8cd581e737baff7898d6 100644 (file)
@@ -1,8 +1,9 @@
-#include "../_all.qh"
 
 #include "pathlib.qh"
 #include "utility.qh"
 
+.vector        pos1, pos2;
+
 vector pathlib_wateroutnode(vector start,vector end, float doedge)
 {SELFPARAM();
     vector surface;
index dbf785266ae67a266a1b9d9c4f66ebac245fc60c..d88a43ed8e14fc2f6ad8bfad91214a7805e5e132 100644 (file)
@@ -13,7 +13,6 @@ const vector PLIB_FORWARD = '0 1 0';
 const vector PLIB_RIGHT = '1 0 0';
 //#define PLIB_LEFT    '-1 0 0'
 
-#define DEBUGPATHING
 #ifdef DEBUGPATHING
 void pathlib_showpath(entity start);
 void pathlib_showpath2(entity path);
@@ -109,8 +108,4 @@ var float  buildpath_nodefilter(vector n,vector c,vector p);
 
 var float  pathlib_wpp_waypointcallback(entity wp, entity wp_prev);
 
-#ifdef DEBUGPATHING
-       #include "debug.qc"
-#endif
-
 #endif
index b21ed2ea37ef988c03ca9363462ad38738ee84b2..082356ae2d86084f2b8ad8d6ffe624f9e9a43936 100644 (file)
@@ -1,8 +1,6 @@
 #if defined(CSQC)
 #elif defined(MENUQC)
 #elif defined(SVQC)
-       #include "../dpdefs/progsdefs.qh"
-    #include "../dpdefs/dpextensions.qh"
     #include "defs.qh"
     #include "playerdemo.qh"
 #endif
index 5132db5729817769657dae6f79c77e4c22c539f7..ca6442f979dff6515ea38f24018fb89afbdc917f 100644 (file)
@@ -1,5 +1,4 @@
 #include "portals.qh"
-#include "_all.qh"
 
 #include "g_hook.qh"
 #include "mutators/mutators_include.qh"
@@ -10,9 +9,12 @@
 #include "../common/triggers/subs.qh"
 #include "../common/util.qh"
 #include "../common/weapons/all.qh"
-#include "../csqcmodellib/sv_model.qh"
-#include "../warpzonelib/anglestransform.qh"
-#include "../warpzonelib/util_server.qh"
+#include "../lib/csqcmodel/sv_model.qh"
+#include "../lib/warpzone/anglestransform.qh"
+#include "../lib/warpzone/util_server.qh"
+#include "../lib/warpzone/common.qh"
+#include "../common/vehicles/vehicle.qh"
+#include "../common/vehicles/sv_vehicles.qh"
 
 #define PORTALS_ARE_NOT_SOLID
 
index d4a4f17125bb73503bc7df31ebd2a79806325168..ece94bdbefb6ca0d67a5b29309cbbe976b0108cf 100644 (file)
@@ -1,11 +1,5 @@
-#include "../common/util-pre.qh"
-#include "sys-pre.qh"
-#include "../dpdefs/progsdefs.qh"
-#include "../dpdefs/dpextensions.qh"
-#include "sys-post.qh"
-#include "../common/util-post.qh"
-
 #include "../lib/_all.inc"
+#include "_all.qh"
 
 #include "anticheat.qc"
 #include "antilag.qc"
 #include "t_quake3.qc"
 #include "t_quake.qc"
 
-#include "bot/aim.qc"
-#include "bot/bot.qc"
-#include "bot/navigation.qc"
-#include "bot/scripting.qc"
-#include "bot/waypoints.qc"
-
-#include "bot/havocbot/havocbot.qc"
-#include "bot/havocbot/role_keyhunt.qc"
-#include "bot/havocbot/roles.qc"
+#include "bot/_all.inc"
 
 #include "command/all.qc"
 
 #include "mutators/mutators_include.qc"
 #include "mutators/mutators.qc"
 
-#include "pathlib/costs.qc"
-#include "pathlib/expandnode.qc"
-#include "pathlib/main.qc"
-#include "pathlib/movenode.qc"
-#include "pathlib/path_waypoint.qc"
-#include "pathlib/utility.qc"
+#include "pathlib/_all.inc"
 
 #include "weapons/accuracy.qc"
 #include "weapons/common.qc"
@@ -81,7 +62,6 @@
 #include "../common/animdecide.qc"
 #include "../common/campaign_file.qc"
 #include "../common/campaign_setup.qc"
-#include "../common/effects/effects.qc"
 #include "../common/effects/effectinfo.qc"
 #include "../common/mapinfo.qc"
 #include "../common/monsters/spawn.qc"
@@ -99,6 +79,8 @@
 
 #include "../common/deathtypes/all.qc"
 #include "../common/buffs/all.qc"
+#include "../common/effects/all.qc"
+#include "../common/gamemodes/all.qc"
 #include "../common/items/all.qc"
 #include "../common/monsters/all.qc"
 #include "../common/mutators/all.qc"
 #include "../common/turrets/targettrigger.qc"
 #include "../common/weapons/config.qc"
 
-#include "../csqcmodellib/sv_model.qc"
+#include "../lib/csqcmodel/sv_model.qc"
 
-#include "../warpzonelib/anglestransform.qc"
-#include "../warpzonelib/common.qc"
-#include "../warpzonelib/server.qc"
-#include "../warpzonelib/util_server.qc"
+#include "../lib/warpzone/anglestransform.qc"
+#include "../lib/warpzone/common.qc"
+#include "../lib/warpzone/server.qc"
+#include "../lib/warpzone/util_server.qc"
 
 #if BUILD_MOD
 #include "../../mod/server/progs.inc"
index 8f9dccf91a24f3ae0e5e8ea77cbda4f0ca79d437..94f3100a40cb7bd76d9d4f710d5e98586e3573c8 100644 (file)
@@ -1,5 +1,4 @@
 #include "race.qh"
-#include "_all.qh"
 
 #include "cl_client.qh"
 #include "portals.qh"
 #include "../common/deathtypes/all.qh"
 #include "../common/notifications.qh"
 #include "../common/mapinfo.qh"
-#include "../warpzonelib/util_server.qh"
+#include "../common/triggers/subs.qh"
+#include "../lib/warpzone/util_server.qh"
+#include "../lib/warpzone/common.qh"
+#include "../common/mutators/mutator/waypoints/waypointsprites.qh"
 
 void W_Porto_Fail(float failhard);
 
index 0d608f9af76268de54d415746ca813e2b965453c..e6a1334f88426fec87ff6b2a95ae312391dcfd24 100644 (file)
@@ -1,5 +1,4 @@
 #include "round_handler.qh"
-#include "_all.qh"
 
 #include "command/vote.qh"
 #include "../common/util.qh"
index 14893b12d8a9d3140da373415fc4b35871fdf56d..bb489f76fc72a2c74073a0ae387f3bd001fd1d37 100644 (file)
@@ -1,5 +1,4 @@
 #include "scores.qh"
-#include "_all.qh"
 
 #include "command/common.qh"
 #include "mutators/mutators_include.qh"
index aefb1754b5ceaab137e2e4d1bb13fa4fa2a3374f..07d7267910cc7391e3e79deccdd4a1416289b4ec 100644 (file)
@@ -1,5 +1,4 @@
 #include "scores_rules.qh"
-#include "_all.qh"
 
 #include "cl_client.qh"
 #include "scores.qh"
index 09d914a3c86751b7f0d6bbc97e49c8277575e560..6980a9e9439d59a0c6a53b72d94065e2244c0ee1 100644 (file)
@@ -1,13 +1,14 @@
 #include "spawnpoints.qh"
-#include "_all.qh"
 
 #include "mutators/mutators_include.qh"
 #include "g_world.qh"
 #include "race.qh"
 #include "../common/constants.qh"
 #include "../common/teams.qh"
+#include "../common/triggers/subs.qh"
 #include "../common/util.qh"
-#include "../warpzonelib/util_server.qh"
+#include "../lib/warpzone/common.qh"
+#include "../lib/warpzone/util_server.qh"
 
 bool SpawnPoint_Send(entity this, entity to, int sf)
 {
index fbf84da32be0b06fb2a16d0ae2f790bdc5fcb9da..4941b5521b7122b5ef534f7371e011291eb827a4 100644 (file)
@@ -1,8 +1,6 @@
 #if defined(CSQC)
 #elif defined(MENUQC)
 #elif defined(SVQC)
-    #include "../dpdefs/progsdefs.qh"
-    #include "../dpdefs/dpextensions.qh"
 #endif
 
 /**
index 43118d926477145a3043aae80e10e9e9d271277b..0a9d8f21014dab6571af9b9deb818ae0d7ed1702 100644 (file)
@@ -1,4 +1,3 @@
-#include "_all.qh"
 
 #include "anticheat.qh"
 #include "g_hook.qh"
 #include "../common/vehicles/all.qh"
 #include "../common/weapons/all.qh"
 
-#include "../csqcmodellib/sv_model.qh"
+#include "../lib/csqcmodel/sv_model.qh"
 
-#include "../warpzonelib/common.qh"
-#include "../warpzonelib/server.qh"
+#include "../lib/warpzone/common.qh"
+#include "../lib/warpzone/server.qh"
 
 .float lastground;
+.int state;
 
 void CreatureFrame (void)
 {SELFPARAM();
index a540e0ec5b8386179ea1cddecf196600fefd196e..d30a54f020f8d48f4a8399ff22926243ce05da6f 100644 (file)
@@ -3,7 +3,6 @@
 #include "../common/items/all.qc"
 
 #if defined(SVQC)
-    #include "_all.qh"
 
     #include "bot/bot.qh"
     #include "bot/waypoints.qh"
@@ -24,7 +23,7 @@
 
     #include "../common/weapons/all.qh"
 
-    #include "../warpzonelib/util_server.qh"
+    #include "../lib/warpzone/util_server.qh"
 #endif
 
 #ifdef CSQC
index dd79b1788f2b14fbf451b5b4ee01f16d1f2ea3c6..8195d250d023b4e528cb40bfd67d272fde8392c0 100644 (file)
@@ -1,47 +1,6 @@
 #ifndef T_ITEMS_H
 #define T_ITEMS_H
 
-// constants
-const int IT_UNLIMITED_WEAPON_AMMO             =       1; // when this bit is set, using a weapon does not reduce ammo. Checkpoints can give this powerup.
-const int IT_UNLIMITED_SUPERWEAPONS            =       2; // when this bit is set, superweapons don't expire. Checkpoints can give this powerup.
-const int IT_CTF_SHIELDED                      =       4; // set for the flag shield
-const int IT_USING_JETPACK                     =       8; // confirmation that button is pressed
-const int IT_JETPACK                           =      16; // actual item
-const int IT_FUEL_REGEN                        =      32; // fuel regeneration trigger
-// where is 64... ?
-const int IT_FUEL                                      =     128;
-// -Wdouble-declaration
-#define IT_SHELLS                                        256
-// -Wdouble-declaration
-#define IT_NAILS                                         512
-// -Wdouble-declaration
-#define IT_ROCKETS                                      1024
-// -Wdouble-declaration
-#define IT_CELLS                                        2048
-const int IT_SUPERWEAPON                               =    4096;
-const int IT_STRENGTH                                  =    8192;
-const int IT_INVINCIBLE                                =   16384;
-const int IT_HEALTH                                    =   32768;
-const int IT_PLASMA                                    =   65536;
-
-// shared value space (union):
-       // for items:
-       // -Wdouble-declaration
-       #define IT_KEY1                                                 131072
-       // -Wdouble-declaration
-       #define IT_KEY2                                                 262144
-// end
-
-const int IT_5HP                               =  524288;
-const int IT_25HP                              = 1048576;
-const int IT_ARMOR_SHARD                       = 2097152;
-const int IT_ARMOR                             = 4194304;
-
-// item masks
-const int IT_AMMO                              =    3968; // IT_FUEL | IT_SHELLS | IT_NAILS | IT_ROCKETS | IT_CELLS | IT_PLASMA;
-const int IT_PICKUPMASK                        =      51; // IT_FUEL_REGEN | IT_JETPACK | IT_UNLIMITED_AMMO; // strength and invincible are handled separately
-const int IT_UNLIMITED_AMMO                    =       3; // IT_UNLIMITED_SUPERWEAPONS | IT_UNLIMITED_WEAPON_AMMO;
-
 const int AMMO_COUNT = 4; // amount of ammo types to show in the inventory panel
 
 // item networking
@@ -65,6 +24,10 @@ const int ISF_SIZE                           = 128;
 .float fade_start;
 .float fade_end;
 
+#ifdef SVQC
+void StartItemA (entity a);
+#endif
+
 #ifdef CSQC
 
 float  autocvar_cl_animate_items = 1;
index 9e22b8d06542ddf2236c4cb2a5ba57dbbbe9e546..29de5d4c71a530623e0e938e291bf0976c618574 100644 (file)
@@ -1,4 +1,3 @@
-#include "_all.qh"
 
 #include "../common/weapons/all.qh"
 
index c8f595761d0b6e03ad911b66cb6f1c7080f1b82a..94663fc36534a93502fc0f6816a2d13da945417d 100644 (file)
@@ -1,4 +1,3 @@
-#include "_all.qh"
 
 #include "../common/weapons/all.qh"
 #include "../common/buffs/all.qh"
@@ -65,6 +64,9 @@ spawnfunc(item_armor_combat)   { spawnfunc_item_armor_big(this);      }
 spawnfunc(item_armor_shard)    { spawnfunc_item_armor_small(this);    }
 spawnfunc(item_enviro)         { spawnfunc_item_invincible(this);     }
 
+.float wait;
+.float delay;
+
 // weapon remove ent from df
 void target_init_verify()
 {
index ff7b63a14e25b4243a173d5414176a79288d3c57..5a9d2ee3b999f5989482d0375fad17c4c8ca8502 100644 (file)
@@ -1,5 +1,4 @@
 #include "teamplay.qh"
-#include "_all.qh"
 
 #include "cl_client.qh"
 #include "race.qh"
@@ -13,6 +12,7 @@
 #include "mutators/mutators_include.qh"
 
 #include "../common/deathtypes/all.qh"
+#include "../common/gamemodes/all.qh"
 #include "../common/teams.qh"
 
 void TeamchangeFrags(entity e)
index 3ce05ac2a66c2d24ab50dc74b91a94c61d6d156a..5664d261daa1a6b26376899369562fe9abc51132 100644 (file)
@@ -9,6 +9,8 @@ string cache_lastmutatormsg;
 // # of bots on those teams
 float cb1, cb2, cb3, cb4;
 
+int redowned, blueowned, yellowowned, pinkowned;
+
 //float audit_teams_time;
 
 void TeamchangeFrags(entity e);
index 09f155ecbd7ea68052a953e1f713c560f0d829b4..baa95c64952ffd34b0fcc56d5da4e0bb6062cb21 100644 (file)
@@ -1,5 +1,4 @@
 #include "accuracy.qh"
-#include "../_all.qh"
 
 #include "../mutators/mutators_include.qh"
 #include "../../common/constants.qh"
index 0f1fa9080286dc8094d2f4e0d03dd8906e2d9dc7..5a5e30bf79c11c92cd217c5e006bf0d399a92c73 100644 (file)
@@ -1,5 +1,4 @@
 #include "common.qh"
-#include "../_all.qh"
 
 #include "../t_items.qh"
 #include "../../common/constants.qh"
@@ -7,6 +6,7 @@
 #include "../../common/notifications.qh"
 #include "../../common/util.qh"
 #include "../../common/weapons/all.qh"
+#include "../../common/items/all.qc"
 
 void W_GiveWeapon (entity e, float wep)
 {SELFPARAM();
index ca98ad10b8bc3837d29651542795ec1ba20e4a7f..1e254b804e13e2b2c28bc73db985d237ba733a79 100644 (file)
@@ -1,5 +1,4 @@
 #include "csqcprojectile.qh"
-#include "../_all.qh"
 
 #include "../t_items.qh"
 
index 065edf1b1478661e197562cf4f3e413c61e9d704..ec48c6d3cea09c19bb6498cc9f1c47691c7aad4c 100644 (file)
@@ -1,7 +1,7 @@
 #include "hitplot.qh"
-#include "../_all.qh"
 
 #include "../antilag.qh"
+#include "../g_subs.qh"
 #include "../../common/weapons/all.qh"
 
 vector W_HitPlotUnnormalizedUntransform(vector screenforward, vector screenright, vector screenup, vector v)
@@ -79,7 +79,7 @@ void W_HitPlotAnalysis(entity player, vector screenforward, vector screenright,
 
 void W_HitPlotOpen(entity player)
 {
-       if(autocvar_g_hitplots || strstrofs(strcat(" ", autocvar_g_hitplots_individuals, " "), strcat(" ", player.netaddress, " "), 0) >= 0)
+       if(autocvar_g_hitplots || strhasword(autocvar_g_hitplots_individuals, player.netaddress))
        {
                player.hitplotfh = fopen(strcat("hits-", matchid, "-", player.netaddress, "-", ftos(player.playerid), ".plot"), FILE_WRITE);
                fputs(player.hitplotfh, strcat("#name ", player.netname, "\n"));
index ce2a671c4584f9290ea9a67d93b985c102f11179..b7eb2fe097e0e169d3cf6a1f9177c0292701dc6c 100644 (file)
@@ -1,11 +1,12 @@
 #include "selection.qh"
-#include "../_all.qh"
 
 #include "weaponsystem.qh"
 #include "../t_items.qh"
 #include "../../common/constants.qh"
 #include "../../common/util.qh"
+#include "../../common/items/item.qh"
 #include "../../common/weapons/all.qh"
+#include "../../common/mutators/mutator/waypoints/waypointsprites.qh"
 
 // switch between weapons
 void Send_WeaponComplain(entity e, float wpn, float type)
index b011bb1fffd3e9c1fd5d3318d0765edd1bc26da7..be2ca6b50f0c6d734d1903aa9470c6d19f1bb291 100644 (file)
@@ -1,5 +1,4 @@
 #include "spawning.qh"
-#include "../_all.qh"
 
 #include "weaponsystem.qh"
 #include "../mutators/mutators_include.qh"
index a649cf75b9858ee2d84ce74ce6e1b857e021a522..83025da9a859869669381fc26167a9fadef66f8b 100644 (file)
@@ -1,12 +1,13 @@
 #include "throwing.qh"
-#include "../_all.qh"
 
 #include "weaponsystem.qh"
 #include "../mutators/mutators_include.qh"
 #include "../t_items.qh"
 #include "../g_damage.qh"
+#include "../../common/items/item.qh"
 #include "../../common/mapinfo.qh"
 #include "../../common/notifications.qh"
+#include "../../common/triggers/subs.qh"
 #include "../../common/util.qh"
 #include "../../common/weapons/all.qh"
 
index 69821aaaf6d84f42f79055407747e6f521e14d8c..4c9e0e34cf02ce30a1524cdaa7452e72acffaba2 100644 (file)
@@ -1,9 +1,9 @@
 #include "tracing.qh"
-#include "../_all.qh"
 
 #include "accuracy.qh"
 #include "common.qh"
 #include "hitplot.qh"
+#include "weaponsystem.qh"
 
 #include "../g_damage.qh"
 #include "../g_subs.qh"
@@ -14,7 +14,7 @@
 
 #include "../../common/weapons/all.qh"
 
-#include "../../warpzonelib/common.qh"
+#include "../../lib/warpzone/common.qh"
 
 // this function calculates w_shotorg and w_shotdir based on the weapon model
 // offset, trueaim and antilag, and won't put w_shotorg inside a wall.
index 6701f5829a25839ba5e353d7deaaaee12cae8aa2..ce1fb6100cfe6c8d16d5117b860ad30f515a8340 100644 (file)
@@ -1,5 +1,4 @@
 #include "weaponstats.qh"
-#include "../_all.qh"
 
 #include "../g_world.qh"
 
index ae76b36b662901661a8cdb172126bfd4c21f015d..dd7e2b59935ceed86ffdc7b24f3d2ac039e774fa 100644 (file)
@@ -1,5 +1,4 @@
 #include "weaponsystem.qh"
-#include "../_all.qh"
 
 #include "selection.qh"
 
@@ -13,7 +12,7 @@
 #include "../../common/notifications.qh"
 #include "../../common/util.qh"
 #include "../../common/weapons/all.qh"
-#include "../../csqcmodellib/sv_model.qh"
+#include "../../lib/csqcmodel/sv_model.qh"
 
 /*
 ===========================================================================
@@ -24,6 +23,8 @@
 ===========================================================================
 */
 
+.int state;
+
 .float weapon_frametime;
 
 float W_WeaponRateFactor()
index e4f387861da3b0bbaae25215c95c29e4c3656ba8..66cf5c57668175008f6547c2341b475f715ca9a1 100755 (executable)
@@ -4,30 +4,35 @@ cd "$(dirname "$0")"
 cd ..
 
 declare -a NOWARN=(
-  '-Wno-field-redeclared'
-  '-Wno-unused-variable'
-  '-Wno-implicit-function-pointer'
+  -Wno-field-redeclared
+  -Wno-unused-variable
+  -Wno-implicit-function-pointer
 )
 declare -a FEATURES=(
-  '-DVEHICLES_ENABLED=1'
-  '-DVEHICLES_USE_ODE=0'
+  -DVEHICLES_ENABLED=1
+  -DVEHICLES_USE_ODE=0
 )
 declare QCC=../../../gmqcc/gmqcc
 
+declare -a QCC_FLAGS=(
+  -std=gmqcc
+  -Wall -Werror
+  -fftepp -fftepp-predefs -Wcpp
+  -futf8
+  -freturn-assignments
+  -frelaxed-switch
+  -O3
+)
+
 function check() {
-  declare -l base="$1"
-  declare -la predefs=("${!2}")
-  find "$base" -type f -name '*.qc' -print0 | sort -z | while IFS= read -r -d '' file; do
+  declare -l base="${1}"
+  declare -la predefs=("-D${2}" "lib/_all.inc" "${base}/_all.qh")
+  find "$base" -type f -name '*.qc' -print0 | sort -z | while read -r -d '' file; do
     echo "$file"
-    ${QCC} -std=gmqcc -fftepp -fftepp-predefs -Werror -Wall "${NOWARN[@]}" "${FEATURES[@]}" -futf8 -O3 "${predefs[@]}" "$file" >/dev/null
+    ${QCC} "${QCC_FLAGS[@]}" "${NOWARN[@]}" "${FEATURES[@]}" "${predefs[@]}" "$file" >/dev/null
   done
 }
 
-clientdefs=("-DCSQC" "common/util-pre.qh" "dpdefs/csprogsdefs.qh")
-check "client" clientdefs[@]
-
-serverdefs=("-DSVQC" "common/util-pre.qh" "server/sys-pre.qh" "dpdefs/progsdefs.qh" "dpdefs/dpextensions.qh" "server/sys-post.qh" "server/defs.qh" "server/autocvars.qh")
-check "server" serverdefs[@]
-
-menudefs=("-DMENUQC" "common/util-pre.qh" "dpdefs/menudefs.qh")
-check "menu" menudefs[@]
+check client CSQC
+check server SVQC
+check menu MENUQC
diff --git a/qcsrc/warpzonelib/COPYING b/qcsrc/warpzonelib/COPYING
deleted file mode 100644 (file)
index d61ba0a..0000000
+++ /dev/null
@@ -1,369 +0,0 @@
-The code in this directory is dual-licensed MIT and GPLv2 "or any later version".
-
-
-
-MIT license:
-
-Copyright (c) 2010 Rudolf Polzer
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of
-this software and associated documentation files (the "Software"), to deal in
-the Software without restriction, including without limitation the rights to
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
-of the Software, and to permit persons to whom the Software is furnished to do
-so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-
-
-
-GPL v2:
-
-                   GNU GENERAL PUBLIC LICENSE
-                      Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-                           Preamble
-
-  The licenses for most software are designed to take away your
-freedom to share and change it.  By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users.  This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it.  (Some other Free Software Foundation software is covered by
-the GNU Lesser General Public License instead.)  You can apply it to
-your programs, too.
-
-  When we speak of free software, we are referring to freedom, not
-price.  Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
-  To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
-  For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have.  You must make sure that they, too, receive or can get the
-source code.  And you must show them these terms so they know their
-rights.
-
-  We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
-  Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software.  If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
-  Finally, any free program is threatened constantly by software
-patents.  We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary.  To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
-  The precise terms and conditions for copying, distribution and
-modification follow.
-
-                   GNU GENERAL PUBLIC LICENSE
-   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
-  0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License.  The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language.  (Hereinafter, translation is included without limitation in
-the term "modification".)  Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope.  The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
-  1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
-  2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
-    a) You must cause the modified files to carry prominent notices
-    stating that you changed the files and the date of any change.
-
-    b) You must cause any work that you distribute or publish, that in
-    whole or in part contains or is derived from the Program or any
-    part thereof, to be licensed as a whole at no charge to all third
-    parties under the terms of this License.
-
-    c) If the modified program normally reads commands interactively
-    when run, you must cause it, when started running for such
-    interactive use in the most ordinary way, to print or display an
-    announcement including an appropriate copyright notice and a
-    notice that there is no warranty (or else, saying that you provide
-    a warranty) and that users may redistribute the program under
-    these conditions, and telling the user how to view a copy of this
-    License.  (Exception: if the Program itself is interactive but
-    does not normally print such an announcement, your work based on
-    the Program is not required to print an announcement.)
-
-These requirements apply to the modified work as a whole.  If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works.  But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
-  3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
-    a) Accompany it with the complete corresponding machine-readable
-    source code, which must be distributed under the terms of Sections
-    1 and 2 above on a medium customarily used for software interchange; or,
-
-    b) Accompany it with a written offer, valid for at least three
-    years, to give any third party, for a charge no more than your
-    cost of physically performing source distribution, a complete
-    machine-readable copy of the corresponding source code, to be
-    distributed under the terms of Sections 1 and 2 above on a medium
-    customarily used for software interchange; or,
-
-    c) Accompany it with the information you received as to the offer
-    to distribute corresponding source code.  (This alternative is
-    allowed only for noncommercial distribution and only if you
-    received the program in object code or executable form with such
-    an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it.  For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable.  However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
-  4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License.  Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
-  5. You are not required to accept this License, since you have not
-signed it.  However, nothing else grants you permission to modify or
-distribute the Program or its derivative works.  These actions are
-prohibited by law if you do not accept this License.  Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
-  6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions.  You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
-  7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License.  If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all.  For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices.  Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
-  8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded.  In such case, this License incorporates
-the limitation as if written in the body of this License.
-
-  9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time.  Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number.  If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation.  If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
-  10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission.  For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this.  Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
-                           NO WARRANTY
-
-  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
-  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
-                    END OF TERMS AND CONDITIONS
-
-           How to Apply These Terms to Your New Programs
-
-  If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
-  To do so, attach the following notices to the program.  It is safest
-to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
-    <one line to give the program's name and a brief idea of what it does.>
-    Copyright (C) <year>  <name of author>
-
-    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.,
-    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
-
-    Gnomovision version 69, Copyright (C) year name of author
-    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
-    This is free software, and you are welcome to redistribute it
-    under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License.  Of course, the commands you use may
-be called something other than `show w' and `show c'; they could even be
-mouse-clicks or menu items--whatever suits your program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary.  Here is a sample; alter the names:
-
-  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
-  `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
-  <signature of Ty Coon>, 1 April 1989
-  Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program into
-proprietary programs.  If your program is a subroutine library, you may
-consider it more useful to permit linking proprietary applications with the
-library.  If this is what you want to do, use the GNU Lesser General
-Public License instead of this License.
diff --git a/qcsrc/warpzonelib/TODO b/qcsrc/warpzonelib/TODO
deleted file mode 100644 (file)
index 927ab12..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-Open issues:
-- grep for TODO and FIXME
-- when shot origin is inside warpzone, vortex shot fails (and is even drawn in totally wrong direction). WHY? Possibly v_forward got lost?
-
-Weapon support:
-
-- blaster: YES
-- shotgun: YES
-- machinegun: YES
-- mortar: YES
-- electro: YES
-- crylink: YES
-- vortex: YES
-- hagar: YES
-- devastator: YES (except for trail bug)
-- porto: YES (bwahahahaha)
-- hlac: YES
-- vaporizer: YES
-- rifle: YES
-- fireball: YES (BFG effect cannot work through warpzones by design, so it's not available through warpzones)
-- hook: YES
-
-- shockwave: NO (does not support warpzones currently)
-- tuba: NO (sound)
diff --git a/qcsrc/warpzonelib/anglestransform.qc b/qcsrc/warpzonelib/anglestransform.qc
deleted file mode 100644 (file)
index 079ceaa..0000000
+++ /dev/null
@@ -1,233 +0,0 @@
-#include "anglestransform.qh"
-
-#if defined(CSQC)
-       #include "../dpdefs/csprogsdefs.qh"
-#elif defined(MENUQC)
-#elif defined(SVQC)
-       #include "../dpdefs/progsdefs.qh"
-    #include "../dpdefs/dpextensions.qh"
-#endif
-
-#ifdef POSITIVE_PITCH_IS_DOWN
-vector fixedvectoangles(vector a)
-{
-       vector ang;
-       ang = vectoangles(a);
-       ang.x = -ang.x;
-       return ang;
-}
-vector fixedvectoangles2(vector a, vector b)
-{
-       vector ang;
-       ang = vectoangles2(a, b);
-       ang.x = -ang.x;
-       return ang;
-}
-#else
-void fixedmakevectors(vector a)
-{
-       // a makevectors that actually inverts vectoangles
-       a.x = -a.x;
-       makevectors(a);
-}
-#endif
-
-// angles transforms
-// angles in fixedmakevectors/fixedvectoangles space
-vector AnglesTransform_Apply(vector transform, vector v)
-{
-       fixedmakevectors(transform);
-       return v_forward * v.x
-               + v_right   * (-v.y)
-               + v_up      * v.z;
-}
-
-vector AnglesTransform_Multiply(vector t1, vector t2)
-{
-       vector m_forward, m_up;
-       fixedmakevectors(t2); m_forward = v_forward; m_up = v_up;
-       m_forward = AnglesTransform_Apply(t1, m_forward); m_up = AnglesTransform_Apply(t1, m_up);
-       return fixedvectoangles2(m_forward, m_up);
-}
-
-vector AnglesTransform_Invert(vector transform)
-{
-       vector i_forward, i_up;
-       fixedmakevectors(transform);
-       // we want angles that turn v_forward into '1 0 0', v_right into '0 1 0' and v_up into '0 0 1'
-       // but these are orthogonal unit vectors!
-       // so to invert, we can simply fixedvectoangles the TRANSPOSED matrix
-       // TODO is this always -transform?
-       i_forward.x = v_forward.x;
-       i_forward.y = -v_right.x;
-       i_forward.z = v_up.x;
-       i_up.x = v_forward.z;
-       i_up.y = -v_right.z;
-       i_up.z = v_up.z;
-       return fixedvectoangles2(i_forward, i_up);
-}
-
-vector AnglesTransform_TurnDirectionFR(vector transform)
-{
-       // turn 180 degrees around v_up
-       // changes in-direction to out-direction
-       //fixedmakevectors(transform);
-       //return fixedvectoangles2(-1 * v_forward, 1 * v_up);
-       transform.x = -transform.x;
-       transform.y = 180 + transform.y;
-       transform.z = -transform.z;
-       // pitch: -s +c
-       // yaw:   -s -c
-       // roll:  -s +c
-       return transform;
-}
-
-vector AnglesTransform_TurnDirectionFU(vector transform)
-{
-       // turn 180 degrees around v_up
-       // changes in-direction to out-direction
-       //fixedmakevectors(transform);
-       //return fixedvectoangles2(-1 * v_forward, 1 * v_up);
-       transform.x = -transform.x;
-       transform.y = 180 + transform.y;
-       transform.z = 180 - transform.z;
-       return transform;
-}
-
-vector AnglesTransform_RightDivide(vector to_transform, vector from_transform)
-{
-       return AnglesTransform_Multiply(to_transform, AnglesTransform_Invert(from_transform));
-}
-
-vector AnglesTransform_LeftDivide(vector from_transform, vector to_transform)
-{
-       return AnglesTransform_Multiply(AnglesTransform_Invert(from_transform), to_transform);
-}
-
-vector AnglesTransform_Normalize(vector t, float minimize_roll)
-{
-       float need_flip;
-       // first, bring all angles in their range...
-       t.x = t.x - 360 * rint(t.x / 360);
-       t.y = t.y - 360 * rint(t.y / 360);
-       t.z = t.z - 360 * rint(t.z / 360);
-       if(minimize_roll)
-               need_flip = (t.z > 90 || t.z <= -90);
-       else
-               need_flip = (t.x > 90 || t.x < -90); // for pitch we prefer to allow exactly -90 degrees for looking straight down
-       if(need_flip)
-       {
-               if(t.x >= 0) t.x = 180 - t.x; else t.x = -180 - t.x;
-               if(t.y > 0) t.y -= 180; else t.y += 180;
-               if(t.z > 0) t.z -= 180; else t.z += 180;
-       }
-       return t;
-}
-
-vector AnglesTransform_CancelRoll(vector t)
-{
-       const float epsilon = 30;
-       float f;
-
-       // constraints:
-       // forward vector (NOT SO important)
-       // right vector, up vector: screen rotation (MORE important)
-       // choose best match among all pitch-yaw only rotations
-
-       // FIXME find a better method
-
-       f = fabs(t.x - (-90)) / epsilon;
-       if(f < 1)
-       {
-               //t_x = -90;
-               t.y += t.z;
-               t.z = 0;
-       }
-       else
-       {
-               f = fabs(t.x - 90) / epsilon;
-               if(f < 1)
-               {
-                       //t_x = 90;
-                       t.y -= t.z;
-                       t.z = 0;
-               }
-       }
-       return t;
-}
-
-#ifdef POSITIVE_PITCH_IS_DOWN
-vector AnglesTransform_ApplyToAngles(vector transform, vector v)
-{
-       v.x = -v.x;
-       v = AnglesTransform_Multiply(transform, v);
-       v.x = -v.x;
-       return v;
-}
-vector AnglesTransform_ApplyToVAngles(vector transform, vector v)
-{
-       v = AnglesTransform_Multiply(transform, v);
-       return v;
-}
-vector AnglesTransform_FromAngles(vector v)
-{
-       v.x = -v.x;
-       return v;
-}
-vector AnglesTransform_ToAngles(vector v)
-{
-       v.x = -v.x;
-       return v;
-}
-vector AnglesTransform_FromVAngles(vector v)
-{
-       return v;
-}
-vector AnglesTransform_ToVAngles(vector v)
-{
-       return v;
-}
-#else
-vector AnglesTransform_ApplyToAngles(vector transform, vector v)
-{
-       v = AnglesTransform_Multiply(transform, v);
-       return v;
-}
-vector AnglesTransform_ApplyToVAngles(vector transform, vector v)
-{
-       v.x = -v.x;
-       v = AnglesTransform_Multiply(transform, v);
-       v.x = -v.x;
-       return v;
-}
-vector AnglesTransform_FromAngles(vector v)
-{
-       return v;
-}
-vector AnglesTransform_ToAngles(vector v)
-{
-       return v;
-}
-vector AnglesTransform_FromVAngles(vector v)
-{
-       v.x = -v.x;
-       return v;
-}
-vector AnglesTransform_ToVAngles(vector v)
-{
-       v.x = -v.x;
-       return v;
-}
-#endif
-
-vector AnglesTransform_Multiply_GetPostShift(vector t0, vector st0, vector t1, vector st1)
-{
-       // we want the result of:
-       //   t0 * (t1 * p + st1) + st0
-       //   t0 * t1 * p + t0 * st1 + st0
-       return st0 + AnglesTransform_Apply(t0, st1);
-}
-vector AnglesTransform_PrePostShift_GetPostShift(vector sf, vector t, vector st)
-{
-       return st - AnglesTransform_Apply(t, sf);
-}
diff --git a/qcsrc/warpzonelib/anglestransform.qh b/qcsrc/warpzonelib/anglestransform.qh
deleted file mode 100644 (file)
index 0538471..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-#ifndef ANGLETRANSFORM_H
-#define ANGLETRANSFORM_H
-
-#define POSITIVE_PITCH_IS_DOWN
-
-#ifdef POSITIVE_PITCH_IS_DOWN
-#define fixedmakevectors makevectors
-vector fixedvectoangles(vector a);
-vector fixedvectoangles2(vector a, vector b);
-#else
-void fixedmakevectors(vector a);
-#define fixedvectoangles2 vectoangles2
-#define fixedvectoangles vectoangles
-#endif
-
-vector AnglesTransform_Apply(vector transform, vector v);
-vector AnglesTransform_Multiply(vector t1, vector t2); // A B
-vector AnglesTransform_Invert(vector transform);
-vector AnglesTransform_TurnDirectionFU(vector transform);
-vector AnglesTransform_TurnDirectionFR(vector transform);
-vector AnglesTransform_RightDivide(vector to_transform, vector from_transform); // A B^-1
-vector AnglesTransform_LeftDivide(vector from_transform, vector to_transform); // A^-1 B
-
-vector AnglesTransform_Normalize(vector t, float minimize_roll); // makes sure all angles are in their range: yaw in -180..180, pitch in -90..90, roll in -180..180 (or if minimize_roll is set, pitch in -180..180, roll in -90..90)
-
-vector AnglesTransform_ApplyToAngles(vector transform, vector v);
-vector AnglesTransform_ApplyToVAngles(vector transform, vector v);
-vector AnglesTransform_FromAngles(vector v);
-vector AnglesTransform_ToAngles(vector v);
-vector AnglesTransform_FromVAngles(vector v);
-vector AnglesTransform_ToVAngles(vector v);
-
-// transformed = original * transform + postshift
-vector AnglesTransform_Multiply_GetPostShift(vector sf0, vector st0, vector t1, vector st1);
-vector AnglesTransform_PrePostShift_GetPostShift(vector sf, vector t, vector st);
-#endif
diff --git a/qcsrc/warpzonelib/client.qc b/qcsrc/warpzonelib/client.qc
deleted file mode 100644 (file)
index 85fbdd9..0000000
+++ /dev/null
@@ -1,290 +0,0 @@
-#include "client.qh"
-#include "common.qh"
-
-#if defined(CSQC)
-       #include "../client/autocvars.qh"
-       #include "../csqcmodellib/cl_model.qh"
-       #include "../dpdefs/csprogsdefs.qh"
-#elif defined(MENUQC)
-#elif defined(SVQC)
-#endif
-
-void WarpZone_Fade_PreDraw()
-{SELFPARAM();
-       vector org;
-       org = getpropertyvec(VF_ORIGIN);
-       if(!checkpvs(org, self)) // this makes sense as long as we don't support recursive warpzones
-               self.alpha = 0;
-       else if(self.warpzone_fadestart)
-               self.alpha = bound(0, (self.warpzone_fadeend - vlen(org - self.origin - 0.5 * (self.mins + self.maxs))) / (self.warpzone_fadeend - self.warpzone_fadestart), 1);
-       else
-               self.alpha = 1;
-       //printf("%v <-> %v\n", view_origin, self.origin + 0.5 * (self.mins + self.maxs));
-       if(self.alpha <= 0)
-               self.drawmask = 0;
-       else
-               self.drawmask = MASK_NORMAL;
-}
-
-void WarpZone_Read(float isnew)
-{SELFPARAM();
-       warpzone_warpzones_exist = 1;
-       if (!self.enemy)
-       {
-               self.enemy = spawn();
-               self.enemy.classname = "warpzone_from";
-       }
-       self.classname = "trigger_warpzone";
-
-       int f = ReadByte();
-       self.warpzone_isboxy = (f & 1);
-       if(f & 4)
-       {
-               self.origin_x = ReadCoord();
-               self.origin_y = ReadCoord();
-               self.origin_z = ReadCoord();
-       }
-       else
-               self.origin = '0 0 0';
-       self.modelindex = ReadShort();
-       self.mins_x = ReadCoord();
-       self.mins_y = ReadCoord();
-       self.mins_z = ReadCoord();
-       self.maxs_x = ReadCoord();
-       self.maxs_y = ReadCoord();
-       self.maxs_z = ReadCoord();
-       self.scale = ReadByte() / 16;
-       self.enemy.oldorigin_x = ReadCoord();
-       self.enemy.oldorigin_y = ReadCoord();
-       self.enemy.oldorigin_z = ReadCoord();
-       self.enemy.avelocity_x = ReadCoord();
-       self.enemy.avelocity_y = ReadCoord();
-       self.enemy.avelocity_z = ReadCoord();
-       self.oldorigin_x = ReadCoord();
-       self.oldorigin_y = ReadCoord();
-       self.oldorigin_z = ReadCoord();
-       self.avelocity_x = ReadCoord();
-       self.avelocity_y = ReadCoord();
-       self.avelocity_z = ReadCoord();
-
-       if(f & 2)
-       {
-               self.warpzone_fadestart = ReadShort();
-               self.warpzone_fadeend = max(self.warpzone_fadestart + 1, ReadShort());
-       }
-       else
-       {
-               self.warpzone_fadestart = 0;
-               self.warpzone_fadeend = 0;
-       }
-
-       // common stuff
-       WarpZone_SetUp(self, self.enemy.oldorigin, self.enemy.avelocity, self.oldorigin, self.avelocity);
-
-       // link me
-       //setmodel(self, self.model);
-       setorigin(self, self.origin);
-       setsize(self, self.mins, self.maxs);
-
-       // how to draw
-       // engine currently wants this
-       self.predraw = WarpZone_Fade_PreDraw;
-}
-
-void WarpZone_Camera_Read(float isnew)
-{SELFPARAM();
-       warpzone_cameras_exist = 1;
-       self.classname = "func_warpzone_camera";
-
-       int f = ReadByte();
-       if(f & 4)
-       {
-               self.origin_x = ReadCoord();
-               self.origin_y = ReadCoord();
-               self.origin_z = ReadCoord();
-       }
-       else
-               self.origin = '0 0 0';
-       self.modelindex = ReadShort();
-       self.mins_x = ReadCoord();
-       self.mins_y = ReadCoord();
-       self.mins_z = ReadCoord();
-       self.maxs_x = ReadCoord();
-       self.maxs_y = ReadCoord();
-       self.maxs_z = ReadCoord();
-       self.scale = ReadByte() / 16;
-       self.oldorigin_x = ReadCoord();
-       self.oldorigin_y = ReadCoord();
-       self.oldorigin_z = ReadCoord();
-       self.avelocity_x = ReadCoord();
-       self.avelocity_y = ReadCoord();
-       self.avelocity_z = ReadCoord();
-
-       if(f & 2)
-       {
-               self.warpzone_fadestart = ReadShort();
-               self.warpzone_fadeend = max(self.warpzone_fadestart + 1, ReadShort());
-       }
-       else
-       {
-               self.warpzone_fadestart = 0;
-               self.warpzone_fadeend = 0;
-       }
-
-       // common stuff
-       WarpZone_Camera_SetUp(self, self.oldorigin, self.avelocity);
-
-       // engine currently wants this
-       self.drawmask = MASK_NORMAL;
-
-       // link me
-       //setmodel(self, self.model);
-       setorigin(self, self.origin);
-       setsize(self, self.mins, self.maxs);
-
-       // how to draw
-       // engine currently wants this
-       self.predraw = WarpZone_Fade_PreDraw;
-}
-
-void CL_RotateMoves(vector ang) = #638;
-void WarpZone_Teleported_Read(float isnew)
-{SELFPARAM();
-       vector v;
-       self.classname = "warpzone_teleported";
-       v.x = ReadCoord();
-       v.y = ReadCoord();
-       v.z = ReadCoord();
-       if(!isnew)
-               return;
-       self.warpzone_transform = v;
-       setproperty(VF_CL_VIEWANGLES, WarpZone_TransformVAngles(self, getpropertyvec(VF_CL_VIEWANGLES)));
-       if(checkextension("DP_CSQC_ROTATEMOVES"))
-               CL_RotateMoves(v);
-               //CL_RotateMoves('0 90 0');
-}
-
-float warpzone_fixingview;
-float warpzone_fixingview_drawexteriormodel;
-
-void WarpZone_View_Outside()
-{
-       if(!warpzone_fixingview)
-               return;
-       warpzone_fixingview = 0;
-       cvar_set("r_drawexteriormodel", ftos(warpzone_fixingview_drawexteriormodel));
-}
-
-void WarpZone_View_Inside()
-{
-       if(autocvar_chase_active)
-       {
-               WarpZone_View_Outside();
-               return;
-       }
-       if(warpzone_fixingview)
-               return;
-       warpzone_fixingview = 1;
-       warpzone_fixingview_drawexteriormodel = cvar("r_drawexteriormodel");
-       cvar_set("r_drawexteriormodel", "0");
-}
-
-vector WarpZone_FixNearClip(vector o, vector c0, vector c1, vector c2, vector c3)
-{
-       vector mi, ma;
-       entity e;
-       float pd;
-
-       mi.x = min(o.x, c0_x, c1_x, c2_x, c3_x);
-       ma.x = max(o.x, c0_x, c1_x, c2_x, c3_x);
-       mi.y = min(o.y, c0_y, c1_y, c2_y, c3_y);
-       ma.y = max(o.y, c0_y, c1_y, c2_y, c3_y);
-       mi.z = min(o.z, c0_z, c1_z, c2_z, c3_z);
-       ma.z = max(o.z, c0_z, c1_z, c2_z, c3_z);
-
-       e = WarpZone_Find(mi, ma);
-       if(e)
-       {
-               if(WarpZone_PlaneDist(e, o) < 0)
-                       return '0 0 0';
-                       // can't really be, though, but if it is, this is not my warpzone, but a random different one in the same mins/maxs
-               pd = min(
-                               WarpZone_PlaneDist(e, c0),
-                               WarpZone_PlaneDist(e, c1),
-                               WarpZone_PlaneDist(e, c2),
-                               WarpZone_PlaneDist(e, c3)
-                       );
-               if(pd < 0)
-                       return e.warpzone_forward * -pd;
-       }
-
-       return '0 0 0';
-}
-
-void WarpZone_FixPMove()
-{
-       entity e;
-       e = WarpZone_Find(pmove_org, pmove_org);
-       if(e)
-       {
-               pmove_org = WarpZone_TransformOrigin(e, pmove_org);
-               input_angles = WarpZone_TransformVAngles(e, input_angles);
-       }
-}
-
-#ifndef KEEP_ROLL
-float autocvar_cl_rollkillspeed = 10;
-#endif
-void WarpZone_FixView()
-{
-       entity e;
-       vector org, ang, nearclip, corner0, corner1, corner2, corner3, o;
-       float f;
-
-       warpzone_save_view_origin = org = getpropertyvec(VF_ORIGIN);
-       warpzone_save_view_angles = ang = getpropertyvec(VF_ANGLES);
-
-       e = WarpZone_Find(org, org);
-       if(e)
-       {
-               org = WarpZone_TransformOrigin(e, org);
-               ang = WarpZone_TransformVAngles(e, ang);
-               WarpZone_View_Inside();
-       }
-       else
-               WarpZone_View_Outside();
-
-#ifndef KEEP_ROLL
-       float rick;
-       if(autocvar_cl_rollkillspeed)
-               f = max(0, (1 - frametime * autocvar_cl_rollkillspeed));
-       else
-               f = 0;
-
-       rick = getproperty(VF_CL_VIEWANGLES_Z);
-       rick *= f;
-       setproperty(VF_CL_VIEWANGLES_Z, rick);
-       ang.z *= f;
-#endif
-
-       setproperty(VF_ORIGIN, org);
-       setproperty(VF_ANGLES, ang);
-
-       nearclip = '0 0 1' * (cvar("r_nearclip") * 1.125);
-       corner0 = cs_unproject('0 0 0' + nearclip);
-       corner1 = cs_unproject('1 0 0' * cvar("vid_conwidth") + nearclip);
-       corner2 = cs_unproject('0 1 0' * cvar("vid_conheight") + nearclip);
-       corner3 = cs_unproject('1 0 0' * cvar("vid_conwidth") + '0 1 0' * cvar("vid_conheight") + nearclip);
-       o = WarpZone_FixNearClip(org, corner0, corner1, corner2, corner3);
-       if(o != '0 0 0')
-               setproperty(VF_ORIGIN, org + o);
-}
-
-void WarpZone_Init()
-{
-}
-
-void WarpZone_Shutdown()
-{
-       WarpZone_View_Outside();
-}
diff --git a/qcsrc/warpzonelib/client.qh b/qcsrc/warpzonelib/client.qh
deleted file mode 100644 (file)
index a9f0fe1..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-#ifndef CLIENT_H
-#define CLIENT_H
-
-void WarpZone_Read(float bIsNewEntity);
-void WarpZone_Camera_Read(float bIsNewEntity);
-void WarpZone_Teleported_Read(float bIsNewEntity);
-
-void WarpZone_FixPMove();
-void WarpZone_FixView();
-
-void WarpZone_Init();
-void WarpZone_Shutdown();
-
-vector warpzone_save_view_origin;
-vector warpzone_save_view_angles;
-#endif
diff --git a/qcsrc/warpzonelib/common.qc b/qcsrc/warpzonelib/common.qc
deleted file mode 100644 (file)
index 0eaaac9..0000000
+++ /dev/null
@@ -1,877 +0,0 @@
-#include "common.qh"
-
-#if defined(CSQC)
-       #include "../dpdefs/csprogsdefs.qh"
-    #include "../server/t_items.qh"
-#elif defined(MENUQC)
-#elif defined(SVQC)
-    #include "../common/weapons/all.qh"
-    #include "../dpdefs/dpextensions.qh"
-       #include "../dpdefs/progsdefs.qh"
-#endif
-
-void WarpZone_Accumulator_Clear(entity acc)
-{
-       acc.warpzone_transform = '0 0 0';
-       acc.warpzone_shift = '0 0 0';
-}
-void WarpZone_Accumulator_AddTransform(entity acc, vector t, vector s)
-{
-       vector tr, st;
-       tr = AnglesTransform_Multiply(t, acc.warpzone_transform);
-       st = AnglesTransform_Multiply_GetPostShift(t, s, acc.warpzone_transform, acc.warpzone_shift);
-       acc.warpzone_transform = tr;
-       acc.warpzone_shift = st;
-}
-void WarpZone_Accumulator_Add(entity acc, entity wz)
-{
-       WarpZone_Accumulator_AddTransform(acc, wz.warpzone_transform, wz.warpzone_shift);
-}
-void WarpZone_Accumulator_AddInverseTransform(entity acc, vector t, vector s)
-{
-       vector tt, ss;
-       tt = AnglesTransform_Invert(t);
-       ss = AnglesTransform_PrePostShift_GetPostShift(s, tt, '0 0 0');
-       WarpZone_Accumulator_AddTransform(acc, tt, ss);
-       // yes, this probably can be done simpler... but this way is "obvious" :)
-}
-void WarpZone_Accumulator_AddInverse(entity acc, entity wz)
-{
-       WarpZone_Accumulator_AddInverseTransform(acc, wz.warpzone_transform, wz.warpzone_shift);
-}
-
-.vector(vector, vector) camera_transform;
-float autocvar_cl_warpzone_usetrace = 1;
-vector WarpZone_camera_transform(vector org, vector ang)
-{SELFPARAM();
-       vector vf, vr, vu;
-       if(self.warpzone_fadestart)
-               if(vlen(org - self.origin - 0.5 * (self.mins + self.maxs)) > self.warpzone_fadeend + 400)
-                       return org;
-                       // don't transform if zone faded out (plus 400qu safety margin for typical speeds and latencies)
-                       // unneeded on client, on server this helps a lot
-       vf = v_forward;
-       vr = v_right;
-       vu = v_up;
-       org = WarpZone_TransformOrigin(self, org);
-       vf = WarpZone_TransformVelocity(self, vf);
-       vr = WarpZone_TransformVelocity(self, vr);
-       vu = WarpZone_TransformVelocity(self, vu);
-       if(autocvar_cl_warpzone_usetrace)
-               traceline(self.warpzone_targetorigin, org, MOVE_NOMONSTERS, world);
-       else
-               trace_endpos = self.warpzone_targetorigin;
-       v_forward = vf;
-       v_right = vr;
-       v_up = vu;
-       return org;
-}
-
-void WarpZone_SetUp(entity e, vector my_org, vector my_ang, vector other_org, vector other_ang)
-{
-       e.warpzone_transform = AnglesTransform_RightDivide(other_ang, AnglesTransform_TurnDirectionFR(my_ang));
-       e.warpzone_shift = AnglesTransform_PrePostShift_GetPostShift(my_org, e.warpzone_transform, other_org);
-       e.warpzone_origin = my_org;
-       e.warpzone_targetorigin = other_org;
-       e.warpzone_angles = my_ang;
-       e.warpzone_targetangles = other_ang;
-       fixedmakevectors(my_ang); e.warpzone_forward = v_forward;
-       fixedmakevectors(other_ang); e.warpzone_targetforward = v_forward;
-       e.camera_transform = WarpZone_camera_transform;
-}
-
-vector WarpZone_Camera_camera_transform(vector org, vector ang)
-{SELFPARAM();
-       // a fixed camera view
-       if(self.warpzone_fadestart)
-               if(vlen(org - self.origin - 0.5 * (self.mins + self.maxs)) > self.warpzone_fadeend + 400)
-                       return org;
-                       // don't transform if zone faded out (plus 400qu safety margin for typical speeds and latencies)
-                       // unneeded on client, on server this helps a lot
-       trace_endpos = self.warpzone_origin;
-       makevectors(self.warpzone_angles);
-       return self.warpzone_origin;
-}
-
-void WarpZone_Camera_SetUp(entity e, vector my_org, vector my_ang) // we assume that e.oldorigin and e.avelocity point to view origin and direction
-{
-       e.warpzone_origin = my_org;
-       e.warpzone_angles = my_ang;
-       e.camera_transform = WarpZone_Camera_camera_transform;
-}
-
-.entity enemy;
-
-vector WarpZoneLib_BoxTouchesBrush_mins;
-vector WarpZoneLib_BoxTouchesBrush_maxs;
-entity WarpZoneLib_BoxTouchesBrush_ent;
-entity WarpZoneLib_BoxTouchesBrush_ignore;
-float WarpZoneLib_BoxTouchesBrush_Recurse()
-{
-       float s;
-       entity se;
-       float f;
-
-       tracebox('0 0 0', WarpZoneLib_BoxTouchesBrush_mins, WarpZoneLib_BoxTouchesBrush_maxs, '0 0 0', MOVE_NOMONSTERS, WarpZoneLib_BoxTouchesBrush_ignore);
-#ifdef CSQC
-       if (trace_networkentity)
-       {
-               LOG_TRACE("hit a network ent, cannot continue WarpZoneLib_BoxTouchesBrush\n");
-               // we cannot continue, as a player blocks us...
-               // so, abort
-               return 0;
-       }
-#endif
-       if (!trace_ent)
-               return 0;
-       if (trace_ent == WarpZoneLib_BoxTouchesBrush_ent)
-               return 1;
-
-       se = trace_ent;
-       s = se.solid;
-       se.solid = SOLID_NOT;
-       f = WarpZoneLib_BoxTouchesBrush_Recurse();
-       se.solid = s;
-
-       return f;
-}
-
-float WarpZoneLib_BoxTouchesBrush(vector mi, vector ma, entity e, entity ig)
-{
-    float f, s;
-
-    if(!e.modelindex || e.warpzone_isboxy)
-        return 1;
-
-    s = e.solid;
-    e.solid = SOLID_BSP;
-    WarpZoneLib_BoxTouchesBrush_mins = mi;
-    WarpZoneLib_BoxTouchesBrush_maxs = ma;
-    WarpZoneLib_BoxTouchesBrush_ent = e;
-    WarpZoneLib_BoxTouchesBrush_ignore = ig;
-    f = WarpZoneLib_BoxTouchesBrush_Recurse();
-    e.solid = s;
-
-    return f;
-}
-
-entity WarpZone_Find(vector mi, vector ma)
-{
-       // if we are near any warpzone planes - MOVE AWAY (work around nearclip)
-       entity e;
-       if(!warpzone_warpzones_exist)
-               return world;
-       for(e = world; (e = find(e, classname, "trigger_warpzone")); )
-               if(WarpZoneLib_BoxTouchesBrush(mi, ma, e, world))
-                       return e;
-       return world;
-}
-
-void WarpZone_MakeAllSolid()
-{
-       entity e;
-       if(!warpzone_warpzones_exist)
-               return;
-       for(e = world; (e = find(e, classname, "trigger_warpzone")); )
-               e.solid = SOLID_BSP;
-}
-
-void WarpZone_MakeAllOther()
-{
-       entity e;
-       if(!warpzone_warpzones_exist)
-               return;
-       for(e = world; (e = find(e, classname, "trigger_warpzone")); )
-               e.solid = SOLID_TRIGGER;
-}
-
-void WarpZone_Trace_InitTransform()
-{
-       if(!WarpZone_trace_transform)
-       {
-               WarpZone_trace_transform = spawn();
-               WarpZone_trace_transform.classname = "warpzone_trace_transform";
-       }
-       WarpZone_Accumulator_Clear(WarpZone_trace_transform);
-}
-void WarpZone_Trace_AddTransform(entity wz)
-{
-       WarpZone_Accumulator_Add(WarpZone_trace_transform, wz);
-}
-
-void WarpZone_TraceBox_ThroughZone(vector org, vector mi, vector ma, vector end, float nomonsters, entity forent, entity zone, WarpZone_trace_callback_t cb)
-{
-       float nomonsters_adjusted;
-       float frac, sol, i;
-       float contentshack;
-       vector o0, e0;
-       entity wz;
-       vector vf, vr, vu;
-
-       WarpZone_trace_forent = forent;
-       WarpZone_trace_firstzone = world;
-       WarpZone_trace_lastzone = world;
-       WarpZone_Trace_InitTransform();
-       if(!warpzone_warpzones_exist)
-       {
-               if(nomonsters == MOVE_NOTHING)
-               {
-                       trace_endpos = end;
-                       trace_fraction = 1;
-                       if(cb)
-                               cb(org, trace_endpos, end);
-                       return;
-               }
-               else
-               {
-                       tracebox(org, mi, ma, end, nomonsters, WarpZone_trace_forent);
-                       if(cb)
-                               cb(org, trace_endpos, end);
-                       return;
-               }
-       }
-
-       vf = v_forward;
-       vr = v_right;
-       vu = v_up;
-       o0 = org;
-       e0 = end;
-
-       switch(nomonsters)
-       {
-               case MOVE_WORLDONLY:
-               case MOVE_NOTHING:
-                       nomonsters_adjusted = MOVE_NOMONSTERS;
-                       break;
-               default:
-                       nomonsters_adjusted = nomonsters;
-                       break;
-       }
-       if((contentshack = (WarpZone_trace_forent.dphitcontentsmask && !(WarpZone_trace_forent.dphitcontentsmask & DPCONTENTS_SOLID))))
-               BITSET_ASSIGN(WarpZone_trace_forent.dphitcontentsmask, DPCONTENTS_SOLID);
-
-       // if starting in warpzone, first transform
-       wz = WarpZone_Find(org + mi, org + ma);
-       if(wz)
-       {
-               WarpZone_trace_firstzone = wz;
-               WarpZone_trace_lastzone = wz;
-               if(zone && wz != zone)
-               {
-                       // we are in ANOTHER warpzone. This is bad. Make a zero length trace and return.
-                       sol = 1;
-                       trace_fraction = 0;
-                       trace_endpos = org;
-                       goto fail;
-               }
-               WarpZone_Trace_AddTransform(wz);
-               org = WarpZone_TransformOrigin(wz, org);
-               end = WarpZone_TransformOrigin(wz, end);
-       }
-       WarpZone_MakeAllSolid();
-       sol = -1;
-       frac = 0;
-       i = 16;
-       for (;;)
-       {
-               if(--i < 1)
-               {
-                       LOG_TRACE("Too many warpzones in sequence, aborting trace.\n");
-                       trace_ent = world;
-                       break;
-               }
-               tracebox(org, mi, ma, end, nomonsters_adjusted, WarpZone_trace_forent);
-               if(cb)
-                       cb(org, trace_endpos, end);
-               if(sol < 0)
-                       sol = trace_startsolid;
-
-               frac = trace_fraction = frac + (1 - frac) * trace_fraction;
-               if(trace_fraction >= 1)
-                       break;
-               if(trace_ent.classname != "trigger_warpzone")
-               {
-                       if((nomonsters == MOVE_NOTHING) || ((nomonsters == MOVE_WORLDONLY) && trace_ent) || (contentshack && (trace_dphitcontents & WarpZone_trace_forent.dphitcontentsmask) == DPCONTENTS_SOLID))
-                       {
-                               // continue the trace, ignoring this hit (we only care for warpzones)
-                               org = trace_endpos + normalize(end - org);
-                               continue;
-                               // we cannot do an inverted trace here, as we do care for further warpzones inside that "solid" to be found
-                               // otherwise, players could block entrances that way
-                       }
-                       break;
-               }
-               if(trace_ent == wz)
-               {
-                       // FIXME can this check be removed? Do we really need it?
-                       LOG_TRACE("I transformed into the same zone again, wtf, aborting the trace\n");
-                       trace_ent = world;
-                       break;
-               }
-               wz = trace_ent;
-               if(!WarpZone_trace_firstzone)
-                       WarpZone_trace_firstzone = wz;
-               WarpZone_trace_lastzone = wz;
-               if(zone && wz != zone)
-                       break;
-               WarpZone_Trace_AddTransform(wz);
-               // we hit a warpzone... so, let's perform the trace after the warp again
-               org = WarpZone_TransformOrigin(wz, trace_endpos);
-               end = WarpZone_TransformOrigin(wz, end);
-
-               // we got warped, so let's step back a bit
-               tracebox(org, mi, ma, org + normalize(org - end) * 32, nomonsters_adjusted, WarpZone_trace_forent);
-               org = trace_endpos;
-       }
-       WarpZone_MakeAllOther();
-:fail
-       if(contentshack)
-               BITCLR_ASSIGN(WarpZone_trace_forent.dphitcontentsmask, DPCONTENTS_SOLID);
-       trace_startsolid = sol;
-       v_forward = vf;
-       v_right = vr;
-       v_up = vu;
-}
-
-void WarpZone_TraceBox(vector org, vector mi, vector ma, vector end, float nomonsters, entity forent)
-{
-       WarpZone_TraceBox_ThroughZone(org, mi, ma, end, nomonsters, forent, world, WarpZone_trace_callback_t_null);
-}
-
-void WarpZone_TraceLine(vector org, vector end, float nomonsters, entity forent)
-{
-       WarpZone_TraceBox(org, '0 0 0', '0 0 0', end, nomonsters, forent);
-}
-
-void WarpZone_TraceToss_ThroughZone(entity e, entity forent, entity zone, WarpZone_trace_callback_t cb)
-{
-       float g, dt, i;
-       vector vf, vr, vu, v0, o0;
-       entity wz;
-
-       o0 = e.origin;
-       v0 = e.velocity;
-       g = cvar("sv_gravity") * e.gravity;
-
-       WarpZone_trace_forent = forent;
-       WarpZone_trace_firstzone = world;
-       WarpZone_trace_lastzone = world;
-       WarpZone_Trace_InitTransform();
-       WarpZone_tracetoss_time = 0;
-       if(!warpzone_warpzones_exist)
-       {
-               tracetoss(e, WarpZone_trace_forent);
-               if(cb)
-                       cb(e.origin, trace_endpos, trace_endpos);
-               dt = vlen(e.origin - o0) / vlen(e.velocity);
-               WarpZone_tracetoss_time += dt;
-               e.velocity_z -= dt * g;
-               WarpZone_tracetoss_velocity = e.velocity;
-               e.velocity = v0;
-               return;
-       }
-
-       vf = v_forward;
-       vr = v_right;
-       vu = v_up;
-
-       // if starting in warpzone, first transform
-       wz = WarpZone_Find(e.origin + e.mins, e.origin + e.maxs);
-       if(wz)
-       {
-               WarpZone_trace_firstzone = wz;
-               WarpZone_trace_lastzone = wz;
-               if(zone && wz != zone)
-               {
-                       // we are in ANOTHER warpzone. This is bad. Make a zero length trace and return.
-
-                       WarpZone_tracetoss_time = 0;
-                       trace_endpos = o0;
-                       goto fail;
-               }
-               WarpZone_Trace_AddTransform(wz);
-               setorigin(e, WarpZone_TransformOrigin(wz, e.origin));
-               e.velocity = WarpZone_TransformVelocity(wz, e.velocity);
-       }
-       WarpZone_MakeAllSolid();
-       i = 16;
-       for (;;)
-       {
-               if(--i < 1)
-               {
-                       LOG_TRACE("Too many warpzones in sequence, aborting trace.\n");
-                       trace_ent = world;
-                       break;
-               }
-               tracetoss(e, WarpZone_trace_forent);
-               if(cb)
-                       cb(e.origin, trace_endpos, trace_endpos);
-               dt = vlen(trace_endpos - e.origin) / vlen(e.velocity);
-               WarpZone_tracetoss_time += dt;
-               e.origin = trace_endpos;
-               e.velocity_z -= dt * g;
-               if(trace_fraction >= 1)
-                       break;
-               if(trace_ent.classname != "trigger_warpzone")
-                       break;
-               if(trace_ent == wz)
-               {
-                       // FIXME can this check be removed? Do we really need it?
-                       LOG_TRACE("I transformed into the same zone again, wtf, aborting the trace\n");
-                       trace_ent = world;
-                       break;
-               }
-               wz = trace_ent;
-               if(!WarpZone_trace_firstzone)
-                       WarpZone_trace_firstzone = wz;
-               WarpZone_trace_lastzone = wz;
-               if(zone && wz != zone)
-                       break;
-               WarpZone_Trace_AddTransform(wz);
-               // we hit a warpzone... so, let's perform the trace after the warp again
-               e.origin = WarpZone_TransformOrigin(wz, e.origin);
-               e.velocity = WarpZone_TransformVelocity(wz, e.velocity);
-
-               // we got warped, so let's step back a bit
-               e.velocity = -e.velocity;
-               tracetoss(e, WarpZone_trace_forent);
-               dt = vlen(trace_endpos - e.origin) / vlen(e.velocity);
-               WarpZone_tracetoss_time -= dt;
-               e.origin = trace_endpos;
-               e.velocity = -e.velocity;
-       }
-       WarpZone_MakeAllOther();
-:fail
-       WarpZone_tracetoss_velocity = e.velocity;
-       v_forward = vf;
-       v_right = vr;
-       v_up = vu;
-       // restore old entity data (caller just uses trace_endpos, WarpZone_tracetoss_velocity and the transform)
-       e.velocity = v0;
-       e.origin = o0;
-}
-
-void WarpZone_TraceToss(entity e, entity forent)
-{
-       WarpZone_TraceToss_ThroughZone(e, forent, world, WarpZone_trace_callback_t_null);
-}
-
-entity WarpZone_TrailParticles_trace_callback_own;
-float WarpZone_TrailParticles_trace_callback_eff;
-void WarpZone_TrailParticles_trace_callback(vector from, vector endpos, vector to)
-{
-       trailparticles(WarpZone_TrailParticles_trace_callback_own, WarpZone_TrailParticles_trace_callback_eff, from, endpos);
-}
-
-void WarpZone_TrailParticles(entity own, float eff, vector org, vector end)
-{
-       WarpZone_TrailParticles_trace_callback_own = own;
-       WarpZone_TrailParticles_trace_callback_eff = eff;
-       WarpZone_TraceBox_ThroughZone(org, '0 0 0', '0 0 0', end, MOVE_NOMONSTERS, world, world, WarpZone_TrailParticles_trace_callback);
-}
-
-#ifdef CSQC
-float WarpZone_TrailParticles_trace_callback_f;
-float WarpZone_TrailParticles_trace_callback_flags;
-void WarpZone_TrailParticles_WithMultiplier_trace_callback(vector from, vector endpos, vector to)
-{
-       boxparticles(WarpZone_TrailParticles_trace_callback_eff, WarpZone_TrailParticles_trace_callback_own, from, endpos, WarpZone_TrailParticles_trace_callback_own.velocity, WarpZone_TrailParticles_trace_callback_own.velocity, WarpZone_TrailParticles_trace_callback_f, WarpZone_TrailParticles_trace_callback_flags);
-}
-
-void WarpZone_TrailParticles_WithMultiplier(entity own, float eff, vector org, vector end, float f, int boxflags)
-{
-       WarpZone_TrailParticles_trace_callback_own = own;
-       WarpZone_TrailParticles_trace_callback_eff = eff;
-       WarpZone_TrailParticles_trace_callback_f = f;
-       WarpZone_TrailParticles_trace_callback_flags = boxflags | PARTICLES_DRAWASTRAIL;
-       WarpZone_TraceBox_ThroughZone(org, '0 0 0', '0 0 0', end, MOVE_NOMONSTERS, world, world, WarpZone_TrailParticles_WithMultiplier_trace_callback);
-}
-#endif
-
-float WarpZone_PlaneDist(entity wz, vector v)
-{
-       return (v - wz.warpzone_origin) * wz.warpzone_forward;
-}
-
-float WarpZone_TargetPlaneDist(entity wz, vector v)
-{
-       return (v - wz.warpzone_targetorigin) * wz.warpzone_targetforward;
-}
-
-vector WarpZone_TransformOrigin(entity wz, vector v)
-{
-       return wz.warpzone_shift + AnglesTransform_Apply(wz.warpzone_transform, v);
-}
-
-vector WarpZone_TransformVelocity(entity wz, vector v)
-{
-       return AnglesTransform_Apply(wz.warpzone_transform, v);
-}
-
-vector WarpZone_TransformAngles(entity wz, vector v)
-{
-       return AnglesTransform_ApplyToAngles(wz.warpzone_transform, v);
-}
-
-vector WarpZone_TransformVAngles(entity wz, vector ang)
-{
-#ifdef KEEP_ROLL
-       float roll;
-       roll = ang.z;
-       ang.z = 0;
-#endif
-
-       ang = AnglesTransform_ApplyToVAngles(wz.warpzone_transform, ang);
-
-#ifdef KEEP_ROLL
-       ang = AnglesTransform_Normalize(ang, true);
-       ang = AnglesTransform_CancelRoll(ang);
-       ang.z = roll;
-#else
-       ang = AnglesTransform_Normalize(ang, false);
-#endif
-
-       return ang;
-}
-
-vector WarpZone_UnTransformOrigin(entity wz, vector v)
-{
-       return AnglesTransform_Apply(AnglesTransform_Invert(wz.warpzone_transform), v - wz.warpzone_shift);
-}
-
-vector WarpZone_UnTransformVelocity(entity wz, vector v)
-{
-       return AnglesTransform_Apply(AnglesTransform_Invert(wz.warpzone_transform), v);
-}
-
-vector WarpZone_UnTransformAngles(entity wz, vector v)
-{
-       return AnglesTransform_ApplyToAngles(AnglesTransform_Invert(wz.warpzone_transform), v);
-}
-
-vector WarpZone_UnTransformVAngles(entity wz, vector ang)
-{
-       float roll;
-
-       roll = ang.z;
-       ang.z = 0;
-
-       ang = AnglesTransform_ApplyToVAngles(AnglesTransform_Invert(wz.warpzone_transform), ang);
-       ang = AnglesTransform_Normalize(ang, true);
-       ang = AnglesTransform_CancelRoll(ang);
-
-       ang.z = roll;
-       return ang;
-}
-
-vector WarpZoneLib_NearestPointOnBox(vector mi, vector ma, vector org)
-{
-       vector nearest;
-       nearest.x = bound(mi.x, org.x, ma.x);
-       nearest.y = bound(mi.y, org.y, ma.y);
-       nearest.z = bound(mi.z, org.z, ma.z);
-       return nearest;
-}
-
-bool WarpZoneLib_BadEntity(entity e)
-{
-       string myclassname = e.classname;
-       if (e.instanceOfObject) return true;
-       switch(myclassname)
-       {
-               case "deathtype":
-               case "weaponentity":
-               case "exteriorweaponentity":
-               case "csqc_score_team":
-               case "pingplreport":
-               case "ent_client_scoreinfo":
-               case "saved_cvar_value":
-               case "accuracy":
-               case "entcs_sender":
-               case "entcs_receiver":
-               case "clientinit":
-               case "sprite_waypoint":
-               case "waypoint":
-               case "gibsplash":
-               //case "net_linked": // actually some real entities are linked without classname, fail
-               case "":
-                       return true;
-       }
-
-       if(startsWith(myclassname, "msg_"))
-               return true;
-
-       if(startsWith(myclassname, "target_"))
-               return true;
-
-       if(startsWith(myclassname, "info_"))
-               return true;
-
-       return false;
-}
-
-.float WarpZone_findradius_hit;
-.entity WarpZone_findradius_next;
-void WarpZone_FindRadius_Recurse(vector org, float rad,        vector org0,               vector transform, vector shift, float needlineofsight)
-//                               blast origin of current search   original blast origin   how to untransform (victim to blast system)
-{
-       vector org_new;
-       vector org0_new;
-       vector shift_new, transform_new;
-       vector p;
-       entity e, e0;
-       entity wz;
-       if(rad <= 0)
-               return;
-       e0 = findradius(org, rad);
-       wz = world;
-
-       for(e = e0; e; e = e.chain)
-       {
-               if(WarpZoneLib_BadEntity(e))
-                       continue;
-               p = WarpZoneLib_NearestPointOnBox(e.origin + e.mins, e.origin + e.maxs, org0);
-               if(needlineofsight)
-               {
-                       traceline(org, p, MOVE_NOMONSTERS, e);
-                       if(trace_fraction < 1)
-                               continue;
-               }
-               if(!e.WarpZone_findradius_hit || vlen(e.WarpZone_findradius_dist) > vlen(org0 - p))
-               {
-                       e.WarpZone_findradius_nearest = p;
-                       e.WarpZone_findradius_dist = org0 - p;
-                       e.WarpZone_findradius_findorigin = org;
-                       e.WarpZone_findradius_findradius = rad;
-                       if(e.classname == "warpzone_refsys")
-                       {
-                               // ignore, especially: do not overwrite the refsys parameters
-                       }
-                       else if(e.classname == "trigger_warpzone")
-                       {
-                               e.WarpZone_findradius_next = wz;
-                               wz = e;
-                               e.WarpZone_findradius_hit = 1;
-                               e.enemy.WarpZone_findradius_dist = '0 0 0'; // we don't want to go through this zone ever again
-                               e.enemy.WarpZone_findradius_hit = 1;
-                       }
-                       else
-                       {
-                               e.warpzone_transform = transform;
-                               e.warpzone_shift = shift;
-                               e.WarpZone_findradius_hit = 1;
-                       }
-               }
-       }
-       for(e = wz; e; e = e.WarpZone_findradius_next)
-       {
-               if(WarpZoneLib_BadEntity(e))
-                       continue;
-
-               org0_new = WarpZone_TransformOrigin(e, org);
-               traceline(e.warpzone_targetorigin, org0_new, MOVE_NOMONSTERS, e);
-               org_new = trace_endpos;
-
-               transform_new = AnglesTransform_Multiply(e.warpzone_transform, transform);
-               shift_new = AnglesTransform_Multiply_GetPostShift(e.warpzone_transform, e.warpzone_shift, transform, shift);
-               WarpZone_FindRadius_Recurse(
-                       org_new,
-                       bound(0, rad - vlen(org_new - org0_new), rad - 8),
-                       org0_new,
-                       transform_new, shift_new,
-                       needlineofsight);
-               e.WarpZone_findradius_hit = 0;
-               e.enemy.WarpZone_findradius_hit = 0;
-       }
-}
-entity WarpZone_FindRadius(vector org, float rad, float needlineofsight)
-{
-       entity e0, e;
-       WarpZone_FindRadius_Recurse(org, rad, org, '0 0 0', '0 0 0', needlineofsight);
-       e0 = findchainfloat(WarpZone_findradius_hit, 1);
-       for(e = e0; e; e = e.chain)
-               e.WarpZone_findradius_hit = 0;
-       return e0;
-}
-
-.entity WarpZone_refsys;
-void WarpZone_RefSys_GC()
-{SELFPARAM();
-       // garbage collect unused reference systems
-       self.nextthink = time + 1;
-       if(self.owner.WarpZone_refsys != self)
-               remove(self);
-}
-void WarpZone_RefSys_CheckCreate(entity me)
-{
-       if(me.WarpZone_refsys.owner != me)
-       {
-               me.WarpZone_refsys = spawn();
-               me.WarpZone_refsys.classname = "warpzone_refsys";
-               me.WarpZone_refsys.owner = me;
-               me.WarpZone_refsys.think = WarpZone_RefSys_GC;
-               me.WarpZone_refsys.nextthink = time + 1;
-               WarpZone_Accumulator_Clear(me.WarpZone_refsys);
-       }
-}
-void WarpZone_RefSys_Clear(entity me)
-{
-       if(me.WarpZone_refsys)
-       {
-               remove(me.WarpZone_refsys);
-               me.WarpZone_refsys = world;
-       }
-}
-void WarpZone_RefSys_AddTransform(entity me, vector t, vector s)
-{
-       if(t != '0 0 0' || s != '0 0 0')
-       {
-               WarpZone_RefSys_CheckCreate(me);
-               WarpZone_Accumulator_AddTransform(me.WarpZone_refsys, t, s);
-       }
-}
-void WarpZone_RefSys_Add(entity me, entity wz)
-{
-       WarpZone_RefSys_AddTransform(me, wz.warpzone_transform, wz.warpzone_shift);
-}
-void WarpZone_RefSys_AddInverseTransform(entity me, vector t, vector s)
-{
-       if(t != '0 0 0' || s != '0 0 0')
-       {
-               WarpZone_RefSys_CheckCreate(me);
-               WarpZone_Accumulator_AddInverseTransform(me.WarpZone_refsys, t, s);
-       }
-}
-void WarpZone_RefSys_AddInverse(entity me, entity wz)
-{
-       WarpZone_RefSys_AddInverseTransform(me, wz.warpzone_transform, wz.warpzone_shift);
-}
-.vector WarpZone_refsys_incremental_shift;
-.vector WarpZone_refsys_incremental_transform;
-void WarpZone_RefSys_AddIncrementally(entity me, entity ref)
-{
-       //vector t, s;
-       if(me.WarpZone_refsys_incremental_transform == ref.WarpZone_refsys.warpzone_transform)
-       if(me.WarpZone_refsys_incremental_shift == ref.WarpZone_refsys.warpzone_shift)
-               return;
-       WarpZone_Accumulator_AddInverseTransform(me.WarpZone_refsys, me.WarpZone_refsys_incremental_transform, me.WarpZone_refsys_incremental_shift);
-       WarpZone_Accumulator_Add(me.WarpZone_refsys, ref.WarpZone_refsys);
-       me.WarpZone_refsys_incremental_shift = ref.WarpZone_refsys.warpzone_shift;
-       me.WarpZone_refsys_incremental_transform = ref.WarpZone_refsys.warpzone_transform;
-}
-void WarpZone_RefSys_BeginAddingIncrementally(entity me, entity ref)
-{
-       me.WarpZone_refsys_incremental_shift = ref.WarpZone_refsys.warpzone_shift;
-       me.WarpZone_refsys_incremental_transform = ref.WarpZone_refsys.warpzone_transform;
-}
-vector WarpZone_RefSys_TransformOrigin(entity from, entity to, vector org)
-{
-       if(from.WarpZone_refsys)
-               org = WarpZone_UnTransformOrigin(from.WarpZone_refsys, org);
-       if(to.WarpZone_refsys)
-               org = WarpZone_TransformOrigin(to.WarpZone_refsys, org);
-       return org;
-}
-vector WarpZone_RefSys_TransformVelocity(entity from, entity to, vector vel)
-{
-       if(from.WarpZone_refsys)
-               vel = WarpZone_UnTransformVelocity(from.WarpZone_refsys, vel);
-       if(to.WarpZone_refsys)
-               vel = WarpZone_TransformVelocity(to.WarpZone_refsys, vel);
-       return vel;
-}
-vector WarpZone_RefSys_TransformAngles(entity from, entity to, vector ang)
-{
-       if(from.WarpZone_refsys)
-               ang = WarpZone_UnTransformAngles(from.WarpZone_refsys, ang);
-       if(to.WarpZone_refsys)
-               ang = WarpZone_TransformAngles(to.WarpZone_refsys, ang);
-       return ang;
-}
-vector WarpZone_RefSys_TransformVAngles(entity from, entity to, vector ang)
-{
-       if(from.WarpZone_refsys)
-               ang = WarpZone_UnTransformVAngles(from.WarpZone_refsys, ang);
-       if(to.WarpZone_refsys)
-               ang = WarpZone_TransformVAngles(to.WarpZone_refsys, ang);
-       return ang;
-}
-void WarpZone_RefSys_Copy(entity me, entity from)
-{
-       if(from.WarpZone_refsys)
-       {
-               WarpZone_RefSys_CheckCreate(me);
-               me.WarpZone_refsys.warpzone_shift = from.WarpZone_refsys.warpzone_shift;
-               me.WarpZone_refsys.warpzone_transform = from.WarpZone_refsys.warpzone_transform;
-       }
-       else
-               WarpZone_RefSys_Clear(me);
-}
-entity WarpZone_RefSys_SpawnSameRefSys(entity me)
-{
-       entity e;
-       e = spawn();
-       WarpZone_RefSys_Copy(e, me);
-       return e;
-}
-
-float WarpZoneLib_ExactTrigger_Touch()
-{SELFPARAM();
-       return !WarpZoneLib_BoxTouchesBrush(other.absmin, other.absmax, self, other);
-}
-
-
-void WarpZoneLib_MoveOutOfSolid_Expand(entity e, vector by)
-{
-       float eps = 0.0625;
-       tracebox(e.origin, e.mins - '1 1 1' * eps, e.maxs + '1 1 1' * eps, e.origin + by, MOVE_WORLDONLY, e);
-       if (trace_startsolid)
-               return;
-       if (trace_fraction < 1)
-       {
-               // hit something
-               // adjust origin in the other direction...
-               setorigin(e,e.origin - by * (1 - trace_fraction));
-       }
-}
-
-float WarpZoneLib_MoveOutOfSolid(entity e)
-{
-       vector o, m0, m1;
-
-       o = e.origin;
-       traceline(o, o, MOVE_WORLDONLY, e);
-       if (trace_startsolid)
-               return false;
-
-       tracebox(o, e.mins, e.maxs, o, MOVE_WORLDONLY, e);
-       if (!trace_startsolid)
-               return true;
-
-       m0 = e.mins;
-       m1 = e.maxs;
-       e.mins = '0 0 0';
-       e.maxs = '0 0 0';
-       WarpZoneLib_MoveOutOfSolid_Expand(e, '1 0 0' * m0_x);
-       e.mins_x = m0_x;
-       WarpZoneLib_MoveOutOfSolid_Expand(e, '1 0 0' * m1_x);
-       e.maxs_x = m1_x;
-       WarpZoneLib_MoveOutOfSolid_Expand(e, '0 1 0' * m0_y);
-       e.mins_y = m0_y;
-       WarpZoneLib_MoveOutOfSolid_Expand(e, '0 1 0' * m1_y);
-       e.maxs_y = m1_y;
-       WarpZoneLib_MoveOutOfSolid_Expand(e, '0 0 1' * m0_z);
-       e.mins_z = m0_z;
-       WarpZoneLib_MoveOutOfSolid_Expand(e, '0 0 1' * m1_z);
-       e.maxs_z = m1_z;
-       setorigin(e, e.origin);
-
-       tracebox(e.origin, e.mins, e.maxs, e.origin, MOVE_WORLDONLY, e);
-       if (trace_startsolid)
-       {
-               setorigin(e, o);
-               return false;
-       }
-
-       return true;
-}
diff --git a/qcsrc/warpzonelib/common.qh b/qcsrc/warpzonelib/common.qh
deleted file mode 100644 (file)
index 3e2b7c7..0000000
+++ /dev/null
@@ -1,116 +0,0 @@
-#ifndef WARPZONELIB_COMMON_H
-#define WARPZONELIB_COMMON_H
-
-// uncomment this if your mod uses the roll angle in fixangle
-// #define KEEP_ROLL
-
-float warpzone_warpzones_exist;
-float warpzone_cameras_exist;
-
-.float warpzone_isboxy;
-.vector warpzone_shift;
-.vector warpzone_origin;
-.vector warpzone_angles;
-.vector warpzone_forward;
-.vector warpzone_targetorigin;
-.vector warpzone_targetangles;
-.vector warpzone_targetforward;
-.vector warpzone_transform;
-.float warpzone_fadestart;
-.float warpzone_fadeend;
-void WarpZone_SetUp(entity e, vector my_org, vector my_ang, vector other_org, vector other_ang);
-void WarpZone_Camera_SetUp(entity e, vector my_org, vector my_ang);
-
-float WarpZoneLib_BoxTouchesBrush(vector mi, vector ma, entity e, entity ig);
-vector WarpZoneLib_NearestPointOnBox(vector mi, vector ma, vector org);
-
-entity WarpZone_Find(vector mi, vector ma);
-void WarpZone_MakeAllSolid();
-void WarpZone_MakeAllOther();
-
-#define MOVE_NOTHING -1
-entity WarpZone_trace_forent; // temp, callback is allowed to change it
-typedef void(vector start, vector hit, vector end) WarpZone_trace_callback_t; // called on every elementary trace
-var WarpZone_trace_callback_t WarpZone_trace_callback_t_null;
-entity WarpZone_trace_transform; // transform accumulator during a trace
-entity WarpZone_trace_firstzone; // first warpzone hit by a trace (can differ from the requested zone in case of _ThroughZone, the trace is aborted then)
-entity WarpZone_trace_lastzone; // first warpzone hit by a trace (can differ from the requested zone in case of _ThroughZone, the trace is aborted then)
-vector WarpZone_tracetoss_velocity; // ending velocity of a tracetoss (post-transform)
-float WarpZone_tracetoss_time; // duration of toss (approximate)
-void WarpZone_TraceBox(vector org, vector min, vector max, vector end, float nomonsters, entity forent);
-void WarpZone_TraceBox_ThroughZone(vector org, vector min, vector max, vector end, float nomonsters, entity forent, entity zone, WarpZone_trace_callback_t cb);
-void WarpZone_TraceLine(vector org, vector end, float nomonsters, entity forent);
-void WarpZone_TraceToss(entity e, entity forent);
-void WarpZone_TraceToss_ThroughZone(entity e, entity forent, entity zone, WarpZone_trace_callback_t cb);
-void WarpZone_TrailParticles(entity own, float eff, vector org, vector end);
-#ifdef CSQC
-void WarpZone_TrailParticles_WithMultiplier(entity own, float eff, vector org, vector end, float f, float boxflags);
-#endif
-
-.vector WarpZone_findradius_dist;
-.vector WarpZone_findradius_nearest;
-// also set: warpzone parameters, so WarpZone_TransformOrigin can transform vectors from blast's to victim's system
-.vector WarpZone_findradius_findorigin;
-.float WarpZone_findradius_findradius;
-entity WarpZone_FindRadius(vector org, float radius, float needlineofsight);
-
-float WarpZone_PlaneDist(entity wz, vector v);
-float WarpZone_TargetPlaneDist(entity wz, vector v);
-vector WarpZone_TransformOrigin(entity wz, vector v);
-vector WarpZone_TransformVelocity(entity wz, vector v);
-vector WarpZone_TransformAngles(entity wz, vector v);
-vector WarpZone_TransformVAngles(entity wz, vector v);
-vector WarpZone_UnTransformOrigin(entity wz, vector v);
-vector WarpZone_UnTransformVelocity(entity wz, vector v);
-vector WarpZone_UnTransformAngles(entity wz, vector v);
-vector WarpZone_UnTransformVAngles(entity wz, vector v);
-
-// reference systems (chained warpzone transforms)
-void WarpZone_RefSys_Clear(entity me); // R := id
-void WarpZone_RefSys_Add(entity me, entity wz); // me.R := wz me.R
-void WarpZone_RefSys_AddInverse(entity me, entity wz); // me.R := wz^-1 me.R
-void WarpZone_RefSys_AddTransform(entity me, vector t, vector s); // me.R := [t s] me.R
-void WarpZone_RefSys_AddInverseTransform(entity me, vector t, vector s); // me.R := [t s]^-1 me.R
-
-// makes this reference system track ref's changes
-// NOTE: this is ONLY sensible if WarpZone_RefSys_Add is no longer called on "me" while doing this
-// To achieve this, make sure no touch events on warpzone are raised by this entity
-// or set a movetype that causes no warpzoning (e.g. MOVETYPE_NONE, MOVETYPE_FOLLOW)
-void WarpZone_RefSys_AddIncrementally(entity me, entity ref); // me.R := ref.R me.Rref^-1 me.R; me.Rref := ref.R
-void WarpZone_RefSys_BeginAddingIncrementally(entity me, entity ref); // me.Rref := ref.R
-
-vector WarpZone_RefSys_TransformOrigin(entity from, entity to, vector org); // return to.R from.R^-1 org
-vector WarpZone_RefSys_TransformVelocity(entity from, entity to, vector vel); // return to.R from.R^-1 vel
-vector WarpZone_RefSys_TransformAngles(entity from, entity to, vector ang); // return to.R from.R^-1 ang
-vector WarpZone_RefSys_TransformVAngles(entity from, entity to, vector ang); // return to.R from.R^-1 ang
-void WarpZone_RefSys_Copy(entity me, entity from); // to.R := from.R
-entity WarpZone_RefSys_SpawnSameRefSys(entity me); // spawn().R = me.R
-
-#ifndef BITCLR
-# define BITCLR(a,b) ((a) - ((a) & (b)))
-#endif
-#ifndef BITSET
-# define BITSET(a,b) ((a) | (b))
-#endif
-#ifndef BITXOR
-# define BITXOR(a,b) (((a) | (b)) - ((a) & (b)))
-#endif
-#ifndef BITCLR_ASSIGN
-# define BITCLR_ASSIGN(a,b) ((a) = (a) - ((a) & (b)))
-#endif
-#ifndef BITSET_ASSIGN
-# define BITSET_ASSIGN(a,b) ((a) |= (b))
-#endif
-#ifndef BITXOR_ASSIGN
-# define BITXOR_ASSIGN(a,b) ((a) = ((a) | (b)) - ((a) & (b)))
-#endif
-float WarpZoneLib_MoveOutOfSolid(entity e);
-#define move_out_of_solid(e) WarpZoneLib_MoveOutOfSolid(e)
-
-float WarpZoneLib_ExactTrigger_Touch();
-void WarpZoneLib_ExactTrigger_Init();
-
-// WARNING: this kills the trace globals
-#define EXACTTRIGGER_TOUCH if(WarpZoneLib_ExactTrigger_Touch()) return
-#define EXACTTRIGGER_INIT  WarpZoneLib_ExactTrigger_Init()
-#endif
diff --git a/qcsrc/warpzonelib/mathlib.qc b/qcsrc/warpzonelib/mathlib.qc
deleted file mode 100644 (file)
index f61712d..0000000
+++ /dev/null
@@ -1,303 +0,0 @@
-#include "mathlib.qh"
-#if defined(CSQC)
-       #include "../dpdefs/csprogsdefs.qh"
-#elif defined(MENUQC)
-#elif defined(SVQC)
-    #include "../dpdefs/dpextensions.qh"
-       #include "../dpdefs/progsdefs.qh"
-#endif
-
-int fpclassify(float x)
-{
-       if(isnan(x))
-               return FP_NAN;
-       if(isinf(x))
-               return FP_INFINITE;
-       if(x == 0)
-               return FP_ZERO;
-       return FP_NORMAL;
-}
-bool isfinite(float x)
-{
-       return !(isnan(x) || isinf(x));
-}
-bool isinf(float x)
-{
-       return (x != 0) && (x + x == x);
-}
-bool isnan(float x)
-{
-       float y;
-       y = x;
-       return (x != y);
-}
-bool isnormal(float x)
-{
-       return isfinite(x);
-}
-bool signbit(float x)
-{
-       return (x < 0);
-}
-
-float acosh(float x)
-{
-       return log(x + sqrt(x*x - 1));
-}
-float asinh(float x)
-{
-       return log(x + sqrt(x*x + 1));
-}
-float atanh(float x)
-{
-       return 0.5 * log((1+x) / (1-x));
-}
-float cosh(float x)
-{
-       return 0.5 * (exp(x) + exp(-x));
-}
-float sinh(float x)
-{
-       return 0.5 * (exp(x) - exp(-x));
-}
-float tanh(float x)
-{
-       return sinh(x) / cosh(x);
-}
-
-float exp(float x)
-{
-       return pow(M_E, x);
-}
-float exp2(float x)
-{
-       return pow(2, x);
-}
-float expm1(float x)
-{
-       return exp(x) - 1;
-}
-
-vector frexp(float x)
-{
-       vector v;
-       v.z = 0;
-       v.y = ilogb(x) + 1;
-       v.x = x / exp2(v.y);
-       return v;
-}
-int ilogb(float x)
-{
-       return floor(log2(fabs(x)));
-}
-float ldexp(float x, int e)
-{
-       return x * pow(2, e);
-}
-float logn(float x, float base)
-{
-       return log(x) / log(base);
-}
-float log10(float x)
-{
-       return log(x) * M_LOG10E;
-}
-float log1p(float x)
-{
-       return log(x + 1);
-}
-float log2(float x)
-{
-       return log(x) * M_LOG2E;
-}
-float logb(float x)
-{
-       return floor(log2(fabs(x)));
-}
-vector modf(float f)
-{
-       return '1 0 0' * (f - trunc(f)) + '0 1 0' * trunc(f);
-}
-
-float scalbn(float x, int n)
-{
-       return x * pow(2, n);
-}
-
-float cbrt(float x)
-{
-       return copysign(pow(fabs(x), 1.0/3.0), x);
-}
-float hypot(float x, float y)
-{
-       return sqrt(x*x + y*y);
-}
-
-float erf(float x)
-{
-       // approximation taken from wikipedia
-       float y;
-       y = x*x;
-       return copysign(sqrt(1 - exp(-y * (1.273239544735163 + 0.14001228868667 * y) / (1 + 0.14001228868667 * y))), x);
-}
-float erfc(float x)
-{
-       return 1.0 - erf(x);
-}
-vector lgamma(float x)
-{
-       // TODO improve accuracy
-       if(!isfinite(x))
-               return fabs(x) * '1 0 0' + copysign(1, x) * '0 1 0';
-       if(x < 1 && x == floor(x))
-               return nan("gamma") * '1 1 1';
-       if(x < 0.1)
-       {
-               vector v;
-               v = lgamma(1.0 - x);
-               // reflection formula:
-               // gamma(1-z) * gamma(z) = pi / sin(pi*z)
-               // lgamma(1-z) + lgamma(z) = log(pi) - log(sin(pi*z))
-               // sign of gamma(1-z) = sign of gamma(z) * sign of sin(pi*z)
-               v.z = sin(M_PI * x);
-               v.x = log(M_PI) - log(fabs(v.z)) - v.x;
-               if(v.z < 0)
-                       v.y = -v.y;
-               v.z = 0;
-               return v;
-       }
-       if(x < 1.1)
-               return lgamma(x + 1) - log(x) * '1 0 0';
-       x -= 1;
-       return (0.5 * log(2 * M_PI * x) + x * (log(x) - 1)) * '1 0 0' + '0 1 0';
-}
-float tgamma(float x)
-{
-       vector v;
-       v = lgamma(x);
-       return exp(v.x) * v.y;
-}
-
-/**
- * Pythonic mod:
- * TODO: %% operator?
- *
- *  1 %  2 ==  1
- * -1 %  2 ==  1
- *  1 % -2 == -1
- * -1 % -2 == -1
- */
-float pymod(float x, float y)
-{
-       return x - y * floor(x / y);
-}
-
-float nearbyint(float x)
-{
-       return rint(x);
-}
-float trunc(float x)
-{
-       return (x>=0) ? floor(x) : ceil(x);
-}
-
-float fmod(float x, float y)
-{
-       return x - y * trunc(x / y);
-}
-float remainder(float x, float y)
-{
-       return x - y * rint(x / y);
-}
-vector remquo(float x, float y)
-{
-       vector v;
-       v.z = 0;
-       v.y = rint(x / y);
-       v.x = x - y * v.y;
-       return v;
-}
-
-float copysign(float x, float y)
-{
-       return fabs(x) * ((y>0) ? 1 : -1);
-}
-float nan(string tag)
-{
-       return sqrt(-1);
-}
-float nextafter(float x, float y)
-{
-       // TODO very crude
-       if(x == y)
-               return nan("nextafter");
-       if(x > y)
-               return -nextafter(-x, -y);
-       // now we know that x < y
-       // so we need the next number > x
-       float d, a, b;
-       d = max(fabs(x), 0.00000000000000000000001);
-       a = x + d;
-       do
-       {
-               d *= 0.5;
-               b = a;
-               a = x + d;
-       }
-       while(a != x);
-       return b;
-}
-float nexttoward(float x, float y)
-{
-       return nextafter(x, y);
-}
-
-float fdim(float x, float y)
-{
-       return max(x-y, 0);
-}
-float fmax(float x, float y)
-{
-       return max(x, y);
-}
-float fmin(float x, float y)
-{
-       return min(x, y);
-}
-float fma(float x, float y, float z)
-{
-       return x * y + z;
-}
-
-int isgreater(float x, float y)
-{
-       return x > y;
-}
-int isgreaterequal(float x, float y)
-{
-       return x >= y;
-}
-int isless(float x, float y)
-{
-       return x < y;
-}
-int islessequal(float x, float y)
-{
-       return x <= y;
-}
-int islessgreater(float x, float y)
-{
-       return x < y || x > y;
-}
-int isunordered(float x, float y)
-{
-       return !(x < y || x == y || x > y);
-}
-
-vector cross(vector a, vector b)
-{
-       return
-               '1 0 0' * (a.y * b.z - a.z * b.y)
-       +       '0 1 0' * (a.z * b.x - a.x * b.z)
-       +       '0 0 1' * (a.x * b.y - a.y * b.x);
-}
diff --git a/qcsrc/warpzonelib/mathlib.qh b/qcsrc/warpzonelib/mathlib.qh
deleted file mode 100644 (file)
index 6f7adf4..0000000
+++ /dev/null
@@ -1,121 +0,0 @@
-#ifndef MATHLIB_H
-#define MATHLIB_H
-
-// <math.h>
-
-// The commented-out functions need no implementation because DarkPlaces offers
-// them as builtins. They are listed here anyway for completeness sake.
-
-const int FP_NAN = 0;
-const int FP_INFINITE = 1;
-const int FP_ZERO = 2;
-const int FP_SUBNORMAL = 3;
-const int FP_NORMAL = 4;
-int fpclassify(float x);
-bool isfinite(float x);
-bool isinf(float x);
-bool isnan(float x);
-bool isnormal(float x);
-bool signbit(float x);
-
-//float acos(float x);
-//float asin(float x);
-//float atan(float x);
-//float atan2(float y, float x);
-//float cos(float x);
-//float sin(float x);
-//float tan(float x);
-
-float acosh(float x);
-float asinh(float x);
-float atanh(float x);
-float cosh(float x);
-float sinh(float x);
-float tanh(float x);
-
-float exp(float x);
-float exp2(float x);
-float expm1(float x);
-
-vector frexp(float x); // returns mantissa as _x, exponent as _y
-int ilogb(float x);
-float ldexp(float x, int e);
-//float log(float x);
-float logn(float x, float base);
-float log10(float x);
-float log1p(float x);
-float log2(float x);
-float logb(float x);
-vector modf(float f); // fraction as _x, integer as _y
-
-float scalbn(float x, int n);
-
-float cbrt(float x);
-//float fabs(float x);
-float hypot(float x, float y);
-//float pow(float x, float y);
-//float sqrt(float x, float y);
-
-float erf(float x);
-float erfc(float x);
-vector lgamma(float x); // value in _x, sign in _y
-float tgamma(float x);
-
-/**
- * Pythonic mod:
- * TODO: %% operator?
- *
- *  1 %  2 ==  1
- * -1 %  2 ==  1
- *  1 % -2 == -1
- * -1 % -2 == -1
- */
-float pymod(float x, float y);
-
-//float ceil(float x);
-//float floor(float x);
-float nearbyint(float x);
-//float rint(float x);
-//float round(float x);
-float trunc(float x);
-
-float fmod(float x, float y);
-float remainder(float x, float y);
-vector remquo(float x, float y);
-
-float copysign(float x, float y);
-float nan(string tag);
-float nextafter(float x, float y);
-float nexttoward(float x, float y);
-
-float fdim(float x, float y);
-float fmax(float x, float y);
-float fmin(float x, float y);
-float fma(float x, float y, float z);
-
-int isgreater(float x, float y);
-int isgreaterequal(float x, float y);
-int isless(float x, float y);
-int islessequal(float x, float y);
-int islessgreater(float x, float y);
-int isunordered(float x, float y);
-
-const float M_E        = 2.7182818284590452354;   /* e */
-const float M_LOG2E    = 1.4426950408889634074;   /* log_2 e */
-const float M_LOG10E   = 0.43429448190325182765;  /* log_10 e */
-const float M_LN2      = 0.69314718055994530942;  /* log_e 2 */
-const float M_LN10     = 2.30258509299404568402;  /* log_e 10 */
-// -Wdouble-declaration
-#define M_PI             3.14159265358979323846   /* pi */
-const float M_PI_2     = 1.57079632679489661923;  /* pi/2 */
-const float M_PI_4     = 0.78539816339744830962;  /* pi/4 */
-const float M_1_PI     = 0.31830988618379067154;  /* 1/pi */
-const float M_2_PI     = 0.63661977236758134308;  /* 2/pi */
-const float M_2_SQRTPI = 1.12837916709551257390;  /* 2/sqrt(pi) */
-const float M_SQRT2    = 1.41421356237309504880;  /* sqrt(2) */
-const float M_SQRT1_2  = 0.70710678118654752440;  /* 1/sqrt(2) */
-
-// Non-<math.h> stuff follows here.
-vector cross(vector a, vector b);
-
-#endif
diff --git a/qcsrc/warpzonelib/server.qc b/qcsrc/warpzonelib/server.qc
deleted file mode 100644 (file)
index d34870e..0000000
+++ /dev/null
@@ -1,901 +0,0 @@
-#include "server.qh"
-
-#include "common.qh"
-#if defined(CSQC)
-#elif defined(MENUQC)
-#elif defined(SVQC)
-       #include "../common/constants.qh"
-       #include "../common/triggers/subs.qh"
-       #include "../common/util.qh"
-       #include "../dpdefs/dpextensions.qh"
-       #include "../dpdefs/progsdefs.qh"
-       #include "../server/command/common.qh"
-       #include "../server/constants.qh"
-       #include "../server/defs.qh"
-#endif
-
-#ifdef WARPZONELIB_KEEPDEBUG
-#define WARPZONELIB_REMOVEHACK
-#endif
-
-// for think function
-.vector warpzone_save_origin;
-.vector warpzone_save_angles;
-.vector warpzone_save_eorigin;
-.vector warpzone_save_eangles;
-
-// for all entities
-.vector warpzone_oldorigin, warpzone_oldvelocity, warpzone_oldangles;
-.float warpzone_teleport_time;
-.float warpzone_teleport_finishtime;
-.entity warpzone_teleport_zone;
-
-void WarpZone_StoreProjectileData(entity e)
-{
-       e.warpzone_oldorigin = e.origin;
-       e.warpzone_oldvelocity = e.velocity;
-       e.warpzone_oldangles = e.angles;
-}
-
-void WarpZone_TeleportPlayer(entity teleporter, entity player, vector to, vector to_angles, vector to_velocity)
-{
-       setorigin (player, to); // NOTE: this also aborts the move, when this is called by touch
-       player.oldorigin = to; // for DP's unsticking
-       player.angles = to_angles;
-       player.fixangle = true;
-       player.velocity = to_velocity;
-
-       BITXOR_ASSIGN(player.effects, EF_TELEPORT_BIT);
-
-       if(IS_PLAYER(player))
-               BITCLR_ASSIGN(player.flags, FL_ONGROUND);
-
-       WarpZone_PostTeleportPlayer_Callback(player);
-}
-
-bool WarpZone_Teleported_Send(entity to, int sf)
-{SELFPARAM();
-       WriteByte(MSG_ENTITY, ENT_CLIENT_WARPZONE_TELEPORTED);
-       WriteCoord(MSG_ENTITY, self.angles.x);
-       WriteCoord(MSG_ENTITY, self.angles.y);
-       WriteCoord(MSG_ENTITY, self.angles.z);
-       return true;
-}
-
-float WarpZone_Teleport(entity wz, entity player, float f0, float f1)
-{
-       vector o0, a0, v0, o1, a1, v1, o10;
-
-       o0 = player.origin + player.view_ofs;
-       v0 = player.velocity;
-       a0 = player.angles;
-
-       o10 = o1 = WarpZone_TransformOrigin(wz, o0);
-       v1 = WarpZone_TransformVelocity(wz, v0);
-       if (!IS_NOT_A_CLIENT(player))
-               a1 = WarpZone_TransformVAngles(wz, player.v_angle);
-       else
-               a1 = WarpZone_TransformAngles(wz, a0);
-
-       if(f0 != 0 || f1 != 0)
-       {
-               // retry last move but behind the warpzone!
-               // we must first go back as far as we can, then forward again, to not cause double touch events!
-
-               tracebox(o1 - player.view_ofs + v1 * frametime * f1, player.mins, player.maxs, o1 - player.view_ofs + v1 * frametime * f0, MOVE_WORLDONLY, player);
-               {
-                       entity own;
-                       own = player.owner;
-                       player.owner = world;
-                       tracebox(trace_endpos, player.mins, player.maxs, o1 - player.view_ofs + v1 * frametime * f1, MOVE_NORMAL, player); // this should get us through the warpzone
-                       player.owner = own;
-               }
-               o1 = trace_endpos + player.view_ofs;
-
-               float d, dv, md;
-               md = max(vlen(player.mins), vlen(player.maxs));
-               d = WarpZone_TargetPlaneDist(wz, o1);
-               dv = WarpZone_TargetPlaneDist(wz, v1);
-               if(d < 0)
-                       o1 = o1 - v1 * (d / dv);
-       }
-
-       // put him out of solid
-       tracebox(o1 - player.view_ofs, player.mins, player.maxs, o1 - player.view_ofs, MOVE_NOMONSTERS, player);
-       if(trace_startsolid)
-       {
-               setorigin(player, o1 - player.view_ofs);
-               if(WarpZoneLib_MoveOutOfSolid(player))
-               {
-                       o1 = player.origin + player.view_ofs;
-                       setorigin(player, o0 - player.view_ofs);
-               }
-               else
-               {
-                       LOG_INFO("would have to put player in solid, won't do that\n");
-                       setorigin(player, o0 - player.view_ofs);
-                       return 0;
-               }
-       }
-
-       // do the teleport
-       WarpZone_RefSys_Add(player, wz);
-       WarpZone_TeleportPlayer(wz, player, o1 - player.view_ofs, a1, v1);
-       WarpZone_StoreProjectileData(player);
-       player.warpzone_teleport_time = time;
-       player.warpzone_teleport_finishtime = time;
-       player.warpzone_teleport_zone = wz;
-
-       // prevent further teleports back
-       float dt = (o1 - o10) * v1 * (1 / (v1 * v1));
-       if(dt < sys_frametime)
-               player.warpzone_teleport_finishtime += sys_frametime - dt;
-
-#ifndef WARPZONE_USE_FIXANGLE
-       if(IS_VEHICLE(player) && player.owner)
-               player = player.owner; // hax
-       if(IS_PLAYER(player))
-       {
-               // instead of fixangle, send the transform to the client for smoother operation
-               player.fixangle = false;
-
-               entity ts = spawn();
-               setmodel(ts, MDL_Null);
-               ts.SendEntity = WarpZone_Teleported_Send;
-               ts.SendFlags = 0xFFFFFF;
-               ts.drawonlytoclient = player;
-               ts.think = SUB_Remove;
-               ts.nextthink = time + 1;
-               ts.owner = player;
-               ts.enemy = wz;
-               ts.effects = EF_NODEPTHTEST;
-               ts.classname = "warpzone_teleported";
-               ts.angles = wz.warpzone_transform;
-       }
-#endif
-
-       return 1;
-}
-
-void WarpZone_Touch (void)
-{SELFPARAM();
-       if(other.classname == "trigger_warpzone")
-               return;
-
-       if(time <= other.warpzone_teleport_finishtime) // already teleported this frame
-               return;
-
-       // FIXME needs a better check to know what is safe to teleport and what not
-       if(other.movetype == MOVETYPE_NONE || other.movetype == MOVETYPE_FOLLOW || other.tag_entity)
-               return;
-
-       if(WarpZoneLib_ExactTrigger_Touch())
-               return;
-
-       if(WarpZone_PlaneDist(self, other.origin + other.view_ofs) >= 0) // wrong side of the trigger_warpzone (don't teleport yet)
-               return;
-
-       float f;
-       // number of frames we need to go back:
-       //   dist = 16*sqrt(2) qu
-       //   dist ~ 24 qu
-       //   24 qu = v*t
-       //   24 qu = v*frametime*n
-       //       n = 24 qu/(v*frametime)
-       // for clients go only one frame though, may be too irritating otherwise
-       // but max 0.25 sec = 0.25/frametime frames
-       //       24/(0.25/frametime)
-       //       96*frametime
-       float d;
-       d = 24 + max(vlen(other.mins), vlen(other.maxs));
-       if(IS_NOT_A_CLIENT(other))
-               f = -d / bound(frametime * d * 1, frametime * vlen(other.velocity), d);
-       else
-               f = -1;
-       if(WarpZone_Teleport(self, other, f, 0))
-       {
-               string save1, save2;
-               activator = other;
-
-               save1 = self.target; self.target = string_null;
-               save2 = self.target3; self.target3 = string_null;
-               SUB_UseTargets();
-               if (!self.target) self.target = save1;
-               if (!self.target3) self.target3 = save2;
-
-               setself(self.enemy);
-               save1 = self.target; self.target = string_null;
-               save2 = self.target2; self.target2 = string_null;
-               SUB_UseTargets();
-               if (!self.target) self.target = save1;
-               if (!self.target2) self.target2 = save2;
-               setself(this);
-       }
-       else
-       {
-               LOG_TRACE("WARPZONE FAIL AHAHAHAHAH))\n");
-       }
-}
-
-bool WarpZone_Send(entity to, int sendflags)
-{SELFPARAM();
-       WriteByte(MSG_ENTITY, ENT_CLIENT_WARPZONE);
-
-       // we must send this flag for clientside to match properly too
-       int f = 0;
-       if(self.warpzone_isboxy)
-               BITSET_ASSIGN(f, 1);
-       if(self.warpzone_fadestart)
-               BITSET_ASSIGN(f, 2);
-       if(self.origin != '0 0 0')
-               BITSET_ASSIGN(f, 4);
-       WriteByte(MSG_ENTITY, f);
-
-       // we need THESE to render the warpzone (and cull properly)...
-       if(f & 4)
-       {
-               WriteCoord(MSG_ENTITY, self.origin.x);
-               WriteCoord(MSG_ENTITY, self.origin.y);
-               WriteCoord(MSG_ENTITY, self.origin.z);
-       }
-
-       WriteShort(MSG_ENTITY, self.modelindex);
-       WriteCoord(MSG_ENTITY, self.mins.x);
-       WriteCoord(MSG_ENTITY, self.mins.y);
-       WriteCoord(MSG_ENTITY, self.mins.z);
-       WriteCoord(MSG_ENTITY, self.maxs.x);
-       WriteCoord(MSG_ENTITY, self.maxs.y);
-       WriteCoord(MSG_ENTITY, self.maxs.z);
-       WriteByte(MSG_ENTITY, bound(1, self.scale * 16, 255));
-
-       // we need THESE to calculate the proper transform
-       WriteCoord(MSG_ENTITY, self.warpzone_origin.x);
-       WriteCoord(MSG_ENTITY, self.warpzone_origin.y);
-       WriteCoord(MSG_ENTITY, self.warpzone_origin.z);
-       WriteCoord(MSG_ENTITY, self.warpzone_angles.x);
-       WriteCoord(MSG_ENTITY, self.warpzone_angles.y);
-       WriteCoord(MSG_ENTITY, self.warpzone_angles.z);
-       WriteCoord(MSG_ENTITY, self.warpzone_targetorigin.x);
-       WriteCoord(MSG_ENTITY, self.warpzone_targetorigin.y);
-       WriteCoord(MSG_ENTITY, self.warpzone_targetorigin.z);
-       WriteCoord(MSG_ENTITY, self.warpzone_targetangles.x);
-       WriteCoord(MSG_ENTITY, self.warpzone_targetangles.y);
-       WriteCoord(MSG_ENTITY, self.warpzone_targetangles.z);
-
-       if(f & 2)
-       {
-               WriteShort(MSG_ENTITY, self.warpzone_fadestart);
-               WriteShort(MSG_ENTITY, self.warpzone_fadeend);
-       }
-
-       return true;
-}
-
-bool WarpZone_Camera_Send(entity to, int sendflags)
-{SELFPARAM();
-       int f = 0;
-       WriteByte(MSG_ENTITY, ENT_CLIENT_WARPZONE_CAMERA);
-
-       if(self.warpzone_fadestart)
-               BITSET_ASSIGN(f, 2);
-       if(self.origin != '0 0 0')
-               BITSET_ASSIGN(f, 4);
-       WriteByte(MSG_ENTITY, f);
-
-       // we need THESE to render the warpzone (and cull properly)...
-       if(f & 4)
-       {
-               WriteCoord(MSG_ENTITY, self.origin.x);
-               WriteCoord(MSG_ENTITY, self.origin.y);
-               WriteCoord(MSG_ENTITY, self.origin.z);
-       }
-
-       WriteShort(MSG_ENTITY, self.modelindex);
-       WriteCoord(MSG_ENTITY, self.mins.x);
-       WriteCoord(MSG_ENTITY, self.mins.y);
-       WriteCoord(MSG_ENTITY, self.mins.z);
-       WriteCoord(MSG_ENTITY, self.maxs.x);
-       WriteCoord(MSG_ENTITY, self.maxs.y);
-       WriteCoord(MSG_ENTITY, self.maxs.z);
-       WriteByte(MSG_ENTITY, bound(1, self.scale * 16, 255));
-
-       // we need THESE to calculate the proper transform
-       WriteCoord(MSG_ENTITY, self.enemy.origin.x);
-       WriteCoord(MSG_ENTITY, self.enemy.origin.y);
-       WriteCoord(MSG_ENTITY, self.enemy.origin.z);
-       WriteCoord(MSG_ENTITY, self.enemy.angles.x);
-       WriteCoord(MSG_ENTITY, self.enemy.angles.y);
-       WriteCoord(MSG_ENTITY, self.enemy.angles.z);
-
-       if(f & 2)
-       {
-               WriteShort(MSG_ENTITY, self.warpzone_fadestart);
-               WriteShort(MSG_ENTITY, self.warpzone_fadeend);
-       }
-
-       return true;
-}
-
-#ifdef WARPZONELIB_KEEPDEBUG
-float WarpZone_CheckProjectileImpact(entity player)
-{SELFPARAM();
-       vector o0, v0;
-
-       o0 = player.origin + player.view_ofs;
-       v0 = player.velocity;
-
-       // if we teleported shortly before, abort
-       if(time <= player.warpzone_teleport_finishtime + 0.1)
-               return 0;
-
-       // if player hit a warpzone, abort
-       entity wz;
-       wz = WarpZone_Find(o0 + player.mins, o0 + player.maxs);
-       if(!wz)
-               return 0;
-
-#ifdef WARPZONELIB_REMOVEHACK
-       LOG_INFO("impactfilter found something - and it no longer gets handled correctly - please tell divVerent whether anything behaves broken now\n");
-#else
-       LOG_INFO("impactfilter found something - and it even gets handled correctly - please tell divVerent that this code apparently gets triggered again\n");
-#endif
-       LOG_INFO("Entity type: ", player.classname, "\n");
-       LOG_INFO("Origin: ", vtos(player.origin), "\n");
-       LOG_INFO("Velocity: ", vtos(player.velocity), "\n");
-
-#ifdef WARPZONELIB_REMOVEHACK
-       return 0;
-#else
-       // retry previous move
-       setorigin(player, player.warpzone_oldorigin);
-       player.velocity = player.warpzone_oldvelocity;
-       if(WarpZone_Teleport(wz, player, 0, 1))
-       {
-               entity oldself;
-               string save1, save2;
-
-               oldself = self;
-               self = wz;
-               other = player;
-               activator = player;
-
-               save1 = self.target; self.target = string_null;
-               save2 = self.target3; self.target3 = string_null;
-               SUB_UseTargets();
-               if (!self.target) self.target = save1;
-               if (!self.target3) self.target3 = save2;
-
-               self = self.enemy;
-               save1 = self.target; self.target = string_null;
-               save2 = self.target2; self.target2 = string_null;
-               SUB_UseTargets();
-               if (!self.target) self.target = save1;
-               if (!self.target2) self.target2 = save2;
-               self = oldself;
-       }
-       else
-       {
-               setorigin(player, o0 - player.view_ofs);
-               player.velocity = v0;
-       }
-
-       return +1;
-#endif
-}
-#endif
-
-float WarpZone_Projectile_Touch()
-{SELFPARAM();
-       if(other.classname == "trigger_warpzone")
-               return true;
-
-       // no further impacts if we teleported this frame!
-       // this is because even if we did teleport, the engine still may raise
-       // touch events for the previous location
-       // engine now aborts moves on teleport, so this SHOULD not happen any more
-       // but if this is called from TouchAreaGrid of the projectile moving,
-       // then this won't do
-       if(time == self.warpzone_teleport_time)
-               return true;
-
-#ifdef WARPZONELIB_KEEPDEBUG
-       // this SEEMS to not happen at the moment, but if it did, it would be more reliable
-       {
-               float save_dpstartcontents;
-               float save_dphitcontents;
-               float save_dphitq3surfaceflags;
-               string save_dphittexturename;
-               float save_allsolid;
-               float save_startsolid;
-               float save_fraction;
-               vector save_endpos;
-               vector save_plane_normal;
-               float save_plane_dist;
-               entity save_ent;
-               float save_inopen;
-               float save_inwater;
-               save_dpstartcontents = trace_dpstartcontents;
-               save_dphitcontents = trace_dphitcontents;
-               save_dphitq3surfaceflags = trace_dphitq3surfaceflags;
-               save_dphittexturename = trace_dphittexturename;
-               save_allsolid = trace_allsolid;
-               save_startsolid = trace_startsolid;
-               save_fraction = trace_fraction;
-               save_endpos = trace_endpos;
-               save_plane_normal = trace_plane_normal;
-               save_plane_dist = trace_plane_dist;
-               save_ent = trace_ent;
-               save_inopen = trace_inopen;
-               save_inwater = trace_inwater;
-               float f;
-               if((f = WarpZone_CheckProjectileImpact(self)) != 0)
-                       return (f > 0);
-               trace_dpstartcontents = save_dpstartcontents;
-               trace_dphitcontents = save_dphitcontents;
-               trace_dphitq3surfaceflags = save_dphitq3surfaceflags;
-               trace_dphittexturename = save_dphittexturename;
-               trace_allsolid = save_allsolid;
-               trace_startsolid = save_startsolid;
-               trace_fraction = save_fraction;
-               trace_endpos = save_endpos;
-               trace_plane_normal = save_plane_normal;
-               trace_plane_dist = save_plane_dist;
-               trace_ent = save_ent;
-               trace_inopen = save_inopen;
-               trace_inwater = save_inwater;
-       }
-#endif
-
-       if(WarpZone_Projectile_Touch_ImpactFilter_Callback())
-               return true;
-
-       return false;
-}
-
-void WarpZone_InitStep_FindOriginTarget()
-{SELFPARAM();
-       if(self.killtarget != "")
-       {
-               self.aiment = find(world, targetname, self.killtarget);
-               if(self.aiment == world)
-               {
-                       error("Warp zone with nonexisting killtarget");
-                       return;
-               }
-               self.killtarget = string_null;
-       }
-}
-
-void WarpZonePosition_InitStep_FindTarget()
-{SELFPARAM();
-       if(self.target == "")
-       {
-               error("Warp zone position with no target");
-               return;
-       }
-       self.enemy = find(world, targetname, self.target);
-       if(self.enemy == world)
-       {
-               error("Warp zone position with nonexisting target");
-               return;
-       }
-       if(self.enemy.aiment)
-       {
-               // already is positioned
-               error("Warp zone position targeting already oriented warpzone");
-               return;
-       }
-       self.enemy.aiment = self;
-}
-
-void WarpZoneCamera_Think(void)
-{SELFPARAM();
-       if(self.warpzone_save_origin != self.origin
-       || self.warpzone_save_angles != self.angles
-       || self.warpzone_save_eorigin != self.enemy.origin
-       || self.warpzone_save_eangles != self.enemy.angles)
-       {
-               WarpZone_Camera_SetUp(self, self.enemy.origin, self.enemy.angles);
-               self.warpzone_save_origin = self.origin;
-               self.warpzone_save_angles = self.angles;
-               self.warpzone_save_eorigin = self.enemy.origin;
-               self.warpzone_save_eangles = self.enemy.angles;
-       }
-       self.nextthink = time;
-}
-
-void WarpZoneCamera_InitStep_FindTarget()
-{SELFPARAM();
-       entity e;
-       float i;
-       if(self.target == "")
-       {
-               error("Camera with no target");
-               return;
-       }
-       self.enemy = world;
-       for(e = world, i = 0; (e = find(e, targetname, self.target)); )
-               if(random() * ++i < 1)
-                       self.enemy = e;
-       if(self.enemy == world)
-       {
-               error("Camera with nonexisting target");
-               return;
-       }
-       warpzone_cameras_exist = 1;
-       WarpZone_Camera_SetUp(self, self.enemy.origin, self.enemy.angles);
-       self.SendFlags = 0xFFFFFF;
-       if(self.spawnflags & 1)
-       {
-               self.think = WarpZoneCamera_Think;
-               self.nextthink = time;
-       }
-       else
-               self.nextthink = 0;
-}
-
-void WarpZone_InitStep_UpdateTransform()
-{SELFPARAM();
-       vector org, ang, norm, point;
-       float area;
-       vector tri, a, b, c, n;
-       float i_s, i_t, n_t;
-       string tex;
-
-       org = self.origin;
-       if(org == '0 0 0')
-               org = 0.5 * (self.mins + self.maxs);
-
-       norm = point = '0 0 0';
-       area = 0;
-       for(i_s = 0; ; ++i_s)
-       {
-               tex = getsurfacetexture(self, i_s);
-               if (!tex)
-                       break; // this is beyond the last one
-               if(tex == "textures/common/trigger" || tex == "trigger")
-                       continue;
-               n_t = getsurfacenumtriangles(self, i_s);
-               for(i_t = 0; i_t < n_t; ++i_t)
-               {
-                       tri = getsurfacetriangle(self, i_s, i_t);
-                       a = getsurfacepoint(self, i_s, tri.x);
-                       b = getsurfacepoint(self, i_s, tri.y);
-                       c = getsurfacepoint(self, i_s, tri.z);
-                       n = cross(c - a, b - a);
-                       area = area + vlen(n);
-                       norm = norm + n;
-                       point = point + vlen(n) * (a + b + c);
-               }
-       }
-       if(area > 0)
-       {
-               norm = norm * (1 / area);
-               point = point * (1 / (3 * area));
-               if(vlen(norm) < 0.99)
-               {
-                       LOG_INFO("trigger_warpzone near ", vtos(self.aiment.origin), " is nonplanar. BEWARE.\n");
-                       area = 0; // no autofixing in this case
-               }
-               norm = normalize(norm);
-       }
-
-       ang = '0 0 0';
-       if(self.aiment)
-       {
-               org = self.aiment.origin;
-               ang = self.aiment.angles;
-               if(area > 0)
-               {
-                       org = org - ((org - point) * norm) * norm; // project to plane
-                       makevectors(ang);
-                       if(norm * v_forward < 0)
-                       {
-                               LOG_INFO("Position target of trigger_warpzone near ", vtos(self.aiment.origin), " points into trigger_warpzone. BEWARE.\n");
-                               norm = -1 * norm;
-                       }
-                       ang = vectoangles2(norm, v_up); // keep rotation, but turn exactly against plane
-                       ang.x = -ang.x;
-                       if(norm * v_forward < 0.99)
-                               LOG_INFO("trigger_warpzone near ", vtos(self.aiment.origin), " has been turned to match plane orientation (", vtos(self.aiment.angles), " -> ", vtos(ang), "\n");
-                       if(vlen(org - self.aiment.origin) > 0.5)
-                               LOG_INFO("trigger_warpzone near ", vtos(self.aiment.origin), " has been moved to match the plane (", vtos(self.aiment.origin), " -> ", vtos(org), ").\n");
-               }
-       }
-       else if(area > 0)
-       {
-               org = point;
-               ang = vectoangles(norm);
-               ang.x = -ang.x;
-       }
-       else
-               error("cannot infer origin/angles for this warpzone, please use a killtarget or a trigger_warpzone_position");
-
-       self.warpzone_origin = org;
-       self.warpzone_angles = ang;
-}
-
-void WarpZone_InitStep_ClearTarget()
-{SELFPARAM();
-       if(self.enemy)
-               self.enemy.enemy = world;
-       self.enemy = world;
-}
-
-entity warpzone_first; .entity warpzone_next;
-void WarpZone_InitStep_FindTarget()
-{SELFPARAM();
-       float i;
-       entity e, e2;
-
-       if(self.enemy)
-               return;
-
-       // this way only one of the two ents needs to target
-       if(self.target != "")
-       {
-               self.enemy = self; // so the if(!e.enemy) check also skips self, saves one IF
-
-               e2 = world;
-               for(e = world, i = 0; (e = find(e, targetname, self.target)); )
-                       if(!e.enemy)
-                               if(e.classname == self.classname) // possibly non-warpzones may use the same targetname!
-                                       if(random() * ++i < 1)
-                                               e2 = e;
-               if(!e2)
-               {
-                       self.enemy = world;
-                       error("Warpzone with non-existing target");
-                       return;
-               }
-               self.enemy = e2;
-               e2.enemy = self;
-       }
-}
-
-void WarpZone_Think();
-void WarpZone_InitStep_FinalizeTransform()
-{SELFPARAM();
-       if(!self.enemy || self.enemy.enemy != self)
-       {
-               error("Invalid warp zone detected. Killed.");
-               return;
-       }
-
-       warpzone_warpzones_exist = 1;
-       WarpZone_SetUp(self, self.warpzone_origin, self.warpzone_angles, self.enemy.warpzone_origin, self.enemy.warpzone_angles);
-       self.touch = WarpZone_Touch;
-       self.SendFlags = 0xFFFFFF;
-       if(self.spawnflags & 1)
-       {
-               self.think = WarpZone_Think;
-               self.nextthink = time;
-       }
-       else
-               self.nextthink = 0;
-}
-
-float warpzone_initialized;
-//entity warpzone_first;
-entity warpzone_position_first;
-entity warpzone_camera_first;
-.entity warpzone_next;
-spawnfunc(misc_warpzone_position)
-{
-       // "target", "angles", "origin"
-       self.warpzone_next = warpzone_position_first;
-       warpzone_position_first = self;
-}
-spawnfunc(trigger_warpzone_position)
-{
-       spawnfunc_misc_warpzone_position(this);
-}
-spawnfunc(trigger_warpzone)
-{
-       // warp zone entities must have:
-       // "killtarget" pointing to a target_position with a direction arrow
-       //              that points AWAY from the warp zone, and that is inside
-       //              the warp zone trigger
-       // "target"     pointing to an identical warp zone at another place in
-       //              the map, with another killtarget to designate its
-       //              orientation
-
-       if(!self.scale)
-               self.scale = self.modelscale;
-       if(!self.scale)
-               self.scale = 1;
-       string m;
-       m = self.model;
-       WarpZoneLib_ExactTrigger_Init();
-       if(m != "")
-       {
-               precache_model(m);
-               _setmodel(self, m); // no precision needed
-       }
-       setorigin(self, self.origin);
-       if(self.scale)
-               setsize(self, self.mins * self.scale, self.maxs * self.scale);
-       else
-               setsize(self, self.mins, self.maxs);
-       self.SendEntity = WarpZone_Send;
-       self.SendFlags = 0xFFFFFF;
-       BITSET_ASSIGN(self.effects, EF_NODEPTHTEST);
-       self.warpzone_next = warpzone_first;
-       warpzone_first = self;
-}
-spawnfunc(func_camera)
-{
-       if(!self.scale)
-               self.scale = self.modelscale;
-       if(!self.scale)
-               self.scale = 1;
-       if(self.model != "")
-       {
-               precache_model(self.model);
-               _setmodel(self, self.model); // no precision needed
-       }
-       setorigin(self, self.origin);
-       if(self.scale)
-               setsize(self, self.mins * self.scale, self.maxs * self.scale);
-       else
-               setsize(self, self.mins, self.maxs);
-       if(!self.solid)
-               self.solid = SOLID_BSP;
-       else if(self.solid < 0)
-               self.solid = SOLID_NOT;
-       self.SendEntity = WarpZone_Camera_Send;
-       self.SendFlags = 0xFFFFFF;
-       self.warpzone_next = warpzone_camera_first;
-       warpzone_camera_first = self;
-}
-void WarpZones_Reconnect()
-{SELFPARAM();
-       for(setself(warpzone_first); self; setself(self.warpzone_next))
-               WarpZone_InitStep_ClearTarget();
-       for(setself(warpzone_first); self; setself(self.warpzone_next))
-               WarpZone_InitStep_FindTarget();
-       for(setself(warpzone_camera_first); self; setself(self.warpzone_next))
-               WarpZoneCamera_InitStep_FindTarget();
-       for(setself(warpzone_first); self; setself(self.warpzone_next))
-               WarpZone_InitStep_FinalizeTransform();
-       setself(this);
-}
-
-void WarpZone_Think()
-{SELFPARAM();
-       if(self.warpzone_save_origin != self.origin
-       || self.warpzone_save_angles != self.angles
-       || self.warpzone_save_eorigin != self.enemy.origin
-       || self.warpzone_save_eangles != self.enemy.angles)
-       {
-               WarpZone_InitStep_UpdateTransform();
-               setself(self.enemy);
-               WarpZone_InitStep_UpdateTransform();
-               setself(this);
-               WarpZone_InitStep_FinalizeTransform();
-               setself(self.enemy);
-               WarpZone_InitStep_FinalizeTransform();
-               setself(this);
-               self.warpzone_save_origin = self.origin;
-               self.warpzone_save_angles = self.angles;
-               self.warpzone_save_eorigin = self.enemy.origin;
-               self.warpzone_save_eangles = self.enemy.angles;
-       }
-       self.nextthink = time;
-}
-
-void WarpZone_StartFrame()
-{SELFPARAM();
-       entity e;
-       if(warpzone_initialized == 0)
-       {
-               warpzone_initialized = 1;
-               for(setself(warpzone_first); self; setself(self.warpzone_next))
-                       WarpZone_InitStep_FindOriginTarget();
-               for(setself(warpzone_position_first); self; setself(self.warpzone_next))
-                       WarpZonePosition_InitStep_FindTarget();
-               for(setself(warpzone_first); self; setself(self.warpzone_next))
-                       WarpZone_InitStep_UpdateTransform();
-               setself(this);
-               WarpZones_Reconnect();
-               WarpZone_PostInitialize_Callback();
-       }
-
-       entity oldother;
-       oldother = other;
-       for(e = world; (e = nextent(e)); )
-       {
-               if(warpzone_warpzones_exist) { WarpZone_StoreProjectileData(e); }
-
-               if(IS_REAL_CLIENT(e))
-               {
-                       if(e.solid == SOLID_NOT) // not spectating?
-                       if(e.movetype == MOVETYPE_NOCLIP || e.movetype == MOVETYPE_FLY || e.movetype == MOVETYPE_FLY_WORLDONLY) // not spectating? (this is to catch observers)
-                       {
-                               other = e; // player
-
-                               // warpzones
-                               if(warpzone_warpzones_exist) {
-                               setself(WarpZone_Find(e.origin + e.mins, e.origin + e.maxs));
-                               if(self)
-                               if(!WarpZoneLib_ExactTrigger_Touch())
-                                       if(WarpZone_PlaneDist(self, e.origin + e.view_ofs) <= 0)
-                                               WarpZone_Teleport(self, e, -1, 0); } // NOT triggering targets by this!
-
-                               // teleporters
-                               setself(Teleport_Find(e.origin + e.mins, e.origin + e.maxs));
-                               if(self)
-                               if(!WarpZoneLib_ExactTrigger_Touch())
-                                       Simple_TeleportPlayer(self, other); // NOT triggering targets by this!
-                       }
-               }
-
-               if(IS_NOT_A_CLIENT(e))
-               {
-                       if(warpzone_warpzones_exist)
-                               for (; (e = nextent(e)); )
-                                       WarpZone_StoreProjectileData(e);
-                       break;
-               }
-       }
-       setself(this);
-       other = oldother;
-}
-
-.float warpzone_reconnecting;
-float visible_to_some_client(entity ent)
-{
-       entity e;
-       for(e = nextent(world); !IS_NOT_A_CLIENT(e); e = nextent(e))
-               if(IS_PLAYER(e) && IS_REAL_CLIENT(e))
-                       if(checkpvs(e.origin + e.view_ofs, ent))
-                               return 1;
-       return 0;
-}
-void trigger_warpzone_reconnect_use()
-{SELFPARAM();
-       entity e;
-       e = self;
-       // NOTE: this matches for target, not targetname, but of course
-       // targetname must be set too on the other entities
-       for(setself(warpzone_first); self; setself(self.warpzone_next))
-               self.warpzone_reconnecting = ((e.target == "" || self.target == e.target) && !((e.spawnflags & 1) && (visible_to_some_client(self) || visible_to_some_client(self.enemy))));
-       for(setself(warpzone_camera_first); self; setself(self.warpzone_next))
-               self.warpzone_reconnecting = ((e.target == "" || self.target == e.target) && !((e.spawnflags & 1) && visible_to_some_client(self)));
-       for(setself(warpzone_first); self; setself(self.warpzone_next))
-               if(self.warpzone_reconnecting)
-                       WarpZone_InitStep_ClearTarget();
-       for(setself(warpzone_first); self; setself(self.warpzone_next))
-               if(self.warpzone_reconnecting)
-                       WarpZone_InitStep_FindTarget();
-       for(setself(warpzone_camera_first); self; setself(self.warpzone_next))
-               if(self.warpzone_reconnecting)
-                       WarpZoneCamera_InitStep_FindTarget();
-       for(setself(warpzone_first); self; setself(self.warpzone_next))
-               if(self.warpzone_reconnecting || self.enemy.warpzone_reconnecting)
-                       WarpZone_InitStep_FinalizeTransform();
-       setself(e);
-}
-
-spawnfunc(trigger_warpzone_reconnect)
-{
-       self.use = trigger_warpzone_reconnect_use;
-}
-
-spawnfunc(target_warpzone_reconnect)
-{
-       spawnfunc_trigger_warpzone_reconnect(this); // both names make sense here :(
-}
-
-void WarpZone_PlayerPhysics_FixVAngle(void)
-{SELFPARAM();
-#ifndef WARPZONE_DONT_FIX_VANGLE
-       if(IS_REAL_CLIENT(self))
-       if(self.v_angle.z <= 360) // if not already adjusted
-       if(time - self.ping * 0.001 < self.warpzone_teleport_time)
-       {
-               self.v_angle = WarpZone_TransformVAngles(self.warpzone_teleport_zone, self.v_angle);
-               self.v_angle_z += 720; // mark as adjusted
-       }
-#endif
-}
diff --git a/qcsrc/warpzonelib/server.qh b/qcsrc/warpzonelib/server.qh
deleted file mode 100644 (file)
index 88ad6f5..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-#ifndef SERVER_H
-#define SERVER_H
-
-void WarpZone_StartFrame();
-float WarpZone_Projectile_Touch();
-
-// THESE must be defined by calling QC code:
-void WarpZone_PostTeleportPlayer_Callback(entity pl);
-float WarpZone_Projectile_Touch_ImpactFilter_Callback();
-
-// server must also define a float called ENT_CLIENT_WARPZONE for the initial byte of WarpZone entities
-//const float ENT_CLIENT_WARPZONE;
-//const float ENT_CLIENT_WARPZONE_CAMERA;
-
-void WarpZone_PlayerPhysics_FixVAngle(void);
-
-void WarpZone_PostInitialize_Callback(void);
-#endif
diff --git a/qcsrc/warpzonelib/util_server.qc b/qcsrc/warpzonelib/util_server.qc
deleted file mode 100644 (file)
index 0b983c2..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-#include "util_server.qh"
-
-#include "common.qh"
-
-#if defined(CSQC)
-#elif defined(MENUQC)
-#elif defined(SVQC)
-    #include "../csqcmodellib/sv_model.qh"
-    #include "../dpdefs/dpextensions.qh"
-       #include "../dpdefs/progsdefs.qh"
-#endif
-#include "common.qh"
-
-void WarpZoneLib_ExactTrigger_Init()
-{SELFPARAM();
-       vector mi, ma;
-       if (self.movedir == '0 0 0')
-       if (self.angles != '0 0 0')
-       {
-               makevectors (self.angles);
-               self.movedir = v_forward;
-       }
-       if(self.model == "")
-       {
-               // It's a box! No need to match with exacttriggers.
-               self.warpzone_isboxy = 1;
-       }
-       else
-       {
-               mi = self.mins;
-               ma = self.maxs;
-               precache_model(self.model);
-               _setmodel(self, self.model);
-               // let mapper-set mins/maxs override the model's bounds if set
-               if(mi != '0 0 0' || ma != '0 0 0')
-               {
-                       // It's a box! No need to match with exacttriggers.
-                       self.mins = mi;
-                       self.maxs = ma;
-                       self.warpzone_isboxy = 1;
-               }
-       }
-       setorigin(self, self.origin);
-       if(self.scale)
-               setsize(self, self.mins * self.scale, self.maxs * self.scale);
-       else
-               setsize(self, self.mins, self.maxs);
-       self.movetype = MOVETYPE_NONE;
-       self.solid = SOLID_TRIGGER;
-       self.model = "";
-}
diff --git a/qcsrc/warpzonelib/util_server.qh b/qcsrc/warpzonelib/util_server.qh
deleted file mode 100644 (file)
index 0a42d7d..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef UTIL_SERVER_H
-#define UTIL_SERVER_H
-
-float WarpZoneLib_MoveOutOfSolid(entity e);
-float WarpZoneLib_ExactTrigger_Touch();
-#ifdef SVQC
-void WarpZoneLib_ExactTrigger_Init();
-#endif
-#endif