]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Merge branch 'master' into Mario/buff_updates
authorMario <zacjardine@y7mail.com>
Fri, 31 Jul 2015 09:45:40 +0000 (19:45 +1000)
committerMario <zacjardine@y7mail.com>
Fri, 31 Jul 2015 09:45:40 +0000 (19:45 +1000)
# Conflicts:
# qcsrc/common/stats.qh
# qcsrc/server/autocvars.qh
# qcsrc/server/g_damage.qc
# qcsrc/server/mutators/mutator_buffs.qc
# qcsrc/server/mutators/mutator_buffs.qh

694 files changed:
_hud_common.cfg
commands.cfg
defaultXonotic.cfg
gamemodes.cfg
gfx/menu/luma/background_ingame.tga
gfx/menu/luma/colorbutton_c.tga
gfx/menu/luma/colorbutton_f.tga
gfx/menu/luma/colorbutton_n.tga
gfx/menu/luma/crosshairbutton_c.tga [deleted file]
gfx/menu/luma/crosshairbutton_d.tga [deleted file]
gfx/menu/luma/crosshairbutton_f.tga [deleted file]
gfx/menu/luma/crosshairbutton_n.tga [deleted file]
gfx/menu/luma/gametype_nb.tga
gfx/menu/luma/nopreview_map.tga
gfx/menu/luma/skinvalues.txt
gfx/menu/luminos/crosshairbutton_c.tga [deleted file]
gfx/menu/luminos/crosshairbutton_d.tga [deleted file]
gfx/menu/luminos/crosshairbutton_f.tga [deleted file]
gfx/menu/luminos/crosshairbutton_n.tga [deleted file]
gfx/menu/luminos/icon_ipv4.tga
gfx/menu/luminos/icon_ipv6.tga
gfx/menu/luminos/icon_mod_.tga
gfx/menu/luminos/icon_mod_MinstaGib.tga
gfx/menu/luminos/icon_mod_NewToys.tga
gfx/menu/luminos/icon_mod_Overkill.tga
gfx/menu/luminos/icon_mod_instagib.tga
gfx/menu/luminos/icon_pure1.tga
gfx/menu/luminos/skinvalues.txt
gfx/menu/wickedx/crosshairbutton_c.tga [deleted file]
gfx/menu/wickedx/crosshairbutton_d.tga [deleted file]
gfx/menu/wickedx/crosshairbutton_f.tga [deleted file]
gfx/menu/wickedx/crosshairbutton_n.tga [deleted file]
gfx/menu/wickedx/icon_ipv4.tga
gfx/menu/wickedx/icon_ipv6.tga
gfx/menu/wickedx/icon_mod_.tga
gfx/menu/wickedx/icon_mod_MinstaGib.tga
gfx/menu/wickedx/icon_mod_NewToys.tga
gfx/menu/wickedx/icon_mod_Overkill.tga
gfx/menu/wickedx/icon_mod_instagib.tga
gfx/menu/wickedx/icon_pure1.tga
gfx/menu/wickedx/skinvalues.txt
gfx/menu/xaw/crosshairbutton_c.tga [deleted file]
gfx/menu/xaw/crosshairbutton_d.tga [deleted file]
gfx/menu/xaw/crosshairbutton_f.tga [deleted file]
gfx/menu/xaw/crosshairbutton_n.tga [deleted file]
gfx/menu/xaw/icon_ipv4.tga
gfx/menu/xaw/icon_ipv6.tga
gfx/menu/xaw/icon_mod_.tga
gfx/menu/xaw/icon_mod_MinstaGib.tga
gfx/menu/xaw/icon_mod_NewToys.tga
gfx/menu/xaw/icon_mod_Overkill.tga
gfx/menu/xaw/icon_mod_instagib.tga
gfx/menu/xaw/icon_pure1.tga
gfx/menu/xaw/skinvalues.txt
models/turrets/terrainbase.md3 [deleted file]
physics.cfg [new file with mode: 0644]
physicsX.cfg
physicsX010.cfg
physicsX07.cfg
physicsXDF.cfg
physicsXDFLight.cfg
qcsrc/Makefile
qcsrc/client/_all.qh [new file with mode: 0644]
qcsrc/client/announcer.qc
qcsrc/client/announcer.qh [new file with mode: 0644]
qcsrc/client/autocvars.qh
qcsrc/client/bgmscript.qc
qcsrc/client/bgmscript.qh
qcsrc/client/casings.qc
qcsrc/client/casings.qh [new file with mode: 0644]
qcsrc/client/command/all.qc [new file with mode: 0644]
qcsrc/client/command/all.qh [new file with mode: 0644]
qcsrc/client/command/cl_cmd.qc
qcsrc/client/csqc_constants.qc [deleted file]
qcsrc/client/csqc_constants.qh [new file with mode: 0644]
qcsrc/client/csqcmodel_hooks.qc
qcsrc/client/csqcmodel_hooks.qh [new file with mode: 0644]
qcsrc/client/damage.qc
qcsrc/client/damage.qh
qcsrc/client/defs.qh
qcsrc/client/effects.qc
qcsrc/client/effects.qh [new file with mode: 0644]
qcsrc/client/gibs.qc
qcsrc/client/hook.qc
qcsrc/client/hook.qh [new file with mode: 0644]
qcsrc/client/hud.qc
qcsrc/client/hud.qh
qcsrc/client/hud_config.qc
qcsrc/client/hud_config.qh [new file with mode: 0644]
qcsrc/client/laser.qc
qcsrc/client/laser.qh [new file with mode: 0644]
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/movelib.qc [new file with mode: 0644]
qcsrc/client/movelib.qh [new file with mode: 0644]
qcsrc/client/movetypes.qc [deleted file]
qcsrc/client/movetypes.qh [deleted file]
qcsrc/client/noise.qc
qcsrc/client/particles.qc
qcsrc/client/particles.qh
qcsrc/client/player_skeleton.qc
qcsrc/client/player_skeleton.qh
qcsrc/client/prandom.qc
qcsrc/client/progs.src
qcsrc/client/rubble.qc
qcsrc/client/rubble.qh
qcsrc/client/scoreboard.qc
qcsrc/client/scoreboard.qh
qcsrc/client/shownames.qc
qcsrc/client/shownames.qh
qcsrc/client/sortlist.qh
qcsrc/client/t_items.qc [new file with mode: 0644]
qcsrc/client/t_items.qh [new file with mode: 0644]
qcsrc/client/target_music.qc [deleted file]
qcsrc/client/target_music.qh [deleted file]
qcsrc/client/teamradar.qc
qcsrc/client/teamradar.qh
qcsrc/client/tturrets.qc
qcsrc/client/tturrets.qh
qcsrc/client/tuba.qc
qcsrc/client/tuba.qh
qcsrc/client/vehicles/all.qc [new file with mode: 0644]
qcsrc/client/vehicles/all.qh [new file with mode: 0644]
qcsrc/client/vehicles/bumblebee.qc [new file with mode: 0644]
qcsrc/client/vehicles/bumblebee.qh [new file with mode: 0644]
qcsrc/client/vehicles/vehicles.qc [deleted file]
qcsrc/client/vehicles/vehicles.qh [deleted file]
qcsrc/client/view.qc
qcsrc/client/wall.qc
qcsrc/client/wall.qh
qcsrc/client/waypointsprites.qc
qcsrc/client/waypointsprites.qh
qcsrc/client/weapons/projectile.qc
qcsrc/client/weapons/projectile.qh
qcsrc/common/animdecide.qc
qcsrc/common/buffs.qh
qcsrc/common/command/all.qc [new file with mode: 0644]
qcsrc/common/command/all.qh [new file with mode: 0644]
qcsrc/common/command/command.qh [new file with mode: 0644]
qcsrc/common/command/generic.qc
qcsrc/common/command/generic.qh
qcsrc/common/command/markup.qc
qcsrc/common/command/markup.qh
qcsrc/common/command/rpn.qc
qcsrc/common/command/rpn.qh
qcsrc/common/command/shared_defs.qh [deleted file]
qcsrc/common/constants.qh
qcsrc/common/counting.qh
qcsrc/common/csqcmodel_settings.qh
qcsrc/common/items/all.inc [new file with mode: 0644]
qcsrc/common/items/all.qc [new file with mode: 0644]
qcsrc/common/items/all.qh [new file with mode: 0644]
qcsrc/common/items/inventory.qh [new file with mode: 0644]
qcsrc/common/items/item.qh [new file with mode: 0644]
qcsrc/common/items/item/ammo.qc [new file with mode: 0644]
qcsrc/common/items/item/ammo.qh [new file with mode: 0644]
qcsrc/common/items/item/armor.qc [new file with mode: 0644]
qcsrc/common/items/item/armor.qh [new file with mode: 0644]
qcsrc/common/items/item/buff.qc [new file with mode: 0644]
qcsrc/common/items/item/buff.qh [new file with mode: 0644]
qcsrc/common/items/item/health.qc [new file with mode: 0644]
qcsrc/common/items/item/health.qh [new file with mode: 0644]
qcsrc/common/items/item/jetpack.qc [new file with mode: 0644]
qcsrc/common/items/item/pickup.qc [new file with mode: 0644]
qcsrc/common/items/item/pickup.qh [new file with mode: 0644]
qcsrc/common/items/item/powerup.qc [new file with mode: 0644]
qcsrc/common/items/item/powerup.qh [new file with mode: 0644]
qcsrc/common/mapinfo.qc
qcsrc/common/mapinfo.qh
qcsrc/common/monsters/all.inc [new file with mode: 0644]
qcsrc/common/monsters/all.qc [new file with mode: 0644]
qcsrc/common/monsters/all.qh
qcsrc/common/monsters/monster/shambler.qc
qcsrc/common/monsters/monsters.qc [deleted file]
qcsrc/common/monsters/monsters.qh [deleted file]
qcsrc/common/monsters/spawn.qc
qcsrc/common/monsters/sv_monsters.qc
qcsrc/common/monsters/sv_monsters.qh
qcsrc/common/movetypes/follow.qc [new file with mode: 0644]
qcsrc/common/movetypes/include.qc [new file with mode: 0644]
qcsrc/common/movetypes/include.qh [new file with mode: 0644]
qcsrc/common/movetypes/movetypes.qc [new file with mode: 0644]
qcsrc/common/movetypes/movetypes.qh [new file with mode: 0644]
qcsrc/common/movetypes/push.qc [new file with mode: 0644]
qcsrc/common/movetypes/push.qh [new file with mode: 0644]
qcsrc/common/movetypes/step.qc [new file with mode: 0644]
qcsrc/common/movetypes/toss.qc [new file with mode: 0644]
qcsrc/common/movetypes/toss.qh [new file with mode: 0644]
qcsrc/common/movetypes/walk.qc [new file with mode: 0644]
qcsrc/common/movetypes/walk.qh [new file with mode: 0644]
qcsrc/common/nades.qc
qcsrc/common/nades.qh
qcsrc/common/net_notice.qc
qcsrc/common/notifications.qc
qcsrc/common/notifications.qh
qcsrc/common/oo.qh [new file with mode: 0644]
qcsrc/common/physics.qc [new file with mode: 0644]
qcsrc/common/physics.qh [new file with mode: 0644]
qcsrc/common/playerstats.qc
qcsrc/common/stats.qh
qcsrc/common/triggers/func/bobbing.qc [new file with mode: 0644]
qcsrc/common/triggers/func/breakable.qc [new file with mode: 0644]
qcsrc/common/triggers/func/breakable.qh [new file with mode: 0644]
qcsrc/common/triggers/func/button.qc [new file with mode: 0644]
qcsrc/common/triggers/func/conveyor.qc [new file with mode: 0644]
qcsrc/common/triggers/func/conveyor.qh [new file with mode: 0644]
qcsrc/common/triggers/func/door.qc [new file with mode: 0644]
qcsrc/common/triggers/func/door.qh [new file with mode: 0644]
qcsrc/common/triggers/func/door_rotating.qc [new file with mode: 0644]
qcsrc/common/triggers/func/door_secret.qc [new file with mode: 0644]
qcsrc/common/triggers/func/fourier.qc [new file with mode: 0644]
qcsrc/common/triggers/func/include.qc [new file with mode: 0644]
qcsrc/common/triggers/func/include.qh [new file with mode: 0644]
qcsrc/common/triggers/func/ladder.qc [new file with mode: 0644]
qcsrc/common/triggers/func/ladder.qh [new file with mode: 0644]
qcsrc/common/triggers/func/pendulum.qc [new file with mode: 0644]
qcsrc/common/triggers/func/plat.qc [new file with mode: 0644]
qcsrc/common/triggers/func/plat.qh [new file with mode: 0644]
qcsrc/common/triggers/func/pointparticles.qc [new file with mode: 0644]
qcsrc/common/triggers/func/pointparticles.qh [new file with mode: 0644]
qcsrc/common/triggers/func/rainsnow.qc [new file with mode: 0644]
qcsrc/common/triggers/func/rainsnow.qh [new file with mode: 0644]
qcsrc/common/triggers/func/rotating.qc [new file with mode: 0644]
qcsrc/common/triggers/func/stardust.qc [new file with mode: 0644]
qcsrc/common/triggers/func/train.qc [new file with mode: 0644]
qcsrc/common/triggers/func/train.qh [new file with mode: 0644]
qcsrc/common/triggers/func/vectormamamam.qc [new file with mode: 0644]
qcsrc/common/triggers/include.qc [new file with mode: 0644]
qcsrc/common/triggers/include.qh [new file with mode: 0644]
qcsrc/common/triggers/misc/corner.qc [new file with mode: 0644]
qcsrc/common/triggers/misc/corner.qh [new file with mode: 0644]
qcsrc/common/triggers/misc/follow.qc [new file with mode: 0644]
qcsrc/common/triggers/misc/include.qc [new file with mode: 0644]
qcsrc/common/triggers/misc/include.qh [new file with mode: 0644]
qcsrc/common/triggers/misc/laser.qc [new file with mode: 0644]
qcsrc/common/triggers/misc/laser.qh [new file with mode: 0644]
qcsrc/common/triggers/misc/teleport_dest.qc [new file with mode: 0644]
qcsrc/common/triggers/platforms.qc [new file with mode: 0644]
qcsrc/common/triggers/platforms.qh [new file with mode: 0644]
qcsrc/common/triggers/subs.qc [new file with mode: 0644]
qcsrc/common/triggers/subs.qh [new file with mode: 0644]
qcsrc/common/triggers/target/changelevel.qc [new file with mode: 0644]
qcsrc/common/triggers/target/include.qc [new file with mode: 0644]
qcsrc/common/triggers/target/include.qh [new file with mode: 0644]
qcsrc/common/triggers/target/location.qc [new file with mode: 0644]
qcsrc/common/triggers/target/music.qc [new file with mode: 0644]
qcsrc/common/triggers/target/music.qh [new file with mode: 0644]
qcsrc/common/triggers/target/spawn.qc [new file with mode: 0644]
qcsrc/common/triggers/target/speaker.qc [new file with mode: 0644]
qcsrc/common/triggers/target/voicescript.qc [new file with mode: 0644]
qcsrc/common/triggers/teleporters.qc [new file with mode: 0644]
qcsrc/common/triggers/teleporters.qh [new file with mode: 0644]
qcsrc/common/triggers/trigger/counter.qc [new file with mode: 0644]
qcsrc/common/triggers/trigger/delay.qc [new file with mode: 0644]
qcsrc/common/triggers/trigger/disablerelay.qc [new file with mode: 0644]
qcsrc/common/triggers/trigger/flipflop.qc [new file with mode: 0644]
qcsrc/common/triggers/trigger/gamestart.qc [new file with mode: 0644]
qcsrc/common/triggers/trigger/gravity.qc [new file with mode: 0644]
qcsrc/common/triggers/trigger/heal.qc [new file with mode: 0644]
qcsrc/common/triggers/trigger/hurt.qc [new file with mode: 0644]
qcsrc/common/triggers/trigger/impulse.qc [new file with mode: 0644]
qcsrc/common/triggers/trigger/impulse.qh [new file with mode: 0644]
qcsrc/common/triggers/trigger/include.qc [new file with mode: 0644]
qcsrc/common/triggers/trigger/include.qh [new file with mode: 0644]
qcsrc/common/triggers/trigger/jumppads.qc [new file with mode: 0644]
qcsrc/common/triggers/trigger/jumppads.qh [new file with mode: 0644]
qcsrc/common/triggers/trigger/keylock.qc [new file with mode: 0644]
qcsrc/common/triggers/trigger/keylock.qh [new file with mode: 0644]
qcsrc/common/triggers/trigger/magicear.qc [new file with mode: 0644]
qcsrc/common/triggers/trigger/monoflop.qc [new file with mode: 0644]
qcsrc/common/triggers/trigger/multi.qc [new file with mode: 0644]
qcsrc/common/triggers/trigger/multi.qh [new file with mode: 0644]
qcsrc/common/triggers/trigger/multivibrator.qc [new file with mode: 0644]
qcsrc/common/triggers/trigger/relay.qc [new file with mode: 0644]
qcsrc/common/triggers/trigger/relay_activators.qc [new file with mode: 0644]
qcsrc/common/triggers/trigger/relay_if.qc [new file with mode: 0644]
qcsrc/common/triggers/trigger/relay_teamcheck.qc [new file with mode: 0644]
qcsrc/common/triggers/trigger/secret.qc [new file with mode: 0644]
qcsrc/common/triggers/trigger/secret.qh [new file with mode: 0644]
qcsrc/common/triggers/trigger/swamp.qc [new file with mode: 0644]
qcsrc/common/triggers/trigger/swamp.qh [new file with mode: 0644]
qcsrc/common/triggers/trigger/teleport.qc [new file with mode: 0644]
qcsrc/common/triggers/triggers.qc [new file with mode: 0644]
qcsrc/common/triggers/triggers.qh [new file with mode: 0644]
qcsrc/common/util-pre.qh
qcsrc/common/util.qc
qcsrc/common/util.qh
qcsrc/common/weapons/all.inc [new file with mode: 0644]
qcsrc/common/weapons/all.qc [new file with mode: 0644]
qcsrc/common/weapons/all.qh
qcsrc/common/weapons/config.qc
qcsrc/common/weapons/w_arc.qc
qcsrc/common/weapons/w_blaster.qc
qcsrc/common/weapons/w_crylink.qc
qcsrc/common/weapons/w_devastator.qc
qcsrc/common/weapons/w_electro.qc
qcsrc/common/weapons/w_fireball.qc
qcsrc/common/weapons/w_hagar.qc
qcsrc/common/weapons/w_hlac.qc
qcsrc/common/weapons/w_hmg.qc
qcsrc/common/weapons/w_hook.qc
qcsrc/common/weapons/w_machinegun.qc
qcsrc/common/weapons/w_minelayer.qc
qcsrc/common/weapons/w_mortar.qc
qcsrc/common/weapons/w_porto.qc
qcsrc/common/weapons/w_rifle.qc
qcsrc/common/weapons/w_rpc.qc
qcsrc/common/weapons/w_seeker.qc
qcsrc/common/weapons/w_shockwave.qc
qcsrc/common/weapons/w_tuba.qc
qcsrc/common/weapons/w_vortex.qc
qcsrc/common/weapons/weapons.qc [deleted file]
qcsrc/common/weapons/weapons.qh [deleted file]
qcsrc/csqcmodellib/cl_model.qc
qcsrc/csqcmodellib/cl_model.qh
qcsrc/csqcmodellib/cl_player.qc
qcsrc/csqcmodellib/cl_player.qh
qcsrc/csqcmodellib/sv_model.qc
qcsrc/dpdefs/csprogsdefs.qh
qcsrc/dpdefs/dpextensions.qh
qcsrc/dpdefs/keycodes.qh
qcsrc/dpdefs/menudefs.qh
qcsrc/dpdefs/progsdefs.qh
qcsrc/dpdefs/upstream/csprogsdefs.qc [new file with mode: 0644]
qcsrc/dpdefs/upstream/dpextensions.qc [new file with mode: 0644]
qcsrc/dpdefs/upstream/keycodes.qc [new file with mode: 0644]
qcsrc/dpdefs/upstream/menudefs.qc [new file with mode: 0644]
qcsrc/dpdefs/upstream/progsdefs.qc [new file with mode: 0644]
qcsrc/menu/_all.qh [new file with mode: 0644]
qcsrc/menu/anim/animation.qc
qcsrc/menu/anim/animhost.qc
qcsrc/menu/anim/easing.qc
qcsrc/menu/anim/keyframe.qc
qcsrc/menu/classes.inc [new file with mode: 0644]
qcsrc/menu/classes.qc [deleted file]
qcsrc/menu/command/all.qc [new file with mode: 0644]
qcsrc/menu/command/all.qh [new file with mode: 0644]
qcsrc/menu/command/menu_cmd.qc
qcsrc/menu/draw.qc
qcsrc/menu/item.qc
qcsrc/menu/item/borderimage.qc
qcsrc/menu/item/button.qc
qcsrc/menu/item/checkbox.qc
qcsrc/menu/item/container.qc
qcsrc/menu/item/dialog.qc
qcsrc/menu/item/image.qc
qcsrc/menu/item/inputbox.qc
qcsrc/menu/item/inputcontainer.qc
qcsrc/menu/item/label.qc
qcsrc/menu/item/listbox.qc
qcsrc/menu/item/modalcontroller.qc
qcsrc/menu/item/nexposee.qc
qcsrc/menu/item/radiobutton.qc
qcsrc/menu/item/slider.qc
qcsrc/menu/item/tab.qc
qcsrc/menu/item/textslider.qc
qcsrc/menu/menu.qc
qcsrc/menu/menu.qh
qcsrc/menu/oo/base.qh
qcsrc/menu/oo/classes.qc [new file with mode: 0644]
qcsrc/menu/oo/implementation.qh [deleted file]
qcsrc/menu/oo/interface.qh [deleted file]
qcsrc/menu/progs.src
qcsrc/menu/skin-customizables.inc
qcsrc/menu/skin.qh
qcsrc/menu/xonotic/bigbutton.qc
qcsrc/menu/xonotic/bigcommandbutton.qc
qcsrc/menu/xonotic/button.qc
qcsrc/menu/xonotic/campaign.qc
qcsrc/menu/xonotic/charmap.qc
qcsrc/menu/xonotic/checkbox.qc
qcsrc/menu/xonotic/checkbox_slider_invalid.qc
qcsrc/menu/xonotic/checkbox_string.qc
qcsrc/menu/xonotic/colorbutton.qc
qcsrc/menu/xonotic/colorpicker.qc
qcsrc/menu/xonotic/colorpicker_string.qc
qcsrc/menu/xonotic/commandbutton.qc
qcsrc/menu/xonotic/credits.qc
qcsrc/menu/xonotic/crosshairbutton.qc [deleted file]
qcsrc/menu/xonotic/crosshairpicker.qc [new file with mode: 0644]
qcsrc/menu/xonotic/crosshairpreview.qc [new file with mode: 0644]
qcsrc/menu/xonotic/cvarlist.qc
qcsrc/menu/xonotic/demolist.qc
qcsrc/menu/xonotic/dialog.qc
qcsrc/menu/xonotic/dialog_credits.qc
qcsrc/menu/xonotic/dialog_firstrun.qc
qcsrc/menu/xonotic/dialog_hudpanel_ammo.qc
qcsrc/menu/xonotic/dialog_hudpanel_buffs.qc
qcsrc/menu/xonotic/dialog_hudpanel_centerprint.qc
qcsrc/menu/xonotic/dialog_hudpanel_chat.qc
qcsrc/menu/xonotic/dialog_hudpanel_engineinfo.qc
qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.qc
qcsrc/menu/xonotic/dialog_hudpanel_infomessages.qc
qcsrc/menu/xonotic/dialog_hudpanel_modicons.qc
qcsrc/menu/xonotic/dialog_hudpanel_notification.qc
qcsrc/menu/xonotic/dialog_hudpanel_physics.qc
qcsrc/menu/xonotic/dialog_hudpanel_powerups.qc
qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.qc
qcsrc/menu/xonotic/dialog_hudpanel_racetimer.qc
qcsrc/menu/xonotic/dialog_hudpanel_radar.qc
qcsrc/menu/xonotic/dialog_hudpanel_score.qc
qcsrc/menu/xonotic/dialog_hudpanel_timer.qc
qcsrc/menu/xonotic/dialog_hudpanel_vote.qc
qcsrc/menu/xonotic/dialog_hudpanel_weapons.qc
qcsrc/menu/xonotic/dialog_hudsetup_exit.qc
qcsrc/menu/xonotic/dialog_monstertools.qc
qcsrc/menu/xonotic/dialog_multiplayer.qc
qcsrc/menu/xonotic/dialog_multiplayer_create.qc
qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.qc
qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc
qcsrc/menu/xonotic/dialog_multiplayer_join.qc
qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc
qcsrc/menu/xonotic/dialog_multiplayer_media.qc
qcsrc/menu/xonotic/dialog_multiplayer_media_demo.qc
qcsrc/menu/xonotic/dialog_multiplayer_media_demo_startconfirm.qc
qcsrc/menu/xonotic/dialog_multiplayer_media_demo_timeconfirm.qc
qcsrc/menu/xonotic/dialog_multiplayer_media_musicplayer.qc
qcsrc/menu/xonotic/dialog_multiplayer_media_screenshot.qc
qcsrc/menu/xonotic/dialog_multiplayer_media_screenshot_viewer.qc
qcsrc/menu/xonotic/dialog_multiplayer_profile.qc
qcsrc/menu/xonotic/dialog_quit.qc
qcsrc/menu/xonotic/dialog_sandboxtools.qc
qcsrc/menu/xonotic/dialog_settings.qc
qcsrc/menu/xonotic/dialog_settings_audio.qc
qcsrc/menu/xonotic/dialog_settings_effects.qc
qcsrc/menu/xonotic/dialog_settings_game.qc
qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc
qcsrc/menu/xonotic/dialog_settings_game_hud.qc
qcsrc/menu/xonotic/dialog_settings_game_hudconfirm.qc
qcsrc/menu/xonotic/dialog_settings_game_messages.qc
qcsrc/menu/xonotic/dialog_settings_game_model.qc
qcsrc/menu/xonotic/dialog_settings_game_view.qc
qcsrc/menu/xonotic/dialog_settings_game_weapons.qc
qcsrc/menu/xonotic/dialog_settings_input.qc
qcsrc/menu/xonotic/dialog_settings_input_userbind.qc
qcsrc/menu/xonotic/dialog_settings_misc.qc
qcsrc/menu/xonotic/dialog_settings_misc_cvars.qc
qcsrc/menu/xonotic/dialog_settings_misc_reset.qc
qcsrc/menu/xonotic/dialog_settings_user.qc
qcsrc/menu/xonotic/dialog_settings_user_languagewarning.qc
qcsrc/menu/xonotic/dialog_settings_video.qc
qcsrc/menu/xonotic/dialog_singleplayer.qc
qcsrc/menu/xonotic/dialog_singleplayer_winner.qc
qcsrc/menu/xonotic/dialog_teamselect.qc
qcsrc/menu/xonotic/gametypebutton.qc
qcsrc/menu/xonotic/gametypelist.qc
qcsrc/menu/xonotic/image.qc
qcsrc/menu/xonotic/inputbox.qc
qcsrc/menu/xonotic/keybinder.qc
qcsrc/menu/xonotic/languagelist.qc
qcsrc/menu/xonotic/listbox.qc
qcsrc/menu/xonotic/mainwindow.qc
qcsrc/menu/xonotic/maplist.qc
qcsrc/menu/xonotic/nexposee.qc
qcsrc/menu/xonotic/picker.qc [new file with mode: 0644]
qcsrc/menu/xonotic/playerlist.qc
qcsrc/menu/xonotic/playermodel.qc
qcsrc/menu/xonotic/playlist.qc
qcsrc/menu/xonotic/radiobutton.qc
qcsrc/menu/xonotic/rootdialog.qc
qcsrc/menu/xonotic/screenshotimage.qc
qcsrc/menu/xonotic/screenshotlist.qc
qcsrc/menu/xonotic/serverlist.qc
qcsrc/menu/xonotic/skinlist.qc
qcsrc/menu/xonotic/slider.qc
qcsrc/menu/xonotic/slider_decibels.qc
qcsrc/menu/xonotic/slider_particles.qc
qcsrc/menu/xonotic/slider_picmip.qc
qcsrc/menu/xonotic/slider_resolution.qc
qcsrc/menu/xonotic/slider_sbfadetime.qc
qcsrc/menu/xonotic/soundlist.qc
qcsrc/menu/xonotic/statslist.qc
qcsrc/menu/xonotic/tab.qc
qcsrc/menu/xonotic/tabcontroller.qc
qcsrc/menu/xonotic/textlabel.qc
qcsrc/menu/xonotic/textslider.qc
qcsrc/menu/xonotic/util.qc
qcsrc/menu/xonotic/util.qh
qcsrc/menu/xonotic/weaponarenacheckbox.qc
qcsrc/menu/xonotic/weaponslist.qc
qcsrc/server/_all.qh [new file with mode: 0644]
qcsrc/server/anticheat.qc
qcsrc/server/antilag.qc
qcsrc/server/autocvars.qh
qcsrc/server/bot/aim.qc
qcsrc/server/bot/aim.qh
qcsrc/server/bot/bot.qc
qcsrc/server/bot/bot.qh
qcsrc/server/bot/havocbot/havocbot.qc
qcsrc/server/bot/havocbot/role_keyhunt.qc
qcsrc/server/bot/havocbot/role_keyhunt.qh [new file with mode: 0644]
qcsrc/server/bot/havocbot/role_onslaught.qc
qcsrc/server/bot/havocbot/role_onslaught.qh [new file with mode: 0644]
qcsrc/server/bot/havocbot/roles.qc
qcsrc/server/bot/havocbot/roles.qh [new file with mode: 0644]
qcsrc/server/bot/havocbot/scripting.qh [new file with mode: 0644]
qcsrc/server/bot/navigation.qc
qcsrc/server/bot/navigation.qh
qcsrc/server/bot/scripting.qc
qcsrc/server/bot/scripting.qh [new file with mode: 0644]
qcsrc/server/bot/waypoints.qc
qcsrc/server/campaign.qc
qcsrc/server/cheats.qc
qcsrc/server/cheats.qh
qcsrc/server/cl_client.qc
qcsrc/server/cl_client.qh [new file with mode: 0644]
qcsrc/server/cl_impulse.qc
qcsrc/server/cl_physics.qc [deleted file]
qcsrc/server/cl_player.qc
qcsrc/server/cl_player.qh
qcsrc/server/command/all.qc [new file with mode: 0644]
qcsrc/server/command/all.qh [new file with mode: 0644]
qcsrc/server/command/banning.qc
qcsrc/server/command/banning.qh
qcsrc/server/command/cmd.qc
qcsrc/server/command/common.qc
qcsrc/server/command/common.qh
qcsrc/server/command/getreplies.qc
qcsrc/server/command/radarmap.qc
qcsrc/server/command/radarmap.qh
qcsrc/server/command/sv_cmd.qc
qcsrc/server/command/vote.qc
qcsrc/server/command/vote.qh
qcsrc/server/constants.qh
qcsrc/server/csqceffects.qh [new file with mode: 0644]
qcsrc/server/defs.qh
qcsrc/server/ent_cs.qc
qcsrc/server/func_breakable.qc [deleted file]
qcsrc/server/g_casings.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_subs.qh
qcsrc/server/g_tetris.qc
qcsrc/server/g_triggers.qc [deleted file]
qcsrc/server/g_triggers.qh [deleted file]
qcsrc/server/g_violence.qc
qcsrc/server/g_violence.qh
qcsrc/server/g_world.qc
qcsrc/server/g_world.qh
qcsrc/server/ipban.qc
qcsrc/server/item_key.qc
qcsrc/server/item_key.qh
qcsrc/server/mapvoting.qc
qcsrc/server/mapvoting.qh
qcsrc/server/miscfunctions.qc
qcsrc/server/miscfunctions.qh
qcsrc/server/mutators/base.qc
qcsrc/server/mutators/gamemode.qh [new file with mode: 0644]
qcsrc/server/mutators/gamemode_assault.qc
qcsrc/server/mutators/gamemode_assault.qh
qcsrc/server/mutators/gamemode_ca.qc
qcsrc/server/mutators/gamemode_ctf.qc
qcsrc/server/mutators/gamemode_ctf.qh
qcsrc/server/mutators/gamemode_cts.qc
qcsrc/server/mutators/gamemode_domination.qc
qcsrc/server/mutators/gamemode_freezetag.qc
qcsrc/server/mutators/gamemode_freezetag.qh [new file with mode: 0644]
qcsrc/server/mutators/gamemode_invasion.qc
qcsrc/server/mutators/gamemode_keepaway.qc
qcsrc/server/mutators/gamemode_keepaway.qh
qcsrc/server/mutators/gamemode_keyhunt.qc
qcsrc/server/mutators/gamemode_keyhunt.qh
qcsrc/server/mutators/gamemode_lms.qc
qcsrc/server/mutators/gamemode_nexball.qc
qcsrc/server/mutators/gamemode_onslaught.qc
qcsrc/server/mutators/gamemode_race.qc
qcsrc/server/mutators/gamemode_tdm.qc
qcsrc/server/mutators/mutator.qh [new file with mode: 0644]
qcsrc/server/mutators/mutator_bloodloss.qc
qcsrc/server/mutators/mutator_buffs.qc
qcsrc/server/mutators/mutator_buffs.qh
qcsrc/server/mutators/mutator_campcheck.qc
qcsrc/server/mutators/mutator_dodging.qc
qcsrc/server/mutators/mutator_instagib.qc
qcsrc/server/mutators/mutator_instagib_items.qc [new file with mode: 0644]
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_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_include.qc
qcsrc/server/mutators/sandbox.qc
qcsrc/server/pathlib.qc
qcsrc/server/pathlib.qh [new file with mode: 0644]
qcsrc/server/pathlib/costs.qc
qcsrc/server/pathlib/debug.qc
qcsrc/server/pathlib/expandnode.qc
qcsrc/server/pathlib/main.qc
qcsrc/server/pathlib/main.qh [new file with mode: 0644]
qcsrc/server/pathlib/movenode.qc
qcsrc/server/pathlib/path_waypoint.qc
qcsrc/server/pathlib/pathlib.qh
qcsrc/server/pathlib/utility.qc
qcsrc/server/pathlib/utility.qh [new file with mode: 0644]
qcsrc/server/playerdemo.qc
qcsrc/server/portals.qc
qcsrc/server/progs.src
qcsrc/server/race.qc
qcsrc/server/race.qh
qcsrc/server/round_handler.qc
qcsrc/server/scores.qc
qcsrc/server/scores.qh
qcsrc/server/scores_rules.qc
qcsrc/server/scores_rules.qh [new file with mode: 0644]
qcsrc/server/secret.qc [deleted file]
qcsrc/server/secret.qh [deleted file]
qcsrc/server/spawnpoints.qc
qcsrc/server/spawnpoints.qh
qcsrc/server/steerlib.qc
qcsrc/server/steerlib.qh [new file with mode: 0644]
qcsrc/server/sv_main.qc
qcsrc/server/t_halflife.qc
qcsrc/server/t_items.qc
qcsrc/server/t_items.qh
qcsrc/server/t_jumppads.qc [deleted file]
qcsrc/server/t_jumppads.qh [deleted file]
qcsrc/server/t_plats.qc
qcsrc/server/t_quake.qc
qcsrc/server/t_quake3.qc
qcsrc/server/t_swamp.qc [deleted file]
qcsrc/server/t_teleporters.qc [deleted file]
qcsrc/server/t_teleporters.qh [deleted file]
qcsrc/server/target_music.qc
qcsrc/server/target_spawn.qc [deleted file]
qcsrc/server/teamplay.qc
qcsrc/server/tturrets/include/turrets_early.qh
qcsrc/server/tturrets/system/system_damage.qc
qcsrc/server/tturrets/system/system_main.qc
qcsrc/server/tturrets/system/system_misc.qc
qcsrc/server/tturrets/units/unit_ewheel.qc
qcsrc/server/tturrets/units/unit_machinegun.qc
qcsrc/server/tturrets/units/unit_phaser.qc
qcsrc/server/tturrets/units/unit_tessla.qc
qcsrc/server/tturrets/units/unit_walker.qc
qcsrc/server/vehicles/all.qc [new file with mode: 0644]
qcsrc/server/vehicles/all.qh [new file with mode: 0644]
qcsrc/server/vehicles/bumblebee.qc
qcsrc/server/vehicles/bumblebee.qh
qcsrc/server/vehicles/racer.qc
qcsrc/server/vehicles/racer.qh [new file with mode: 0644]
qcsrc/server/vehicles/raptor.qc
qcsrc/server/vehicles/raptor.qh [new file with mode: 0644]
qcsrc/server/vehicles/spiderbot.qc
qcsrc/server/vehicles/spiderbot.qh [new file with mode: 0644]
qcsrc/server/vehicles/vehicle.qc [new file with mode: 0644]
qcsrc/server/vehicles/vehicle.qh [new file with mode: 0644]
qcsrc/server/vehicles/vehicles.qc [deleted file]
qcsrc/server/vehicles/vehicles.qh [deleted file]
qcsrc/server/vehicles/vehicles_def.qh [deleted file]
qcsrc/server/waypointsprites.qc
qcsrc/server/weapons/accuracy.qc
qcsrc/server/weapons/common.qc
qcsrc/server/weapons/common.qh
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/tracing.qh
qcsrc/server/weapons/weaponstats.qc
qcsrc/server/weapons/weaponsystem.qc
qcsrc/test/compilationunit.sh [new file with mode: 0755]
qcsrc/warpzonelib/anglestransform.qc
qcsrc/warpzonelib/client.qc
qcsrc/warpzonelib/common.qc
qcsrc/warpzonelib/common.qh
qcsrc/warpzonelib/mathlib.qc
qcsrc/warpzonelib/mathlib.qh
qcsrc/warpzonelib/server.qc
qcsrc/warpzonelib/util_server.qc
qcsrc/warpzonelib/util_server.qh
xonotic-credits.txt

index 5aa1bbfeea3203469aedb2a4b248d08951d12617..b74eff9607999b19978d0128dd466824e1167585 100644 (file)
@@ -38,6 +38,9 @@ seta hud_panel_engineinfo_framecounter_exponentialmovingaverage 1 "use an averag
 seta hud_panel_engineinfo_framecounter_exponentialmovingaverage_new_weight 0.1 "weight of latest data point"
 seta hud_panel_engineinfo_framecounter_exponentialmovingaverage_instantupdate_change_threshold 0.5 "threshold for fps change when to update instantly, to make big fps changes update faster"
 
+seta hud_panel_physics_acceleration_movingaverage 1 "use an averaging method for calculating acceleration instead of the real value"
+seta hud_panel_phisics_update_interval 0.0666 "how often (in seconds) numeric values get updated on screen"
+
 // hud panel aliases
 alias hud_panel_radar_rotate "toggle hud_panel_radar_rotation 0 1 2 3 4"
 alias +hud_panel_radar_maximized "cl_cmd hud radar 1"
index 20f957029a3472151c0756d25eb444959906d57d..812e572b274b341177468f8ec99d616e4944ead0 100644 (file)
@@ -160,6 +160,7 @@ alias sentcvar             "qc_cmd_cmd    sentcvar             ${* ?}" // New sy
 alias mobedit              "qc_cmd_cmd    mobedit              ${* ?}" // Edit a monster's properties
 alias mobkill              "qc_cmd_cmd    mobkill              ${* ?}" // Kill a monster
 alias mobspawn             "qc_cmd_cmd    mobspawn             ${* ?}" // Spawn a monster infront of the player
+alias physics              "qc_cmd_cmd    physics              ${* ?}" // Change physics set
 alias spectate             "qc_cmd_cmd    spectate             ${* ?}" // Become an observer
 alias suggestmap           "qc_cmd_cmd    suggestmap           ${* ?}" // Suggest a map to the mapvote at match end
 //alias tell               "qc_cmd_cmd    tell                 ${* ?}" // Send a message directly to a player
index 4f02d145e0276f7d66ae0a9036c3b9d9d6191cd2..c0d585e9fce4a00cc9a79e59461805f527631f14 100644 (file)
@@ -10,7 +10,7 @@
 // e.g. Xonotic 1.5.1 RC1 will be 15101
 set g_xonoticversion git "Xonotic version (formatted for humans)"
 
-gameversion 800 // 0.8.0
+gameversion 801 // 0.8.1
 gameversion_min 0 // git builds see all versions
 gameversion_max 65535 // git builds see all versions
 
@@ -296,6 +296,7 @@ set sv_fraginfo_stats 1 "Enable statistics (health/armor) display information, 0
 
 // use default physics
 set sv_friction_on_land 0
+set sv_friction_slick 0.5
 
 set sv_player_viewoffset "0 0 35" "view offset of the player model"
 set sv_player_mins "-16 -16 -24" "playermodel mins"
@@ -472,7 +473,7 @@ set g_botclip_collisions 1 "0 = disable collision testing against botclips, migh
 set g_grappling_hook 0 "let players spawn with the grappling hook which allows them to pull themselves up"
 
 set g_spawn_alloweffects 1 "allow clients to enable spawn point and event effects such as particles and sounds, see cl_spawn_ cvars for more info"
-set g_spawn_furthest 1.0 "this amount of the spawns shall be far away from any players"
+set g_spawn_furthest 0.5 "this amount of the spawns shall be far away from any players"
 set g_spawn_useallspawns 0 "use all spawns, e.g. also team spawns in non-teamplay, and all spawns, even enemy spawns, in teamplay"
 // respawn delay
 set g_respawn_delay_small 2 "small game number of seconds you have to wait before you can respawn again"
@@ -1399,6 +1400,7 @@ exec gamemodes.cfg
 exec mutators.cfg
 exec notifications.cfg
 exec monsters.cfg
+exec physics.cfg
 
 // load console command aliases and settings
 exec commands.cfg
index b6cbe92cfcba116c79de77e667e30d35d2c6601a..d660aa123aecfcca782679a62cace4864842fb23 100644 (file)
@@ -66,8 +66,11 @@ alias sv_hook_gameend
 // =====================
 //  gametype vote hooks
 // =====================
-// these are called when the mode is switched via gametype vote screen, earlier than gamestart hooks (useful for enabling per-gamemode mutators)
-alias sv_vote_gametype_hook_all 
+// These are called when the mode is switched via gametype vote screen,
+// earlier than gamestart hooks (useful for enabling per-gamemode mutators)
+// The _all hook is called before the specific one
+// here it sets g_maxplayers to undo what duel does
+alias sv_vote_gametype_hook_all "set g_maxplayers 0"
 alias sv_vote_gametype_hook_as
 alias sv_vote_gametype_hook_ca
 alias sv_vote_gametype_hook_ctf
@@ -84,6 +87,15 @@ alias sv_vote_gametype_hook_ons
 alias sv_vote_gametype_hook_rc
 alias sv_vote_gametype_hook_tdm
 
+// Preset to allow duel to be used for the gametype voting screen
+// sv_vote_gametype_*_type Must be set to the name of the gametype the option is based on
+// sv_vote_gametype_*_name Contains a human-readable name of the gametype
+// sv_vote_gametype_*_description Contains a longer description
+set sv_vote_gametype_duel_type dm
+set sv_vote_gametype_duel_name Duel
+set sv_vote_gametype_duel_description "One vs One match"
+alias sv_vote_gametype_hook_duel "set g_maxplayers 2"
+
 
 // ===========
 //  leadlimit
index 6ead9343b6db6e153e137f14058a946ee06600b8..547fa0904bc1d505929c97fda475cf947505df47 100644 (file)
Binary files a/gfx/menu/luma/background_ingame.tga and b/gfx/menu/luma/background_ingame.tga differ
index 0d8eef1394ba987c9e1d75a077ef188403b21a1a..91f343e70339192491eab3787fa99dd32f3a2662 100644 (file)
Binary files a/gfx/menu/luma/colorbutton_c.tga and b/gfx/menu/luma/colorbutton_c.tga differ
index 1a2fc860e99ad45d4fb86b05fb664b4888259e3a..0aa806b0418c56ed3bd97c0296d4f7cd6f73d89d 100644 (file)
Binary files a/gfx/menu/luma/colorbutton_f.tga and b/gfx/menu/luma/colorbutton_f.tga differ
index 3498ad541b333959d3975dc904f0536786815ebb..bcba096780ef13ad713664c38997e05e2023dcd5 100644 (file)
Binary files a/gfx/menu/luma/colorbutton_n.tga and b/gfx/menu/luma/colorbutton_n.tga differ
diff --git a/gfx/menu/luma/crosshairbutton_c.tga b/gfx/menu/luma/crosshairbutton_c.tga
deleted file mode 100644 (file)
index ecfd0a8..0000000
Binary files a/gfx/menu/luma/crosshairbutton_c.tga and /dev/null differ
diff --git a/gfx/menu/luma/crosshairbutton_d.tga b/gfx/menu/luma/crosshairbutton_d.tga
deleted file mode 100644 (file)
index 4e7901e..0000000
Binary files a/gfx/menu/luma/crosshairbutton_d.tga and /dev/null differ
diff --git a/gfx/menu/luma/crosshairbutton_f.tga b/gfx/menu/luma/crosshairbutton_f.tga
deleted file mode 100644 (file)
index 604a935..0000000
Binary files a/gfx/menu/luma/crosshairbutton_f.tga and /dev/null differ
diff --git a/gfx/menu/luma/crosshairbutton_n.tga b/gfx/menu/luma/crosshairbutton_n.tga
deleted file mode 100644 (file)
index 4e7901e..0000000
Binary files a/gfx/menu/luma/crosshairbutton_n.tga and /dev/null differ
index 9bfb5adc4c65222fe7cf9a1ed2a917aed28de718..15d273634fa1caa6a8471eeaae9370f422e456e3 100644 (file)
Binary files a/gfx/menu/luma/gametype_nb.tga and b/gfx/menu/luma/gametype_nb.tga differ
index 5fedc940b5bd40e948c57a070fd8c2b744bce924..5cd70916d5d2519328d9c0673857aa61148c6803 100644 (file)
Binary files a/gfx/menu/luma/nopreview_map.tga and b/gfx/menu/luma/nopreview_map.tga differ
index 1e87e8869ec5d9443c3147dde51298a675738f94..c997fea25772cd797dc361c60304db04e7cc3b5b 100644 (file)
@@ -33,8 +33,10 @@ COLOR_CAMPAIGN_SELECTABLE     '0.96 0.99 1'
 // charmap
 ALPHA_CHARMAP_CHAR            0.85
 COLOR_CHARMAP_CHAR            '1 1 1'
-ALPHA_CHARMAP_FOCUS           0.85
-COLOR_CHARMAP_FOCUS           '0.09 0.42 0.69'
+
+// crosshairpicker
+ALPHA_CROSSHAIRPICKER_CROSSHAIR 0.6
+COLOR_CROSSHAIRPICKER_CROSSHAIR '1 1 1'
 
 // checkbox
 COLOR_CHECKBOX_C              '1 1 1'
@@ -120,10 +122,13 @@ COLOR_HEADER                  '0.96 0.99 1'
 FONTSIZE_NORMAL               12
 FONTSIZE_TITLE                16
 FONTSIZE_TOOLTIP              12
-HEIGHT_NORMAL                 1.5
-HEIGHT_TITLE                  1.5
+HEIGHT_NORMAL                 1.45
+HEIGHT_TITLE                  1.45
 HEIGHT_ZOOMEDTITLE            -1
 
+// gametypelist
+BOOL_GAMETYPELIST_ICON_BLUR   0
+
 // inputbox
 COLOR_INPUTBOX_F              '1 1 1'
 COLOR_INPUTBOX_N              '1 1 1'
@@ -142,6 +147,9 @@ ALPHA_LISTBOX_SELECTED        1
 COLOR_LISTBOX_SELECTED        '0.97 0.56 0.27'
 ALPHA_LISTBOX_WAITING         0.8
 COLOR_LISTBOX_WAITING         '0.73 0.82 0.9'
+ALPHA_LISTBOX_FOCUSED         0.55
+FADEALPHA_LISTBOX_FOCUSED     0.3
+COLOR_LISTBOX_FOCUSED         '0.09 0.42 0.69'
 
 // mainmenu
 ALPHAS_MAINMENU               '0.8 0.9 1'
diff --git a/gfx/menu/luminos/crosshairbutton_c.tga b/gfx/menu/luminos/crosshairbutton_c.tga
deleted file mode 100644 (file)
index 586f9b4..0000000
Binary files a/gfx/menu/luminos/crosshairbutton_c.tga and /dev/null differ
diff --git a/gfx/menu/luminos/crosshairbutton_d.tga b/gfx/menu/luminos/crosshairbutton_d.tga
deleted file mode 100755 (executable)
index cba9d88..0000000
Binary files a/gfx/menu/luminos/crosshairbutton_d.tga and /dev/null differ
diff --git a/gfx/menu/luminos/crosshairbutton_f.tga b/gfx/menu/luminos/crosshairbutton_f.tga
deleted file mode 100644 (file)
index 57d7d93..0000000
Binary files a/gfx/menu/luminos/crosshairbutton_f.tga and /dev/null differ
diff --git a/gfx/menu/luminos/crosshairbutton_n.tga b/gfx/menu/luminos/crosshairbutton_n.tga
deleted file mode 100755 (executable)
index ac94535..0000000
Binary files a/gfx/menu/luminos/crosshairbutton_n.tga and /dev/null differ
index a0484f4e37eeb9aba750de55cf2e203b654cdb7e..74b44139950cf7e46d00997d4f0a34d7435aa7bb 100644 (file)
Binary files a/gfx/menu/luminos/icon_ipv4.tga and b/gfx/menu/luminos/icon_ipv4.tga differ
index d3fdc03ee3e1cd4e6951e1b44beebd0d34b2111a..fe1227cb03383059c108918537888312707080f6 100644 (file)
Binary files a/gfx/menu/luminos/icon_ipv6.tga and b/gfx/menu/luminos/icon_ipv6.tga differ
index 0b31a343dc10305cf3829733ef92106b9a679854..63738cbcfa16f218b111ecde8b05fa2ba4279408 100644 (file)
Binary files a/gfx/menu/luminos/icon_mod_.tga and b/gfx/menu/luminos/icon_mod_.tga differ
index 518fd79649f966c692ca4e3562c9d774a94817df..065b84424651647058a56cb04d780e583f670465 100644 (file)
Binary files a/gfx/menu/luminos/icon_mod_MinstaGib.tga and b/gfx/menu/luminos/icon_mod_MinstaGib.tga differ
index cf88f77032e403a405b64007125995079d8a2b34..00acb711750154ab87ec26b7b693592cd8bd8343 100644 (file)
Binary files a/gfx/menu/luminos/icon_mod_NewToys.tga and b/gfx/menu/luminos/icon_mod_NewToys.tga differ
index 743722ea1817a237201c552a13aae63772c3defd..42e92c68ce0407b23e3a9171668210bdc9a758e0 100644 (file)
Binary files a/gfx/menu/luminos/icon_mod_Overkill.tga and b/gfx/menu/luminos/icon_mod_Overkill.tga differ
index 518fd79649f966c692ca4e3562c9d774a94817df..065b84424651647058a56cb04d780e583f670465 100644 (file)
Binary files a/gfx/menu/luminos/icon_mod_instagib.tga and b/gfx/menu/luminos/icon_mod_instagib.tga differ
index 62980d257acf7c009589f7d256612dd106cf70a8..7f7a1302946720c94e4990b3e3b5e9d1a7d1b676 100644 (file)
Binary files a/gfx/menu/luminos/icon_pure1.tga and b/gfx/menu/luminos/icon_pure1.tga differ
index 77af6c8dc0dfededc9af62be884e9eb482f55a90..ca0384fb554135f88ed4bf13a41c3b3e849497f9 100755 (executable)
@@ -1,4 +1,4 @@
-title Luminos (default)
+title Luminos
 author sev
 
 // Colors: 'Red Green Blue'
@@ -32,9 +32,9 @@ HEIGHT_DIALOGBORDER             1
 
 // font sizes (used for everything)
 FONTSIZE_NORMAL                 12
-HEIGHT_NORMAL                   1.5
+HEIGHT_NORMAL                   1.45
 FONTSIZE_TITLE                  16
-HEIGHT_TITLE                    1.5
+HEIGHT_TITLE                    1.45
 HEIGHT_ZOOMEDTITLE              -1
 
 // general
@@ -108,6 +108,9 @@ COLOR_LISTBOX_SELECTED          '1 0.4375 0'
 ALPHA_LISTBOX_SELECTED          1
 COLOR_LISTBOX_WAITING           '1 1 1'
 ALPHA_LISTBOX_WAITING           0.5
+COLOR_LISTBOX_FOCUSED           '0 0.25 0.5'
+ALPHA_LISTBOX_FOCUSED           0.6
+FADEALPHA_LISTBOX_FOCUSED       0.3
 
 // item: map list
 COLOR_MAPLIST_TITLE             '1 1 1'
@@ -170,9 +173,6 @@ COLOR_CHECKBOX_C                '1 1 1'
 COLOR_CHECKBOX_F                '1 1 1'
 COLOR_CHECKBOX_D                '1 1 1'
 
-// item: crosshair button
-//   uses "crosshairbutton" images
-
 // dialog background colors
 //   uses "border" images
 COLOR_DIALOG_MULTIPLAYER        '1 1 1'
@@ -196,6 +196,9 @@ COLOR_DIALOG_SCREENSHOTVIEWER   '1 1 1'
 COLOR_DIALOG_CVARS              '1 0 0'
 COLOR_DIALOG_HUDCONFIRM         '1 0 0'
 
+// gametypelist
+BOOL_GAMETYPELIST_ICON_BLUR     1
+
 // item: input box
 //   uses "inputbox" images
 COLOR_INPUTBOX_N                '1 1 1'
@@ -221,8 +224,10 @@ ALPHA_KEYGRABBER_KEYS           0.7
 // item: charmap
 ALPHA_CHARMAP_CHAR              0.85
 COLOR_CHARMAP_CHAR              '1 1 1'
-ALPHA_CHARMAP_FOCUS             1
-COLOR_CHARMAP_FOCUS             '0 0.25 0.5'
+
+// item: crosshairpicker
+ALPHA_CROSSHAIRPICKER_CROSSHAIR 0.6
+COLOR_CROSSHAIRPICKER_CROSSHAIR '1 1 1'
 
 // item: radio button
 //   uses "radiobutton" images
diff --git a/gfx/menu/wickedx/crosshairbutton_c.tga b/gfx/menu/wickedx/crosshairbutton_c.tga
deleted file mode 100644 (file)
index 1c294f7..0000000
Binary files a/gfx/menu/wickedx/crosshairbutton_c.tga and /dev/null differ
diff --git a/gfx/menu/wickedx/crosshairbutton_d.tga b/gfx/menu/wickedx/crosshairbutton_d.tga
deleted file mode 100755 (executable)
index 110faa1..0000000
Binary files a/gfx/menu/wickedx/crosshairbutton_d.tga and /dev/null differ
diff --git a/gfx/menu/wickedx/crosshairbutton_f.tga b/gfx/menu/wickedx/crosshairbutton_f.tga
deleted file mode 100644 (file)
index 0031c35..0000000
Binary files a/gfx/menu/wickedx/crosshairbutton_f.tga and /dev/null differ
diff --git a/gfx/menu/wickedx/crosshairbutton_n.tga b/gfx/menu/wickedx/crosshairbutton_n.tga
deleted file mode 100755 (executable)
index ac94535..0000000
Binary files a/gfx/menu/wickedx/crosshairbutton_n.tga and /dev/null differ
index a0484f4e37eeb9aba750de55cf2e203b654cdb7e..74b44139950cf7e46d00997d4f0a34d7435aa7bb 100644 (file)
Binary files a/gfx/menu/wickedx/icon_ipv4.tga and b/gfx/menu/wickedx/icon_ipv4.tga differ
index d3fdc03ee3e1cd4e6951e1b44beebd0d34b2111a..fe1227cb03383059c108918537888312707080f6 100644 (file)
Binary files a/gfx/menu/wickedx/icon_ipv6.tga and b/gfx/menu/wickedx/icon_ipv6.tga differ
index 0b31a343dc10305cf3829733ef92106b9a679854..63738cbcfa16f218b111ecde8b05fa2ba4279408 100644 (file)
Binary files a/gfx/menu/wickedx/icon_mod_.tga and b/gfx/menu/wickedx/icon_mod_.tga differ
index 518fd79649f966c692ca4e3562c9d774a94817df..065b84424651647058a56cb04d780e583f670465 100644 (file)
Binary files a/gfx/menu/wickedx/icon_mod_MinstaGib.tga and b/gfx/menu/wickedx/icon_mod_MinstaGib.tga differ
index cf88f77032e403a405b64007125995079d8a2b34..00acb711750154ab87ec26b7b693592cd8bd8343 100644 (file)
Binary files a/gfx/menu/wickedx/icon_mod_NewToys.tga and b/gfx/menu/wickedx/icon_mod_NewToys.tga differ
index 743722ea1817a237201c552a13aae63772c3defd..42e92c68ce0407b23e3a9171668210bdc9a758e0 100644 (file)
Binary files a/gfx/menu/wickedx/icon_mod_Overkill.tga and b/gfx/menu/wickedx/icon_mod_Overkill.tga differ
index 518fd79649f966c692ca4e3562c9d774a94817df..065b84424651647058a56cb04d780e583f670465 100644 (file)
Binary files a/gfx/menu/wickedx/icon_mod_instagib.tga and b/gfx/menu/wickedx/icon_mod_instagib.tga differ
index 62980d257acf7c009589f7d256612dd106cf70a8..7f7a1302946720c94e4990b3e3b5e9d1a7d1b676 100644 (file)
Binary files a/gfx/menu/wickedx/icon_pure1.tga and b/gfx/menu/wickedx/icon_pure1.tga differ
index 8b56baa1f3c54a54d561f3a335017a68424fa876..b7011a0b0e18369246a573e86f52dd0d22174bb4 100644 (file)
@@ -108,6 +108,9 @@ COLOR_LISTBOX_SELECTED          '0.875 0.375 0'
 ALPHA_LISTBOX_SELECTED          1
 COLOR_LISTBOX_WAITING           '1 1 1'
 ALPHA_LISTBOX_WAITING           0.5
+COLOR_LISTBOX_FOCUSED           '0 0.375 0.75'
+ALPHA_LISTBOX_FOCUSED           0.35
+FADEALPHA_LISTBOX_FOCUSED       0.75
 
 // item: map list
 COLOR_MAPLIST_TITLE             '1 1 1'
@@ -170,9 +173,6 @@ COLOR_CHECKBOX_C                '0.5 0.75 1'
 COLOR_CHECKBOX_F                '0.5 0.75 1'
 COLOR_CHECKBOX_D                '1 1 1'
 
-// item: crosshair button
-//   uses "crosshairbutton" images
-
 // dialog background colors
 //   uses "border" images
 COLOR_DIALOG_MULTIPLAYER        '1 1 1'
@@ -196,6 +196,9 @@ COLOR_DIALOG_SCREENSHOTVIEWER   '1 1 1'
 COLOR_DIALOG_CVARS              '1 0 0'
 COLOR_DIALOG_HUDCONFIRM         '1 0 0'
 
+// gametypelist
+BOOL_GAMETYPELIST_ICON_BLUR     1
+
 // item: input box
 //   uses "inputbox" images
 COLOR_INPUTBOX_N                '1 1 1'
@@ -221,8 +224,10 @@ ALPHA_KEYGRABBER_KEYS           0.7
 // item: charmap
 ALPHA_CHARMAP_CHAR              0.85
 COLOR_CHARMAP_CHAR              '1 1 1'
-ALPHA_CHARMAP_FOCUS             0.75
-COLOR_CHARMAP_FOCUS             '0 0.375 0.75'
+
+// item: crosshairpicker
+ALPHA_CROSSHAIRPICKER_CROSSHAIR 0.85
+COLOR_CROSSHAIRPICKER_CROSSHAIR '1 1 1'
 
 // item: radio button
 //   uses "radiobutton" images
diff --git a/gfx/menu/xaw/crosshairbutton_c.tga b/gfx/menu/xaw/crosshairbutton_c.tga
deleted file mode 100644 (file)
index 646c64e..0000000
Binary files a/gfx/menu/xaw/crosshairbutton_c.tga and /dev/null differ
diff --git a/gfx/menu/xaw/crosshairbutton_d.tga b/gfx/menu/xaw/crosshairbutton_d.tga
deleted file mode 100644 (file)
index 110faa1..0000000
Binary files a/gfx/menu/xaw/crosshairbutton_d.tga and /dev/null differ
diff --git a/gfx/menu/xaw/crosshairbutton_f.tga b/gfx/menu/xaw/crosshairbutton_f.tga
deleted file mode 100644 (file)
index d8f25ef..0000000
Binary files a/gfx/menu/xaw/crosshairbutton_f.tga and /dev/null differ
diff --git a/gfx/menu/xaw/crosshairbutton_n.tga b/gfx/menu/xaw/crosshairbutton_n.tga
deleted file mode 100644 (file)
index 5d678a6..0000000
Binary files a/gfx/menu/xaw/crosshairbutton_n.tga and /dev/null differ
index a0484f4e37eeb9aba750de55cf2e203b654cdb7e..74b44139950cf7e46d00997d4f0a34d7435aa7bb 100644 (file)
Binary files a/gfx/menu/xaw/icon_ipv4.tga and b/gfx/menu/xaw/icon_ipv4.tga differ
index d3fdc03ee3e1cd4e6951e1b44beebd0d34b2111a..fe1227cb03383059c108918537888312707080f6 100644 (file)
Binary files a/gfx/menu/xaw/icon_ipv6.tga and b/gfx/menu/xaw/icon_ipv6.tga differ
index 0b31a343dc10305cf3829733ef92106b9a679854..63738cbcfa16f218b111ecde8b05fa2ba4279408 100644 (file)
Binary files a/gfx/menu/xaw/icon_mod_.tga and b/gfx/menu/xaw/icon_mod_.tga differ
index 518fd79649f966c692ca4e3562c9d774a94817df..065b84424651647058a56cb04d780e583f670465 100644 (file)
Binary files a/gfx/menu/xaw/icon_mod_MinstaGib.tga and b/gfx/menu/xaw/icon_mod_MinstaGib.tga differ
index cf88f77032e403a405b64007125995079d8a2b34..00acb711750154ab87ec26b7b693592cd8bd8343 100644 (file)
Binary files a/gfx/menu/xaw/icon_mod_NewToys.tga and b/gfx/menu/xaw/icon_mod_NewToys.tga differ
index 743722ea1817a237201c552a13aae63772c3defd..42e92c68ce0407b23e3a9171668210bdc9a758e0 100644 (file)
Binary files a/gfx/menu/xaw/icon_mod_Overkill.tga and b/gfx/menu/xaw/icon_mod_Overkill.tga differ
index 518fd79649f966c692ca4e3562c9d774a94817df..065b84424651647058a56cb04d780e583f670465 100644 (file)
Binary files a/gfx/menu/xaw/icon_mod_instagib.tga and b/gfx/menu/xaw/icon_mod_instagib.tga differ
index 62980d257acf7c009589f7d256612dd106cf70a8..7f7a1302946720c94e4990b3e3b5e9d1a7d1b676 100644 (file)
Binary files a/gfx/menu/xaw/icon_pure1.tga and b/gfx/menu/xaw/icon_pure1.tga differ
index 57c6f2a35009163a49426aa802b167804474a6f3..5f4bbaad40211135e157b03f89e82e99ef337475 100644 (file)
@@ -107,9 +107,6 @@ ALPHA_CREDITS_PERSON            1
 ROWS_CREDITS                    20
 WIDTH_CREDITS                   0.5
 
-// item: crosshair button
-//   uses "crosshairbutton" images
-
 // item: cvar list
 ALPHA_CVARLIST_SAVED            1
 ALPHA_CVARLIST_TEMPORARY        0.7
@@ -117,6 +114,9 @@ COLOR_CVARLIST_CHANGED          '1 0 0'
 COLOR_CVARLIST_UNCHANGED        '1 1 1'
 COLOR_CVARLIST_CONTROLS         '1 0 0'
 
+// gametypelist
+BOOL_GAMETYPELIST_ICON_BLUR     1
+
 // item: dialog
 //   uses "border" images
 //   uses "closebutton" images
@@ -152,8 +152,11 @@ COLOR_LISTBOX_SELECTED          '0 0 0'
 ALPHA_LISTBOX_SELECTED          1
 COLOR_LISTBOX_WAITING           '1 0 0'
 ALPHA_LISTBOX_WAITING           0.5
-COLOR_LISTBOX_BACKGROUND               '0 0 0'
-ALPHA_LISTBOX_BACKGROUND               0
+COLOR_LISTBOX_BACKGROUND        '0 0 0'
+ALPHA_LISTBOX_BACKGROUND        0
+COLOR_LISTBOX_FOCUSED           '0 0 0'
+ALPHA_LISTBOX_FOCUSED           0.3
+FADEALPHA_LISTBOX_FOCUSED       0.3
 
 // item: map list
 COLOR_MAPLIST_TITLE             '1 1 1'
@@ -176,8 +179,10 @@ ALPHA_MODELTITLE                1
 // item: charmap
 ALPHA_CHARMAP_CHAR              0.85
 COLOR_CHARMAP_CHAR              '1 1 1'
-ALPHA_CHARMAP_FOCUS             0.5
-COLOR_CHARMAP_FOCUS             '0 0 0'
+
+// item: crosshairpicker
+ALPHA_CROSSHAIRPICKER_CROSSHAIR 0.85
+COLOR_CROSSHAIRPICKER_CROSSHAIR '1 1 1'
 
 // item: radio button
 //   uses "radiobutton" images
diff --git a/models/turrets/terrainbase.md3 b/models/turrets/terrainbase.md3
deleted file mode 100644 (file)
index ee67dc5..0000000
Binary files a/models/turrets/terrainbase.md3 and /dev/null differ
diff --git a/physics.cfg b/physics.cfg
new file mode 100644 (file)
index 0000000..58d1b1f
--- /dev/null
@@ -0,0 +1,256 @@
+// ==================================================
+//  Main configuration for client selectable physics
+// ==================================================
+
+
+// ==============
+//  Main options
+// ==============
+seta cl_physics "default" "client selected physics set"
+
+set g_physics_clientselect 0 "allow clients to select their physics set"
+set g_physics_clientselect_options "xonotic nexuiz quake warsow defrag quake3 vecxis quake2 bones"
+set g_physics_clientselect_default "" "override default physics"
+
+// =========
+//  Xonotic
+// =========
+set g_physics_xonotic_airaccel_qw -0.8
+set g_physics_xonotic_airstrafeaccel_qw -0.95
+set g_physics_xonotic_airspeedlimit_nonqw 900
+set g_physics_xonotic_maxspeed 360
+set g_physics_xonotic_jumpvelocity 260
+set g_physics_xonotic_maxairstrafespeed 100
+set g_physics_xonotic_maxairspeed 360
+set g_physics_xonotic_airstrafeaccelerate 18
+set g_physics_xonotic_warsowbunny_turnaccel 0
+set g_physics_xonotic_airaccel_qw_stretchfactor 2
+set g_physics_xonotic_airaccel_sideways_friction 0
+set g_physics_xonotic_aircontrol 100
+set g_physics_xonotic_aircontrol_power 2
+set g_physics_xonotic_aircontrol_penalty 0
+set g_physics_xonotic_warsowbunny_airforwardaccel 1.00001
+set g_physics_xonotic_warsowbunny_topspeed 925
+set g_physics_xonotic_warsowbunny_accel 0.1593
+set g_physics_xonotic_warsowbunny_backtosideratio 0.8
+set g_physics_xonotic_friction 6
+set g_physics_xonotic_accelerate 15
+set g_physics_xonotic_stopspeed 100
+set g_physics_xonotic_airaccelerate 2
+set g_physics_xonotic_airstopaccelerate 3
+
+// ========
+//  Nexuiz
+// ========
+set g_physics_nexuiz_airaccel_qw 0.95
+set g_physics_nexuiz_airstrafeaccel_qw 0
+set g_physics_nexuiz_airspeedlimit_nonqw 0
+set g_physics_nexuiz_maxspeed 400
+set g_physics_nexuiz_jumpvelocity 300 "333 to match xonotic physics"
+set g_physics_nexuiz_maxairstrafespeed 0
+set g_physics_nexuiz_maxairspeed 220
+set g_physics_nexuiz_airstrafeaccelerate 0
+set g_physics_nexuiz_warsowbunny_turnaccel 0
+set g_physics_nexuiz_airaccel_qw_stretchfactor 0
+set g_physics_nexuiz_airaccel_sideways_friction 0.35
+set g_physics_nexuiz_aircontrol 0
+set g_physics_nexuiz_aircontrol_power 2
+set g_physics_nexuiz_aircontrol_penalty 0
+set g_physics_nexuiz_warsowbunny_airforwardaccel 1.00001
+set g_physics_nexuiz_warsowbunny_topspeed 925
+set g_physics_nexuiz_warsowbunny_accel 0.1593
+set g_physics_nexuiz_warsowbunny_backtosideratio 0.8
+set g_physics_nexuiz_friction 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
+
+// =======
+//  Quake
+// =======
+set g_physics_quake_airaccel_qw 1
+set g_physics_quake_airstrafeaccel_qw 0
+set g_physics_quake_airspeedlimit_nonqw 0
+set g_physics_quake_maxspeed 320
+set g_physics_quake_jumpvelocity 270
+set g_physics_quake_maxairstrafespeed 0
+set g_physics_quake_maxairspeed 30
+set g_physics_quake_airstrafeaccelerate 0
+set g_physics_quake_warsowbunny_turnaccel 0
+set g_physics_quake_airaccel_qw_stretchfactor 0
+set g_physics_quake_airaccel_sideways_friction 0
+set g_physics_quake_aircontrol 0
+set g_physics_quake_aircontrol_power 2
+set g_physics_quake_aircontrol_penalty 0
+set g_physics_quake_warsowbunny_airforwardaccel 1.00001
+set g_physics_quake_warsowbunny_topspeed 925
+set g_physics_quake_warsowbunny_accel 0.1593
+set g_physics_quake_warsowbunny_backtosideratio 0.8
+set g_physics_quake_friction 4
+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
+
+// ========
+//  Warsow
+// ========
+set g_physics_warsow_airaccel_qw 1
+set g_physics_warsow_airstrafeaccel_qw 0
+set g_physics_warsow_airspeedlimit_nonqw 0
+set g_physics_warsow_maxspeed 320
+set g_physics_warsow_jumpvelocity 280
+set g_physics_warsow_maxairstrafespeed 30
+set g_physics_warsow_maxairspeed 320
+set g_physics_warsow_airstrafeaccelerate 70
+set g_physics_warsow_warsowbunny_turnaccel 9
+set g_physics_warsow_airaccel_qw_stretchfactor 0
+set g_physics_warsow_airaccel_sideways_friction 0
+set g_physics_warsow_aircontrol 0
+set g_physics_warsow_aircontrol_power 2
+set g_physics_warsow_aircontrol_penalty 0
+set g_physics_warsow_warsowbunny_airforwardaccel 1.00001
+set g_physics_warsow_warsowbunny_topspeed 925
+set g_physics_warsow_warsowbunny_accel 0.1593
+set g_physics_warsow_warsowbunny_backtosideratio 0.8
+set g_physics_warsow_friction 8
+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
+
+// ========
+//  DeFrag
+// ========
+set g_physics_defrag_airaccel_qw 0.95
+set g_physics_defrag_airstrafeaccel_qw 1
+set g_physics_defrag_airspeedlimit_nonqw 0
+set g_physics_defrag_maxspeed 320
+set g_physics_defrag_jumpvelocity 270
+set g_physics_defrag_maxairstrafespeed 30
+set g_physics_defrag_maxairspeed 320
+set g_physics_defrag_airstrafeaccelerate 70
+set g_physics_defrag_warsowbunny_turnaccel 0
+set g_physics_defrag_airaccel_qw_stretchfactor 0
+set g_physics_defrag_airaccel_sideways_friction 0
+set g_physics_defrag_aircontrol 150
+set g_physics_defrag_aircontrol_power 2
+set g_physics_defrag_aircontrol_penalty 0
+set g_physics_defrag_warsowbunny_airforwardaccel 1.00001
+set g_physics_defrag_warsowbunny_topspeed 925
+set g_physics_defrag_warsowbunny_accel 0.1593
+set g_physics_defrag_warsowbunny_backtosideratio 0.8
+set g_physics_defrag_friction 5.8
+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
+
+// =========
+//  Quake 3
+// =========
+set g_physics_quake3_airaccel_qw 1
+set g_physics_quake3_airstrafeaccel_qw 0
+set g_physics_quake3_airspeedlimit_nonqw 0
+set g_physics_quake3_maxspeed 320
+set g_physics_quake3_jumpvelocity 270
+set g_physics_quake3_maxairstrafespeed 0
+set g_physics_quake3_maxairspeed 320
+set g_physics_quake3_airstrafeaccelerate 0
+set g_physics_quake3_warsowbunny_turnaccel 0
+set g_physics_quake3_airaccel_qw_stretchfactor 0
+set g_physics_quake3_airaccel_sideways_friction 0
+set g_physics_quake3_aircontrol 0
+set g_physics_quake3_aircontrol_power 2
+set g_physics_quake3_aircontrol_penalty 0
+set g_physics_quake3_warsowbunny_airforwardaccel 1.00001
+set g_physics_quake3_warsowbunny_topspeed 925
+set g_physics_quake3_warsowbunny_accel 0.1593
+set g_physics_quake3_warsowbunny_backtosideratio 0.8
+set g_physics_quake3_friction 6
+set g_physics_quake3_accelerate 10
+set g_physics_quake3_stopspeed 100
+set g_physics_quake3_airaccelerate 1
+set g_physics_quake3_airstopaccelerate 0
+
+// ========
+//  Vecxis
+// ========
+set g_physics_vecxis_airaccel_qw 0.93
+set g_physics_vecxis_airstrafeaccel_qw 0
+set g_physics_vecxis_airspeedlimit_nonqw 0
+set g_physics_vecxis_maxspeed 400
+set g_physics_vecxis_jumpvelocity 300 "333 to match xonotic physics"
+set g_physics_vecxis_maxairstrafespeed 0
+set g_physics_vecxis_maxairspeed 220
+set g_physics_vecxis_airstrafeaccelerate 0
+set g_physics_vecxis_warsowbunny_turnaccel 0
+set g_physics_vecxis_airaccel_qw_stretchfactor 0
+set g_physics_vecxis_airaccel_sideways_friction 0.3
+set g_physics_vecxis_aircontrol 0
+set g_physics_vecxis_aircontrol_power 2
+set g_physics_vecxis_aircontrol_penalty 0
+set g_physics_vecxis_warsowbunny_airforwardaccel 1.00001
+set g_physics_vecxis_warsowbunny_topspeed 925
+set g_physics_vecxis_warsowbunny_accel 0.1593
+set g_physics_vecxis_warsowbunny_backtosideratio 0.8
+set g_physics_vecxis_friction 5
+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
+
+// =========
+//  Quake 2
+// =========
+set g_physics_quake2_airaccel_qw 1
+set g_physics_quake2_airstrafeaccel_qw 0
+set g_physics_quake2_airspeedlimit_nonqw 0
+set g_physics_quake2_maxspeed 300
+set g_physics_quake2_jumpvelocity 270
+set g_physics_quake2_maxairstrafespeed 0
+set g_physics_quake2_maxairspeed 300
+set g_physics_quake2_airstrafeaccelerate 0
+set g_physics_quake2_warsowbunny_turnaccel 0
+set g_physics_quake2_airaccel_qw_stretchfactor 0
+set g_physics_quake2_airaccel_sideways_friction 0
+set g_physics_quake2_aircontrol 0
+set g_physics_quake2_aircontrol_power 2
+set g_physics_quake2_aircontrol_penalty 0
+set g_physics_quake2_warsowbunny_airforwardaccel 1.00001
+set g_physics_quake2_warsowbunny_topspeed 925
+set g_physics_quake2_warsowbunny_accel 0.1593
+set g_physics_quake2_warsowbunny_backtosideratio 0.8
+set g_physics_quake2_friction 6
+set g_physics_quake2_accelerate 10
+set g_physics_quake2_stopspeed 100
+set g_physics_quake2_airaccelerate 1
+set g_physics_quake2_airstopaccelerate 0
+
+// =======
+//  Bones
+// =======
+set g_physics_bones_airaccel_qw 1
+set g_physics_bones_airstrafeaccel_qw 1
+set g_physics_bones_airspeedlimit_nonqw 0
+set g_physics_bones_maxspeed 320
+set g_physics_bones_jumpvelocity 270
+set g_physics_bones_maxairstrafespeed 30
+set g_physics_bones_maxairspeed 320
+set g_physics_bones_airstrafeaccelerate 70
+set g_physics_bones_warsowbunny_turnaccel 0
+set g_physics_bones_airaccel_qw_stretchfactor 0
+set g_physics_bones_airaccel_sideways_friction 0
+set g_physics_bones_aircontrol 150
+set g_physics_bones_aircontrol_power 2
+set g_physics_bones_aircontrol_penalty 0
+set g_physics_bones_warsowbunny_airforwardaccel 1.00001
+set g_physics_bones_warsowbunny_topspeed 925
+set g_physics_bones_warsowbunny_accel 0.1593
+set g_physics_bones_warsowbunny_backtosideratio 0.8
+set g_physics_bones_friction 5.97
+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
index e03a6d4171b442f1f5297e3c2f9db5b676cd7c99..c109e1157636e5b6fb91f658a0c8ba37910b922f 100644 (file)
@@ -44,6 +44,7 @@ sv_warsowbunny_accel 0.1593
 sv_warsowbunny_topspeed 925
 sv_warsowbunny_backtosideratio 0.8
 sv_friction_on_land 0
+sv_friction_slick 0.5
 sv_doublejump 0
 sv_jumpspeedcap_min ""
 sv_jumpspeedcap_max ""
index 77926d05f7bf99a21aba09dee93c8ce864c974bb..6dadcf161bd1078d9b6b4227e84c6d9624b0f7e0 100644 (file)
@@ -37,6 +37,7 @@ sv_warsowbunny_accel 0.1593
 sv_warsowbunny_topspeed 925
 sv_warsowbunny_backtosideratio 0.8
 sv_friction_on_land 0
+sv_friction_slick 0.5
 sv_doublejump 0
 sv_jumpspeedcap_min ""
 sv_jumpspeedcap_max ""
index e2a3ef648087b64716ae7b5a7153a9663995ec67..a3e42a977eca1a69fc3ba438f7aa69f305466e34 100644 (file)
@@ -43,6 +43,7 @@ sv_warsowbunny_accel 0.1593
 sv_warsowbunny_topspeed 925
 sv_warsowbunny_backtosideratio 0.8
 sv_friction_on_land 0
+sv_friction_slick 0.5
 sv_doublejump 0
 sv_jumpspeedcap_min ""
 sv_jumpspeedcap_max ""
index 0acb6e9535955b03e79f281a2a502f95c6946f58..8597e9e005d77020ea96c2375efa78ba56887b8c 100644 (file)
@@ -35,6 +35,7 @@ sv_warsowbunny_accel 0.1593
 sv_warsowbunny_topspeed 925
 sv_warsowbunny_backtosideratio 0.8
 sv_friction_on_land 0
+sv_friction_slick 0.5
 sv_doublejump 1
 sv_jumpspeedcap_min 0
 sv_jumpspeedcap_max 0.5
index cac90b4ee748314e844c882df28d9edbbb8eb8c6..6cb0780dd988ee2f7ffafed71d16e8348d0a8b4b 100644 (file)
@@ -35,6 +35,7 @@ sv_warsowbunny_accel 0.1593
 sv_warsowbunny_topspeed 925
 sv_warsowbunny_backtosideratio 0.8
 sv_friction_on_land 0
+sv_friction_slick 0.5
 sv_doublejump 0
 sv_jumpspeedcap_min ""
 sv_jumpspeedcap_max ""
index abbd25ffd8ba40041322b62fee2577aafe85a286..f53707e829f482c39e0f6dcdee0c54d54d4aa3c1 100644 (file)
@@ -15,8 +15,13 @@ QCCFLAGS ?= \
        -Werror -fno-bail-on-werror -Wall \
        -fftepp -fftepp-predefs -Wcpp -futf8 \
        $(QCCFLAGS_WTFS) \
+       $(QCCFLAGS_FEATURES) \
        $(QCCFLAGS_EXTRA) $(QCCFLAGS_WATERMARK)
 
+QCCFLAGS_FEATURES ?= \
+       -DVEHICLES_ENABLED=1 \
+       -DVEHICLES_USE_ODE=0
+
 # xonotic build system overrides this by command line argument to turn off the update-cvarcount step
 XON_BUILDSYSTEM =
 
diff --git a/qcsrc/client/_all.qh b/qcsrc/client/_all.qh
new file mode 100644 (file)
index 0000000..e758fdb
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef CLIENT_ALL_H
+#define CLIENT_ALL_H
+
+#include "autocvars.qh"
+#include "defs.qh"
+#include "main.qh"
+#include "miscfunctions.qh"
+
+#include "../dpdefs/csprogsdefs.qh"
+
+#endif
index 116dba7d3cc5898bf6acc70f13772e810babdd6c..19e51cedc6b98f2611c274476fba9cc0430300d2 100644 (file)
@@ -1,13 +1,9 @@
-#if defined(CSQC)
-       #include "../dpdefs/csprogsdefs.qh"
-    #include "../common/stats.qh"
-    #include "../common/util.qh"
-    #include "autocvars.qh"
-    #include "../common/notifications.qh"
-    #include "main.qh"
-#elif defined(MENUQC)
-#elif defined(SVQC)
-#endif
+#include "announcer.qh"
+#include "_all.qh"
+
+#include "../common/notifications.qh"
+#include "../common/stats.qh"
+#include "../common/util.qh"
 
 bool announcer_1min;
 bool announcer_5min;
diff --git a/qcsrc/client/announcer.qh b/qcsrc/client/announcer.qh
new file mode 100644 (file)
index 0000000..620b845
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef ANNOUNCER_H
+#define ANNOUNCER_H
+
+void Announcer();
+
+#endif
index 48666902abe838063d56603af1721427a0eea5b7..b9a241da9feb143d86696d4f9bed8e7c22a5e758 100644 (file)
@@ -282,10 +282,12 @@ float autocvar_hud_panel_notify_fontsize;
 float autocvar_hud_panel_notify_time;
 float autocvar_hud_panel_notify_icon_aspect;
 bool autocvar_hud_panel_physics;
+float autocvar_hud_panel_physics_acceleration_movingaverage = 1;
 float autocvar_hud_panel_physics_acceleration_progressbar_mode;
 float autocvar_hud_panel_physics_acceleration_progressbar_scale;
 float autocvar_hud_panel_physics_acceleration_progressbar_nonlinear;
 float autocvar_hud_panel_physics_acceleration_max;
+float autocvar_hud_panel_physics_update_interval;
 int autocvar_hud_panel_physics_progressbar;
 bool autocvar_hud_panel_physics_acceleration_vertical;
 int autocvar_hud_panel_physics_baralign;
index b567190caa666f165cfe49bea7a09ea6fd8b0d73..697cae91ca3296d36c9d0c79612bb575a7ab4e38 100644 (file)
@@ -1,13 +1,7 @@
-#if defined(CSQC)
-       #include "../dpdefs/csprogsdefs.qh"
-       #include "defs.qh"
-       #include "../common/util.qh"
-       #include "autocvars.qh"
-       #include "bgmscript.qh"
-       #include "main.qh"
-#elif defined(MENUQC)
-#elif defined(SVQC)
-#endif
+#include "bgmscript.qh"
+#include "_all.qh"
+
+#include "../common/util.qh"
 
 #define CONSTANT_SPEED_DECAY
 
@@ -15,12 +9,12 @@ float bgmscriptbuf;
 float bgmscriptbufsize;
 float bgmscriptbufloaded;
 
-.float bgmscriptline;
-.float bgmscriptline0;
-.float bgmscriptvolume;
-.float bgmscripttime;
-.float bgmscriptstate;
-.float bgmscriptstatetime;
+class(BGMScript) .float bgmscriptline;
+class(BGMScript) .float bgmscriptline0;
+class(BGMScript) .float bgmscriptvolume;
+class(BGMScript) .float bgmscripttime;
+class(BGMScript) .float bgmscriptstate;
+class(BGMScript) .float bgmscriptstatetime;
 
 float GetAttackDecaySustainAmplitude(float a, float d, float s, float t)
 {
@@ -177,7 +171,7 @@ float GetTimeForAmplitude(entity e, float amp)
        }
 }
 
-float BGMScript(entity e)
+float doBGMScript(entity e)
 {
        float amp, vel;
 
index 910ef6b5df006c69f3347ad33363498d31f53a74..5921bb4bc7325126c5227353192a1aa1fe18c250 100644 (file)
@@ -1,14 +1,18 @@
 #ifndef BGMSCRIPT_H
 #define BGMSCRIPT_H
 
-.string bgmscript;
-.float bgmscriptattack;
-.float bgmscriptdecay;
-.float bgmscriptsustain;
-.float bgmscriptrelease;
+entityclass(BGMScript);
+class(BGMScript) .string bgmscript;
+class(BGMScript) .float bgmscriptattack;
+class(BGMScript) .float bgmscriptdecay;
+class(BGMScript) .float bgmscriptsustain;
+class(BGMScript) .float bgmscriptrelease;
 
-.float just_toggled;
+class(BGMScript) .float just_toggled;
 
+#ifdef CSQC
 void BGMScript_InitEntity(entity e);
-float BGMScript(entity e);
+float doBGMScript(entity e);
+#endif
+
 #endif
index 6068a799f752892a2d1dc8f86b7d412537c0644c..8961af2241a34dc489001a1f867a9b1c924da694 100644 (file)
@@ -1,17 +1,18 @@
-#if defined(CSQC)
-       #include "movetypes.qh"
-       #include "prandom.qh"
-       #include "rubble.qh"
+#include "casings.qh"
+#include "_all.qh"
 
-       .float cnt;
-       .float alpha;
-       .int state;
-#elif defined(MENUQC)
-#elif defined(SVQC)
-#endif
+#include "../common/movetypes/movetypes.qh"
+#include "prandom.qh"
+#include "rubble.qh"
 
+#include "../common/util.qh"
 
-.bool silent;
+.float cnt;
+.float alpha;
+.int state;
+
+entityclass(Casing);
+class(Casing) .bool silent;
 
 void Casing_Delete()
 {
diff --git a/qcsrc/client/casings.qh b/qcsrc/client/casings.qh
new file mode 100644 (file)
index 0000000..dafe66a
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef CASINGS_H
+#define CASINGS_H
+
+void Casings_Precache();
+
+void Ent_Casing(float isNew);
+
+#endif
diff --git a/qcsrc/client/command/all.qc b/qcsrc/client/command/all.qc
new file mode 100644 (file)
index 0000000..dcace65
--- /dev/null
@@ -0,0 +1,5 @@
+#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
new file mode 100644 (file)
index 0000000..34fc423
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef CLIENT_COMMANDS_ALL_H
+#define CLIENT_COMMANDS_ALL_H
+
+#include "../../common/command/all.qh"
+
+#include "cl_cmd.qh"
+
+#endif
index 7b74d2dd7fa56752889ee75f6abb3cdbb1e08115..ed8cb190d26ee803a68df32662ff62f3a9e14b2a 100644 (file)
@@ -3,8 +3,20 @@
 //  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 "../../common/mapinfo.qh"
+
 #include "../../common/command/generic.qh"
-#include "../../common/command/shared_defs.qh"
 
 void DrawDebugModel()
 {
@@ -339,6 +351,31 @@ void LocalCommand_mv_download(int request, int argc)
        }
 }
 
+void LocalCommand_find(int request, int argc)
+{
+       switch(request)
+       {
+               case CMD_REQUEST_COMMAND:
+               {
+                       entity client;
+
+                       for(client = world; (client = find(client, classname, argv(1))); )
+                               print(etos(client), "\n");
+
+                       return;
+               }
+
+               default:
+                       print("Incorrect parameters for ^2find^7\n");
+               case CMD_REQUEST_USAGE:
+               {
+                       print("\nUsage:^3 cl_cmd find classname\n");
+                       print("  Where 'classname' is the classname to search for.\n");
+                       return;
+               }
+       }
+}
+
 void LocalCommand_sendcvar(int request, int argc)
 {
        switch(request)
@@ -410,6 +447,7 @@ void LocalCommand_(int request)
        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 */
diff --git a/qcsrc/client/csqc_constants.qc b/qcsrc/client/csqc_constants.qc
deleted file mode 100644 (file)
index f11c31c..0000000
+++ /dev/null
@@ -1,143 +0,0 @@
-// MenuQC redefines world, change define it here to be safe
-#define world world
-
-// Mask Constants (set .drawmask on entities; use R_AddEntities to add all entities based on mask)
-const int              MASK_ENGINE                                             = 1;
-const int              MASK_ENGINEVIEWMODELS                   = 2;
-const int              MASK_NORMAL                                             = 4;
-
-// Renderflag Constants (used for CSQC entities)
-const int              RF_VIEWMODEL                                    = 1;
-const int              RF_EXTERNALMODEL                                = 2;
-const int              RF_DEPTHHACK                                    = 4;
-const int              RF_ADDITIVE                                             = 8;
-const int              RF_USEAXIS                                              = 16;
-
-// Viewflag Constants (use with R_SetView)
-const int              VF_MIN                                                  = 1;    //(vector)
-const int              VF_MIN_X                                                = 2;    //(float)
-const int              VF_MIN_Y                                                = 3;    //(float)
-const int              VF_SIZE                                                 = 4;    //(vector) (viewport size)
-const int              VF_SIZE_Y                                               = 5;    //(float)
-const int              VF_SIZE_X                                               = 6;    //(float)
-const int              VF_VIEWPORT                                             = 7;    //(vector, vector)
-const int              VF_FOV                                                  = 8;    //(vector)
-const int              VF_FOVX                                                 = 9;    //(float)
-const int              VF_FOVY                                                 = 10;   //(float)
-const int              VF_ORIGIN                                               = 11;   //(vector)
-const int              VF_ORIGIN_X                                             = 12;   //(float)
-const int              VF_ORIGIN_Y                                             = 13;   //(float)
-const int              VF_ORIGIN_Z                                             = 14;   //(float)
-const int              VF_ANGLES                                               = 15;   //(vector)
-const int              VF_ANGLES_X                                             = 16;   //(float)
-const int              VF_ANGLES_Y                                             = 17;   //(float)
-const int              VF_ANGLES_Z                                             = 18;   //(float)
-const int              VF_DRAWWORLD                                    = 19;   //(float)
-const int              VF_DRAWENGINEHUD                                = 20;   //(float)
-const int              VF_DRAWCROSSHAIR                                = 21;   //(float)
-const int              VF_PERSPECTIVE                                  = 200;  //(float)
-
-const int              VF_CL_VIEWANGLES                                = 33;   //(vector)
-const int              VF_CL_VIEWANGLES_X                              = 34;   //(float)
-const int              VF_CL_VIEWANGLES_Y                              = 35;   //(float)
-const int              VF_CL_VIEWANGLES_Z                              = 36;   //(float)
-
-// Quake-style Point Contents
-const int              CONTENT_EMPTY                                   = -1;
-const int              CONTENT_SOLID                                   = -2;
-const int              CONTENT_WATER                                   = -3;
-const int              CONTENT_SLIME                                   = -4;
-const int              CONTENT_LAVA                                    = -5;
-const int              CONTENT_SKY                                             = -6;
-
-// Vector / Hull Constants
-const vector   VEC_1                                                   = '1 1 1';
-const vector   VEC_0                                                   = '0 0 0';
-const vector   VEC_M1                                                  = '-1 -1 -1';
-
-const vector   VEC_HULL_MIN                                    = '-16 -16 -24';
-const vector   VEC_HULL_MAX                                    = '16 16 32';
-
-// Effect Constants
-const int      EF_NODRAW                                               = 16;
-const int      EF_ADDITIVE                                             = 32;
-const int      EF_BLUE                                                 = 64;
-const int      EF_RED                                                  = 128;
-const int      EF_FULLBRIGHT                                   = 512;
-const int      EF_FLAME                                                = 1024;
-const int      EF_STARDUST                                             = 2048;
-const int      EF_NOSHADOW                                             = 4096;
-const int      EF_NODEPTHTEST                                  = 8192;
-
-// Quake Player Flag Constants
-const int      PFL_ONGROUND                                    = 1;
-const int      PFL_CROUCH                                              = 2;
-const int      PFL_DEAD                                                = 4;
-const int      PFL_GIBBED                                              = 8;
-
-// Quake Temporary Entity Constants
-const int              TE_SPIKE                                                = 0;
-const int              TE_SUPERSPIKE                                   = 1;
-const int              TE_GUNSHOT                                              = 2;
-const int              TE_EXPLOSION                                    = 3;
-const int              TE_TAREXPLOSION                                 = 4;
-const int              TE_LIGHTNING1                                   = 5;
-const int              TE_LIGHTNING2                                   = 6;
-const int              TE_WIZSPIKE                                             = 7;
-const int              TE_KNIGHTSPIKE                                  = 8;
-const int              TE_LIGHTNING3                                   = 9;
-const int              TE_LAVASPLASH                                   = 10;
-const int              TE_TELEPORT                                             = 11;
-const int      TE_EXPLOSION2                                   = 12;
-// Darkplaces Additions
-const int      TE_EXPLOSIONRGB                                 = 53;
-const int              TE_GUNSHOTQUAD                                  = 57;
-const int              TE_EXPLOSIONQUAD                                = 70;
-
-// Math Constants
-const int      EXTRA_LOW                                               = -99999999;
-const int      EXTRA_HIGH                                              = 99999999;
-
-// Frik File Constants
-const int              FILE_READ                                               = 0;
-const int              FILE_APPEND                                             = 1;
-const int              FILE_WRITE                                              = 2;
-
-// Button values used by input_buttons
-const int BUTTON_ATTACK = 1;
-const int BUTTON_JUMP = 2;
-const int BUTTON_3 = 4;
-const int BUTTON_4 = 8;
-const int BUTTON_5 = 16;
-const int BUTTON_6 = 32;
-const int BUTTON7 = 64;
-const int BUTTON8 = 128;
-const int BUTTON_USE = 256;
-const int BUTTON_CHAT = 512;
-const int BUTTON_PRYDONCURSOR = 1024;
-const int BUTTON_9 = 2048;
-const int BUTTON_10 = 4096;
-const int BUTTON_11 = 8192;
-const int BUTTON_12 = 16384;
-const int BUTTON_13 = 32768;
-const int BUTTON_14 = 65536;
-const int BUTTON_15 = 131072;
-const int BUTTON_16 = 262144;
-
-const int SOLID_NOT            = 0; // no interaction with other objects
-const int SOLID_TRIGGER        = 1; // touch on edge, but not blocking
-const int SOLID_BBOX           = 2; // touch on edge, block
-const int SOLID_SLIDEBOX       = 3; // touch on edge, but not an onground
-const int SOLID_BSP            = 4; // bsp clip, touch on edge, block
-const int SOLID_CORPSE         = 5; // same as SOLID_BBOX, except it behaves as SOLID_NOT against SOLID_SLIDEBOX objects (players/monsters)
-
-const int MOVE_NORMAL = 0; // same as false
-const int MOVE_NOMONSTERS = 1; // same as true
-const int MOVE_MISSILE = 2; // save as movement with .movetype == MOVETYPE_FLYMISSILE
-const int MOVE_HITMODEL = 4;
-const int MOVE_WORLDONLY = 3;
-
-const int CAMERA_FREE = 1;
-const int CAMERA_CHASE = 2;
-
-const int EF_NOMODELFLAGS = 8388608;
diff --git a/qcsrc/client/csqc_constants.qh b/qcsrc/client/csqc_constants.qh
new file mode 100644 (file)
index 0000000..09d217b
--- /dev/null
@@ -0,0 +1,148 @@
+#ifndef CSQC_CONSTANTS
+#define CSQC_CONSTANTS
+
+// MenuQC redefines world, change define it here to be safe
+#define world world
+
+// Mask Constants (set .drawmask on entities; use R_AddEntities to add all entities based on mask)
+const int              MASK_ENGINE                                             = 1;
+const int              MASK_ENGINEVIEWMODELS                   = 2;
+const int              MASK_NORMAL                                             = 4;
+
+// Renderflag Constants (used for CSQC entities)
+const int              RF_VIEWMODEL                                    = 1;
+const int              RF_EXTERNALMODEL                                = 2;
+const int              RF_DEPTHHACK                                    = 4;
+const int              RF_ADDITIVE                                             = 8;
+const int              RF_USEAXIS                                              = 16;
+
+// Viewflag Constants (use with R_SetView)
+const int              VF_MIN                                                  = 1;    //(vector)
+const int              VF_MIN_X                                                = 2;    //(float)
+const int              VF_MIN_Y                                                = 3;    //(float)
+const int              VF_SIZE                                                 = 4;    //(vector) (viewport size)
+const int              VF_SIZE_Y                                               = 5;    //(float)
+const int              VF_SIZE_X                                               = 6;    //(float)
+const int              VF_VIEWPORT                                             = 7;    //(vector, vector)
+const int              VF_FOV                                                  = 8;    //(vector)
+const int              VF_FOVX                                                 = 9;    //(float)
+const int              VF_FOVY                                                 = 10;   //(float)
+const int              VF_ORIGIN                                               = 11;   //(vector)
+const int              VF_ORIGIN_X                                             = 12;   //(float)
+const int              VF_ORIGIN_Y                                             = 13;   //(float)
+const int              VF_ORIGIN_Z                                             = 14;   //(float)
+const int              VF_ANGLES                                               = 15;   //(vector)
+const int              VF_ANGLES_X                                             = 16;   //(float)
+const int              VF_ANGLES_Y                                             = 17;   //(float)
+const int              VF_ANGLES_Z                                             = 18;   //(float)
+const int              VF_DRAWWORLD                                    = 19;   //(float)
+const int              VF_DRAWENGINEHUD                                = 20;   //(float)
+const int              VF_DRAWCROSSHAIR                                = 21;   //(float)
+const int              VF_PERSPECTIVE                                  = 200;  //(float)
+
+const int              VF_CL_VIEWANGLES                                = 33;   //(vector)
+const int              VF_CL_VIEWANGLES_X                              = 34;   //(float)
+const int              VF_CL_VIEWANGLES_Y                              = 35;   //(float)
+const int              VF_CL_VIEWANGLES_Z                              = 36;   //(float)
+
+// Quake-style Point Contents
+const int              CONTENT_EMPTY                                   = -1;
+const int              CONTENT_SOLID                                   = -2;
+const int              CONTENT_WATER                                   = -3;
+const int              CONTENT_SLIME                                   = -4;
+const int              CONTENT_LAVA                                    = -5;
+const int              CONTENT_SKY                                             = -6;
+
+// Vector / Hull Constants
+const vector   VEC_1                                                   = '1 1 1';
+const vector   VEC_0                                                   = '0 0 0';
+const vector   VEC_M1                                                  = '-1 -1 -1';
+
+const vector   VEC_HULL_MIN                                    = '-16 -16 -24';
+const vector   VEC_HULL_MAX                                    = '16 16 32';
+
+// Effect Constants
+const int      EF_NODRAW                                               = 16;
+const int      EF_ADDITIVE                                             = 32;
+const int      EF_BLUE                                                 = 64;
+const int      EF_RED                                                  = 128;
+const int      EF_FULLBRIGHT                                   = 512;
+const int      EF_FLAME                                                = 1024;
+const int      EF_STARDUST                                             = 2048;
+const int      EF_NOSHADOW                                             = 4096;
+const int      EF_NODEPTHTEST                                  = 8192;
+
+// Quake Player Flag Constants
+const int      PFL_ONGROUND                                    = 1;
+const int      PFL_CROUCH                                              = 2;
+const int      PFL_DEAD                                                = 4;
+const int      PFL_GIBBED                                              = 8;
+
+// Quake Temporary Entity Constants
+const int              TE_SPIKE                                                = 0;
+const int              TE_SUPERSPIKE                                   = 1;
+const int              TE_GUNSHOT                                              = 2;
+const int              TE_EXPLOSION                                    = 3;
+const int              TE_TAREXPLOSION                                 = 4;
+const int              TE_LIGHTNING1                                   = 5;
+const int              TE_LIGHTNING2                                   = 6;
+const int              TE_WIZSPIKE                                             = 7;
+const int              TE_KNIGHTSPIKE                                  = 8;
+const int              TE_LIGHTNING3                                   = 9;
+const int              TE_LAVASPLASH                                   = 10;
+const int              TE_TELEPORT                                             = 11;
+const int      TE_EXPLOSION2                                   = 12;
+// Darkplaces Additions
+const int      TE_EXPLOSIONRGB                                 = 53;
+const int              TE_GUNSHOTQUAD                                  = 57;
+const int              TE_EXPLOSIONQUAD                                = 70;
+
+// Math Constants
+const int      EXTRA_LOW                                               = -99999999;
+const int      EXTRA_HIGH                                              = 99999999;
+
+// Frik File Constants
+const int              FILE_READ                                               = 0;
+const int              FILE_APPEND                                             = 1;
+const int              FILE_WRITE                                              = 2;
+
+// Button values used by input_buttons
+const int BUTTON_ATTACK = 1;
+const int BUTTON_JUMP = 2;
+const int BUTTON_3 = 4;
+const int BUTTON_4 = 8;
+const int BUTTON_5 = 16;
+const int BUTTON_6 = 32;
+const int BUTTON7 = 64;
+const int BUTTON8 = 128;
+const int BUTTON_USE = 256;
+const int BUTTON_CHAT = 512;
+const int BUTTON_PRYDONCURSOR = 1024;
+const int BUTTON_9 = 2048;
+const int BUTTON_10 = 4096;
+const int BUTTON_11 = 8192;
+const int BUTTON_12 = 16384;
+const int BUTTON_13 = 32768;
+const int BUTTON_14 = 65536;
+const int BUTTON_15 = 131072;
+const int BUTTON_16 = 262144;
+
+const int SOLID_NOT            = 0; // no interaction with other objects
+const int SOLID_TRIGGER        = 1; // touch on edge, but not blocking
+const int SOLID_BBOX           = 2; // touch on edge, block
+const int SOLID_SLIDEBOX       = 3; // touch on edge, but not an onground
+const int SOLID_BSP            = 4; // bsp clip, touch on edge, block
+const int SOLID_CORPSE         = 5; // same as SOLID_BBOX, except it behaves as SOLID_NOT against SOLID_SLIDEBOX objects (players/monsters)
+
+const int MOVE_NORMAL = 0; // same as false
+const int MOVE_NOMONSTERS = 1; // same as true
+const int MOVE_MISSILE = 2; // save as movement with .movetype == MOVETYPE_FLYMISSILE
+const int MOVE_HITMODEL = 4;
+const int MOVE_WORLDONLY = 3;
+
+const int CAMERA_FREE = 1;
+const int CAMERA_CHASE = 2;
+
+const int EF_NOMODELFLAGS = 8388608;
+
+#endif
index dde4461821ee9feef7e501d25961931082a79028..92cef15efff3316b3f936aa2dca50a95f359e575 100644 (file)
@@ -1,26 +1,24 @@
-#if defined(CSQC)
-       #include "gibs.qh"
-       #include "miscfunctions.qh"
-       #include "player_skeleton.qh"
-       #include "sortlist.qh"
+#include "csqcmodel_hooks.qh"
+#include "_all.qh"
 
-       #include "../client/weapons/projectile.qh"
+#include "gibs.qh"
+#include "player_skeleton.qh"
+#include "sortlist.qh"
 
-       #include "../common/animdecide.qh"
-       #include "../common/csqcmodel_settings.qh"
+#include "weapons/projectile.qh"
 
-       #include "../csqcmodellib/cl_model.qh"
-       #include "../csqcmodellib/cl_player.qh"
-       #include "../csqcmodellib/interpolate.qh"
+#include "../common/animdecide.qh"
+#include "../common/csqcmodel_settings.qh"
+#include "../common/teams.qh"
 
-       #include "../warpzonelib/mathlib.qh"
+#include "../csqcmodellib/cl_model.qh"
+#include "../csqcmodellib/cl_player.qh"
+#include "../csqcmodellib/interpolate.qh"
 
-       .float death_time;
-       .int modelflags;
-#elif defined(MENUQC)
-#elif defined(SVQC)
-#endif
+#include "../warpzonelib/mathlib.qh"
 
+.float death_time;
+.int modelflags;
 
 void CSQCModel_Hook_PreDraw(bool isplayer);
 
@@ -657,10 +655,10 @@ void CSQCModel_Hook_PreDraw(bool isplayer)
                        bool onground = 0;
                        if(self == csqcplayer)
                        {
-                               if(self.pmove_flags & PMF_ONGROUND)
+                               if(self.flags & FL_ONGROUND)
                                        onground = 1;
-                               self.anim_prev_pmove_flags = self.pmove_flags;
-                               if(self.pmove_flags & PMF_DUCKED)
+                               self.anim_prev_pmove_flags = self.flags;
+                               if(self.flags & FL_DUCKED)
                                        animdecide_setstate(self, self.anim_state | ANIMSTATE_DUCK, false);
                                else if(self.anim_state & ANIMSTATE_DUCK)
                                        animdecide_setstate(self, self.anim_state - ANIMSTATE_DUCK, false);
diff --git a/qcsrc/client/csqcmodel_hooks.qh b/qcsrc/client/csqcmodel_hooks.qh
new file mode 100644 (file)
index 0000000..8995880
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef CSQCMODEL_HOOKS
+#define CSQCMODEL_HOOKS
+
+void CSQCPlayer_Precache();
+
+#endif
index 000ef8bcc9f45106d9c33e38c085c1e66653ebb3..3626c44c617408555c5bb4c4eaede028fe6399db 100644 (file)
@@ -1,18 +1,23 @@
-#if defined(CSQC)
-       #include "../dpdefs/csprogsdefs.qh"
-       #include "defs.qh"
-       #include "../common/constants.qh"
-       #include "../common/util.qh"
-       #include "../common/weapons/weapons.qh"
-       #include "autocvars.qh"
-       #include "../common/deathtypes.qh"
-       #include "damage.qh"
-       #include "movetypes.qh"
-       #include "prandom.qh"
-       #include "vehicles/vehicles.qh"
-#elif defined(MENUQC)
-#elif defined(SVQC)
-#endif
+#include "damage.qh"
+#include "_all.qh"
+
+#include "gibs.qh"
+#include "prandom.qh"
+
+#include "vehicles/all.qh"
+
+#include "../common/constants.qh"
+#include "../common/deathtypes.qh"
+#include "../common/movetypes/movetypes.qh"
+#include "../common/util.qh"
+
+#include "../common/weapons/all.qh"
+
+.entity tag_entity;
+
+.float cnt;
+.int state;
+.bool isplayermodel;
 
 void DamageEffect_Think()
 {
@@ -47,7 +52,7 @@ void DamageEffect_Think()
        pointparticles(self.team, org, '0 0 0', 1);
 }
 
-void DamageEffect(vector hitorg, float dmg, int type, int specnum)
+void DamageEffect(vector hitorg, float thedamage, int type, int specnum)
 {
        // particle effects for players and objects damaged by weapons (eg: flames coming out of victims shot with rockets)
 
@@ -92,7 +97,7 @@ void DamageEffect(vector hitorg, float dmg, int type, int specnum)
                        return; // allow a single damage on non-skeletal models
        }
 
-       life = bound(autocvar_cl_damageeffect_lifetime_min, dmg * autocvar_cl_damageeffect_lifetime, autocvar_cl_damageeffect_lifetime_max);
+       life = bound(autocvar_cl_damageeffect_lifetime_min, thedamage * autocvar_cl_damageeffect_lifetime, autocvar_cl_damageeffect_lifetime_max);
 
        effectname = get_weaponinfo(DEATH_WEAPONOF(type)).netname;
 
@@ -121,7 +126,7 @@ void DamageEffect(vector hitorg, float dmg, int type, int specnum)
 
 void Ent_DamageInfo(float isNew)
 {
-       float dmg, rad, edge, thisdmg;
+       float thedamage, rad, edge, thisdmg;
        bool hitplayer = false;
        int species, forcemul;
        vector force, thisforce;
@@ -137,7 +142,7 @@ void Ent_DamageInfo(float isNew)
        w_org.y = ReadCoord();
        w_org.z = ReadCoord();
 
-       dmg = ReadByte();
+       thedamage = ReadByte();
        rad = ReadByte();
        edge = ReadByte();
        force = decompressShortVector(ReadShort());
@@ -168,10 +173,10 @@ void Ent_DamageInfo(float isNew)
                                continue;
                        if(thisdmg < 0)
                                thisdmg = 0;
-                       if(dmg)
+                       if(thedamage)
                        {
-                               thisdmg = dmg + (edge - dmg) * thisdmg;
-                               thisforce = forcemul * vlen(force) * (thisdmg / dmg) * normalize(self.origin - w_org);
+                               thisdmg = thedamage + (edge - thedamage) * thisdmg;
+                               thisforce = forcemul * vlen(force) * (thisdmg / thedamage) * normalize(self.origin - w_org);
                        }
                        else
                        {
@@ -184,7 +189,7 @@ void Ent_DamageInfo(float isNew)
                        if(vlen(nearest - w_org) > bound(MIN_DAMAGEEXTRARADIUS, self.damageextraradius, MAX_DAMAGEEXTRARADIUS))
                                continue;
 
-                       thisdmg = dmg;
+                       thisdmg = thedamage;
                        thisforce = forcemul * force;
                }
 
index 7c5c74130e41d8e7cf3dd27ade14b5748eef38bc..0de69a02d850a478906840ff353ed81902061059 100644 (file)
@@ -2,4 +2,7 @@
 #define DAMAGE_H
 
 .float total_damages; // number of effects which currently are attached to a player
+
+void Ent_DamageInfo(float isNew);
+
 #endif
index 82c43e2e27a0be796c16d9e008312715d3be540b..6325a8ab3c6651481938e9999f23ecc5f63aae5c 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef DEFS_H
-#define DEFS_H
+#ifndef CLIENT_DEFS_H
+#define CLIENT_DEFS_H
 
 // Additional OPTIONAL Fields and Globals
 //float                intermission;
index 95623505b83e297d2a7e63e12a4f78e378838d5b..c0c378fd1a42c4cb5fb697902e8bdca4c743539c 100644 (file)
@@ -1,9 +1,5 @@
-#if defined(CSQC)
-    #include "../dpdefs/csprogsdefs.qh"
-    #include "autocvars.qh"
-#elif defined(MENUQC)
-#elif defined(SVQC)
-#endif
+#include "effects.qh"
+#include "_all.qh"
 
 /*
 .vector fx_start;
@@ -12,9 +8,6 @@
 .string fx_texture;
 .float  fx_lifetime;
 
-void SUB_Remove()
-{ remove(self); }
-
 void b_draw()
 {
     //Draw_CylindricLine(self.fx_start, self.fx_end, self.fx_with, self.fx_texture, 0, time * 3, '1 1 1', 0.7, DRAWFLAG_ADDITIVE, view_origin);
diff --git a/qcsrc/client/effects.qh b/qcsrc/client/effects.qh
new file mode 100644 (file)
index 0000000..0bebdb9
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef EFFECTS_H
+#define EFFECTS_H
+
+void Net_ReadArc();
+
+#endif
index eb7d4787777c0435b67721dd874aff64a87592e7..298e9d5e672d61566d314cfa286d128cd8f63ce2 100644 (file)
@@ -1,4 +1,17 @@
 #include "gibs.qh"
+#include "_all.qh"
+
+#include "prandom.qh"
+#include "rubble.qh"
+
+#include "../common/constants.qh"
+#include "../common/movetypes/movetypes.qh"
+#include "../common/util.qh"
+
+.float scale;
+.float alpha;
+.float cnt;
+.float gravity;
 
 void Gib_Delete()
 {
index 8436ff6225a0ccc0e546bf5007fccec05720c394..2a9be2e0e26602faacaae72f8154aab64b61e487 100644 (file)
@@ -1,12 +1,22 @@
+#include "hook.qh"
+#include "_all.qh"
+
 #include "hud.qh"
 #include "noise.qh"
+
+#include "../common/teams.qh"
+
+#include "../csqcmodellib/interpolate.qh"
+
 #include "../warpzonelib/common.qh"
+#include "../warpzonelib/mathlib.qh"
 
-.float HookType; // ENT_CLIENT_*
-.vector origin;
-.vector velocity;
-.float HookSilent;
-.float HookRange;
+entityclass(Hook);
+class(Hook) .float HookType; // ENT_CLIENT_*
+class(Hook) .vector origin;
+class(Hook) .vector velocity;
+class(Hook) .float HookSilent;
+class(Hook) .float HookRange;
 
 void Draw_CylindricLine(vector from, vector to, float thickness, string texture, float aspect, float shift, vector rgb, float theAlpha, float drawflag, vector vieworg)
 {
@@ -49,7 +59,7 @@ void Draw_GrapplingHook_trace_callback(vector start, vector hit, vector end)
        Draw_GrapplingHook_trace_callback_rnd += 0.25 * vlen(hit - start) / 8;
 }
 
-.float teleport_time;
+class(Hook) .float teleport_time;
 void Draw_GrapplingHook()
 {
        vector a, b, atrans;
diff --git a/qcsrc/client/hook.qh b/qcsrc/client/hook.qh
new file mode 100644 (file)
index 0000000..8401dce
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef HOOK_H
+#define 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);
+void Hook_Precache();
+
+void Ent_ReadHook(float bIsNew, float type);
+
+#endif
index dfe52049b16ed8c6ed79c7140dd9ab54de9f9227..f30edcbdcbb8ecf877be46390c89e2320b8f7063 100644 (file)
@@ -1,10 +1,23 @@
+#include "hud.qh"
+#include "_all.qh"
+
+#include "hud_config.qh"
 #include "scoreboard.qh"
+#include "sortlist.qh"
 #include "teamradar.qh"
+#include "t_items.qh"
+
 #include "../common/buffs.qh"
+#include "../common/constants.qh"
 #include "../common/counting.qh"
+#include "../common/deathtypes.qh"
 #include "../common/mapinfo.qh"
 #include "../common/nades.qh"
-#include "../server/t_items.qh"
+#include "../common/stats.qh"
+
+#include "../csqcmodellib/cl_player.qh"
+
+#include "../warpzonelib/mathlib.qh"
 
 /*
 ==================
@@ -140,13 +153,13 @@ vector HUD_Get_Num_Color (float x, float maxvalue)
        return color;
 }
 
-float HUD_GetRowCount(float item_count, vector size, float item_aspect)
+float HUD_GetRowCount(int item_count, vector size, float item_aspect)
 {
        float aspect = size_y / size_x;
        return bound(1, floor((sqrt(4 * item_aspect * aspect * item_count + aspect * aspect) + aspect + 0.5) / 2), item_count);
 }
 
-vector HUD_GetTableSize(float item_count, vector psize, float item_aspect)
+vector HUD_GetTableSize(int item_count, vector psize, float item_aspect)
 {
        float columns, rows;
        float ratio, best_ratio = 0;
@@ -196,20 +209,20 @@ float stringwidth_nocolors(string s, vector theSize)
        return stringwidth(s, false, theSize);
 }
 
-void drawstringright(vector position, string text, vector theScale, vector rgb, float theAlpha, float flag)
+void drawstringright(vector position, string text, vector theScale, vector rgb, float theAlpha, int flag)
 {
        position.x -= 2 / 3 * strlen(text) * theScale.x;
        drawstring(position, text, theScale, rgb, theAlpha, flag);
 }
 
-void drawstringcenter(vector position, string text, vector theScale, vector rgb, float theAlpha, float flag)
+void drawstringcenter(vector position, string text, vector theScale, vector rgb, float theAlpha, int flag)
 {
        position.x = 0.5 * (vid_conwidth - 0.6025 * strlen(text) * theScale.x);
        drawstring(position, text, theScale, rgb, theAlpha, flag);
 }
 
 // return the string of the onscreen race timer
-string MakeRaceString(float cp, float mytime, float histime, float lapdelta, string hisname)
+string MakeRaceString(int cp, float mytime, float theirtime, float lapdelta, string theirname)
 {
        string col;
        string timestr;
@@ -217,7 +230,7 @@ string MakeRaceString(float cp, float mytime, float histime, float lapdelta, str
        string lapstr;
        lapstr = "";
 
-       if(histime == 0) // goal hit
+       if(theirtime == 0) // goal hit
        {
                if(mytime > 0)
                {
@@ -246,12 +259,12 @@ string MakeRaceString(float cp, float mytime, float histime, float lapdelta, str
                        col = "^1";
                }
        }
-       else if(histime > 0) // anticipation
+       else if(theirtime > 0) // anticipation
        {
-               if(mytime >= histime)
-                       timestr = strcat("+", ftos_decimals(mytime - histime, TIME_DECIMALS));
+               if(mytime >= theirtime)
+                       timestr = strcat("+", ftos_decimals(mytime - theirtime, TIME_DECIMALS));
                else
-                       timestr = TIME_ENCODED_TOSTRING(TIME_ENCODE(histime));
+                       timestr = TIME_ENCODED_TOSTRING(TIME_ENCODE(theirtime));
                col = "^3";
        }
        else
@@ -269,24 +282,25 @@ string MakeRaceString(float cp, float mytime, float histime, float lapdelta, str
        else
                cpname = _("Finish line");
 
-       if(histime < 0)
+       if(theirtime < 0)
                return strcat(col, cpname);
-       else if(hisname == "")
+       else if(theirname == "")
                return strcat(col, sprintf("%s (%s)", cpname, timestr));
        else
-               return strcat(col, sprintf("%s (%s %s)", cpname, timestr, strcat(hisname, col, lapstr)));
+               return strcat(col, sprintf("%s (%s %s)", cpname, timestr, strcat(theirname, col, lapstr)));
 }
 
 // Check if the given name already exist in race rankings? In that case, where? (otherwise return 0)
-float race_CheckName(string net_name) {
-       float i;
+int race_CheckName(string net_name)
+{
+       int i;
        for (i=RANKINGS_CNT-1;i>=0;--i)
                if(grecordholder[i] == net_name)
                        return i+1;
        return 0;
 }
 
-float GetPlayerColorForce(int i)
+int GetPlayerColorForce(int i)
 {
        if(!teamplay)
                return 0;
@@ -294,7 +308,7 @@ float GetPlayerColorForce(int i)
                return stof(getplayerkeyvalue(i, "colors")) & 15;
 }
 
-float GetPlayerColor(int i)
+int GetPlayerColor(int i)
 {
        if(!playerslots[i].gotscores) // unconnected
                return NUM_SPECTATOR;
@@ -323,7 +337,7 @@ HUD panels
 } 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, float vertical, float baralign, vector theColor, float theAlpha, float drawflag)
+void HUD_Panel_DrawProgressBar(vector theOrigin, vector theSize, string pic, float length_ratio, bool vertical, float baralign, vector theColor, float theAlpha, int drawflag)
 {
        if(!length_ratio || !theAlpha)
                return;
@@ -426,7 +440,7 @@ void HUD_Panel_DrawProgressBar(vector theOrigin, vector theSize, string pic, flo
        }
 }
 
-void HUD_Panel_DrawHighlight(vector pos, vector mySize, vector color, float theAlpha, float drawflag)
+void HUD_Panel_DrawHighlight(vector pos, vector mySize, vector color, float theAlpha, int drawflag)
 {
        if(!theAlpha)
                return;
@@ -454,9 +468,9 @@ void weaponorder_swap(int i, int j, entity pass)
 }
 
 string weaponorder_cmp_str;
-float weaponorder_cmp(float i, float j, entity pass)
+int weaponorder_cmp(int i, int j, entity pass)
 {
-       float ai, aj;
+       int ai, aj;
        ai = strstrofs(weaponorder_cmp_str, sprintf(" %d ", weaponorder[i].weapon), 0);
        aj = strstrofs(weaponorder_cmp_str, sprintf(" %d ", weaponorder[j].weapon), 0);
        return aj - ai; // the string is in REVERSE order (higher prio at the right is what we want, but higher prio first is the string)
@@ -466,11 +480,12 @@ void HUD_Weapons(void)
 {
        // declarations
        WepSet weapons_stat = WepSet_GetFromStat();
-       float i, f, a;
+       int i;
+       float f, a;
        float screen_ar;
        vector center = '0 0 0';
-       float weapon_count, weapon_id;
-       float row, column, rows = 0, columns = 0;
+       int weapon_count, weapon_id;
+       int row, column, rows = 0, columns = 0;
        bool vertical_order = true;
        float aspect = autocvar_hud_panel_weapons_aspect;
 
@@ -506,8 +521,6 @@ void HUD_Weapons(void)
        // update generic hud functions
        HUD_Panel_UpdateCvars();
 
-       draw_beginBoldFont();
-
        // figure out weapon order (how the weapons are sorted) // TODO make this configurable
        if(weaponorder_bypriority != autocvar_cl_weaponpriority || !weaponorder[0])
        {
@@ -577,10 +590,7 @@ void HUD_Weapons(void)
 
                // might as well commit suicide now, no reason to live ;)
                if (weapon_count == 0)
-               {
-                       draw_endBoldFont();
                        return;
-               }
 
                vector old_panel_size = panel_size;
                vector padded_panel_size = panel_size - '2 2 0' * panel_bg_padding;
@@ -597,7 +607,7 @@ void HUD_Weapons(void)
                if(padded_panel_size.x / padded_panel_size.y < aspect)
                {
                        // maximum number of rows that allows to display items with the desired aspect ratio
-                       float max_rows = floor(padded_panel_size.y / (weapon_size.x / aspect));
+                       int max_rows = floor(padded_panel_size.y / (weapon_size.x / aspect));
                        columns = min(columns, ceil(weapon_count / max_rows));
                        rows = ceil(weapon_count / columns);
                        weapon_size.y = min(padded_panel_size.y / rows, weapon_size.x / aspect);
@@ -606,7 +616,7 @@ void HUD_Weapons(void)
                }
                else
                {
-                       float max_columns = floor(padded_panel_size.x / (weapon_size.y * aspect));
+                       int max_columns = floor(padded_panel_size.x / (weapon_size.y * aspect));
                        rows = min(rows, ceil(weapon_count / max_columns));
                        columns = ceil(weapon_count / rows);
                        weapon_size.x = min(padded_panel_size.x / columns, aspect * weapon_size.y);
@@ -734,10 +744,7 @@ void HUD_Weapons(void)
        HUD_Panel_DrawBg(1);
 
        if(center.x == -1)
-       {
-               draw_endBoldFont();
                return;
-       }
 
        if(panel_bg_padding)
        {
@@ -940,8 +947,6 @@ void HUD_Weapons(void)
                        }
                }
        }
-
-       draw_endBoldFont();
 }
 
 // Ammo (#1)
@@ -957,7 +962,7 @@ void DrawNadeScoreBar(vector myPos, vector mySize, vector color)
 
 }
 
-void DrawAmmoNades(vector myPos, vector mySize, float draw_expanding, float expand_time)
+void DrawAmmoNades(vector myPos, vector mySize, bool draw_expanding, float expand_time)
 {
        float theAlpha = 1, a, b;
        vector nade_color, picpos, numpos;
@@ -993,14 +998,14 @@ void DrawAmmoNades(vector myPos, vector mySize, float draw_expanding, float expa
        }
 }
 
-void DrawAmmoItem(vector myPos, vector mySize, .float ammoType, float isCurrent, float isInfinite)
+void DrawAmmoItem(vector myPos, vector mySize, .int ammoType, bool isCurrent, bool isInfinite)
 {
        if(ammoType == ammo_none)
                return;
 
        // Initialize variables
 
-       float ammo;
+       int ammo;
        if(autocvar__hud_configure)
        {
                isCurrent = (ammoType == ammo_rockets); // Rockets always current
@@ -1028,7 +1033,7 @@ void DrawAmmoItem(vector myPos, vector mySize, .float ammoType, float isCurrent,
                textPos = myPos + eX * mySize.y;
        }
 
-       float isShadowed = (ammo <= 0 && !isCurrent && !isInfinite);
+       bool isShadowed = (ammo <= 0 && !isCurrent && !isInfinite);
 
        vector iconColor = isShadowed ? '0 0 0' : '1 1 1';
        vector textColor;
@@ -1065,8 +1070,8 @@ void DrawAmmoItem(vector myPos, vector mySize, .float ammoType, float isCurrent,
        drawpic_aspect_skin(iconPos, GetAmmoPicture(ammoType), '1 1 0' * mySize.y, iconColor, alpha, DRAWFLAG_NORMAL);
 }
 
-float nade_prevstatus;
-float nade_prevframe;
+int nade_prevstatus;
+int nade_prevframe;
 float nade_statuschange_time;
 void HUD_Ammo(void)
 {
@@ -1092,10 +1097,11 @@ void HUD_Ammo(void)
                mySize -= '2 2 0' * panel_bg_padding;
        }
 
-       float rows = 0, columns, row, column;
+       int rows = 0, columns, row, column;
        float nade_cnt = getstatf(STAT_NADE_BONUS), nade_score = getstatf(STAT_NADE_BONUS_SCORE);
-       float draw_nades = (nade_cnt > 0 || nade_score > 0), nade_statuschange_elapsedtime;
-       float total_ammo_count;
+       bool draw_nades = (nade_cnt > 0 || nade_score > 0);
+       float nade_statuschange_elapsedtime;
+       int total_ammo_count;
 
        vector ammo_size;
        if (autocvar_hud_panel_ammo_onlycurrent)
@@ -1137,8 +1143,8 @@ void HUD_Ammo(void)
                ammo_size.y = newSize;
        }
 
-       float i;
-       float infinite_ammo = (getstati(STAT_ITEMS, 0, 24) & IT_UNLIMITED_WEAPON_AMMO);
+       int i;
+       bool infinite_ammo = (getstati(STAT_ITEMS, 0, 24) & IT_UNLIMITED_WEAPON_AMMO);
        row = column = 0;
        if(autocvar_hud_panel_ammo_onlycurrent)
        {
@@ -1166,7 +1172,7 @@ void HUD_Ammo(void)
        }
        else
        {
-               .float ammotype;
+               .int ammotype;
                row = column = 0;
                for(i = 0; i < AMMO_COUNT; ++i)
                {
@@ -1200,7 +1206,7 @@ void HUD_Ammo(void)
        draw_endBoldFont();
 }
 
-void DrawNumIcon_expanding(vector myPos, vector mySize, float x, string icon, float vertical, float icon_right_align, vector color, float theAlpha, float fadelerp)
+void DrawNumIcon_expanding(vector myPos, vector mySize, float x, string icon, bool vertical, bool icon_right_align, vector color, float theAlpha, float fadelerp)
 {
        vector newPos = '0 0 0', newSize = '0 0 0';
        vector picpos, numpos;
@@ -1279,7 +1285,7 @@ void DrawNumIcon_expanding(vector myPos, vector mySize, float x, string icon, fl
        drawpic_aspect_skin_expanding(picpos, icon, '1 1 0' * newSize.y, '1 1 1', panel_fg_alpha * theAlpha, DRAWFLAG_NORMAL, fadelerp);
 }
 
-void DrawNumIcon(vector myPos, vector mySize, float x, string icon, float vertical, float icon_right_align, vector color, float theAlpha)
+void DrawNumIcon(vector myPos, vector mySize, float x, string icon, bool vertical, bool icon_right_align, vector color, float theAlpha)
 {
        DrawNumIcon_expanding(myPos, mySize, x, icon, vertical, icon_right_align, color, theAlpha, 0);
 }
@@ -1330,10 +1336,10 @@ void HUD_Powerups(void)
        }
 
        float panel_ar = mySize.x/mySize.y;
-       float is_vertical = (panel_ar < 1);
+       bool is_vertical = (panel_ar < 1);
        vector shield_offset = '0 0 0', strength_offset = '0 0 0', superweapons_offset = '0 0 0';
 
-       float superweapons_is = -1;
+       int superweapons_is = -1;
 
        if(superweapons_time)
        {
@@ -1395,8 +1401,8 @@ void HUD_Powerups(void)
                }
        }
 
-       float shield_baralign, strength_baralign, superweapons_baralign;
-       float shield_iconalign, strength_iconalign, superweapons_iconalign;
+       bool shield_baralign, strength_baralign, superweapons_baralign;
+       bool shield_iconalign, strength_iconalign, superweapons_iconalign;
 
        if (autocvar_hud_panel_powerups_flip)
        {
@@ -1482,21 +1488,10 @@ void HUD_Powerups(void)
 // Health/armor (#3)
 //
 
-// prev_* vars contain the health/armor at the previous FRAME
-// set to -1 when player is dead or was not playing
-float prev_health, prev_armor;
-float health_damagetime, armor_damagetime;
-float health_beforedamage, armor_beforedamage;
-// old_p_* vars keep track of previous values when smoothing value changes of the progressbar
-float old_p_health, old_p_armor;
-float old_p_healthtime, old_p_armortime;
-// prev_p_* vars contain the health/armor progressbar value at the previous FRAME
-// set to -1 to forcedly stop effects when we switch spectated player (e.g. from playerX: 70h to playerY: 50h)
-float prev_p_health, prev_p_armor;
 
 void HUD_HealthArmor(void)
 {
-       float armor, health, fuel;
+       int armor, health, fuel;
        if(!autocvar__hud_configure)
        {
                if(!autocvar_hud_panel_healtharmor) return;
@@ -1546,6 +1541,9 @@ void HUD_HealthArmor(void)
        }
 
        HUD_Panel_UpdateCvars();
+
+       draw_beginBoldFont();
+
        vector pos, mySize;
        pos = panel_pos;
        mySize = panel_size;
@@ -1557,11 +1555,11 @@ void HUD_HealthArmor(void)
                mySize -= '2 2 0' * panel_bg_padding;
        }
 
-       float baralign = autocvar_hud_panel_healtharmor_baralign;
-       float iconalign = autocvar_hud_panel_healtharmor_iconalign;
+       int baralign = autocvar_hud_panel_healtharmor_baralign;
+       int iconalign = autocvar_hud_panel_healtharmor_iconalign;
 
-    float maxhealth = autocvar_hud_panel_healtharmor_maxhealth;
-    float maxarmor = autocvar_hud_panel_healtharmor_maxarmor;
+    int maxhealth = autocvar_hud_panel_healtharmor_maxhealth;
+    int maxarmor = autocvar_hud_panel_healtharmor_maxarmor;
        if(autocvar_hud_panel_healtharmor == 2) // combined health and armor display
        {
                vector v;
@@ -1599,7 +1597,7 @@ void HUD_HealthArmor(void)
        else
        {
                float panel_ar = mySize.x/mySize.y;
-               float is_vertical = (panel_ar < 1);
+               bool is_vertical = (panel_ar < 1);
                vector health_offset = '0 0 0', armor_offset = '0 0 0';
                if (panel_ar >= 4 || (panel_ar >= 1/4 && panel_ar < 1))
                {
@@ -1618,8 +1616,8 @@ void HUD_HealthArmor(void)
                                armor_offset.y = mySize.y;
                }
 
-               float health_baralign, armor_baralign, fuel_baralign;
-               float health_iconalign, armor_iconalign;
+               bool health_baralign, armor_baralign, fuel_baralign;
+               bool health_iconalign, armor_iconalign;
                if (autocvar_hud_panel_healtharmor_flip)
                {
                        armor_baralign = (autocvar_hud_panel_healtharmor_baralign == 2 || autocvar_hud_panel_healtharmor_baralign == 1);
@@ -1751,6 +1749,8 @@ void HUD_HealthArmor(void)
                        HUD_Panel_DrawProgressBar(pos, mySize, "progressbar", fuel/100, is_vertical, fuel_baralign, autocvar_hud_progressbar_fuel_color, panel_fg_alpha * 0.8, DRAWFLAG_NORMAL);
                }
        }
+
+       draw_endBoldFont();
 }
 
 // Notification area (#4)
@@ -1823,7 +1823,7 @@ void HUD_Notify(void)
        float fade_time = max(0, autocvar_hud_panel_notify_fadetime);
        float icon_aspect = max(1, autocvar_hud_panel_notify_icon_aspect);
 
-       float entry_count = bound(1, floor(NOTIFY_MAX_ENTRIES * size.y / size.x), NOTIFY_MAX_ENTRIES);
+       int entry_count = bound(1, floor(NOTIFY_MAX_ENTRIES * size.y / size.x), NOTIFY_MAX_ENTRIES);
        float entry_height = size.y / entry_count;
 
        float panel_width_half = size.x * 0.5;
@@ -1838,7 +1838,8 @@ void HUD_Notify(void)
 
        vector attacker_pos, victim_pos, icon_pos;
        string attacker, victim, icon;
-       float i, j, count, step, limit, alpha;
+       int i, j, count, step, limit;
+       float alpha;
 
        if (autocvar_hud_panel_notify_flip)
        {
@@ -2089,7 +2090,7 @@ void HUD_Radar(void)
                mySize -= '2 2 0' * panel_bg_padding;
        }
 
-       float color2;
+       int color2;
        entity tm;
        float scale2d, normalsize, bigsize;
 
@@ -2172,9 +2173,9 @@ void HUD_Score_Rankings(vector pos, vector mySize, entity me)
 {
        float score;
        entity tm = world, pl;
-       float SCOREPANEL_MAX_ENTRIES = 6;
+       int SCOREPANEL_MAX_ENTRIES = 6;
        float SCOREPANEL_ASPECTRATIO = 2;
-       float entries = bound(1, floor(SCOREPANEL_MAX_ENTRIES * mySize.y/mySize.x * SCOREPANEL_ASPECTRATIO), SCOREPANEL_MAX_ENTRIES);
+       int entries = bound(1, floor(SCOREPANEL_MAX_ENTRIES * mySize.y/mySize.x * SCOREPANEL_ASPECTRATIO), SCOREPANEL_MAX_ENTRIES);
        vector fontsize = '1 1 0' * (mySize.y/entries);
 
        vector rgb, score_color;
@@ -2184,7 +2185,8 @@ void HUD_Score_Rankings(vector pos, vector mySize, entity me)
        float name_size = mySize.x*0.75;
        float spacing_size = mySize.x*0.04;
        const float highlight_alpha = 0.2;
-       float i = 0, me_printed = 0, first_pl = 0;
+       int i = 0, first_pl = 0;
+       bool me_printed = false;
        string s;
        if (autocvar__hud_configure)
        {
@@ -2275,7 +2277,7 @@ void HUD_Score_Rankings(vector pos, vector mySize, entity me)
                {
                        if (i == first_pl)
                                rgb = '0 1 0'; //first: green
-                       me_printed = 1;
+                       me_printed = true;
                        drawfill(pos, eX * mySize.x + eY * fontsize.y, rgb, highlight_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
                }
                if (team_count)
@@ -2483,8 +2485,6 @@ void HUD_RaceTimer (void)
 
        HUD_Panel_UpdateCvars();
 
-       draw_beginBoldFont();
-
        vector pos, mySize;
        pos = panel_pos;
        mySize = panel_size;
@@ -2520,7 +2520,9 @@ void HUD_RaceTimer (void)
        if(autocvar__hud_configure)
        {
                s = "0:13:37";
+               draw_beginBoldFont();
                drawstring(pos + eX * 0.5 * mySize.x - '0.5 0 0' * stringwidth(s, false, '0.60 0.60 0' * mySize.y), s, '0.60 0.60 0' * mySize.y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+               draw_endBoldFont();
                s = _("^1Intermediate 1 (+15.42)");
                drawcolorcodedstring(pos + eX * 0.5 * mySize.x - '0.5 0 0' * stringwidth(s, true, '1 1 0' * 0.20 * mySize.y) + eY * 0.60 * mySize.y, s, '1 1 0' * 0.20 * mySize.y, panel_fg_alpha, DRAWFLAG_NORMAL);
                s = sprintf(_("^1PENALTY: %.1f (%s)"), 2, "missing a checkpoint");
@@ -2570,6 +2572,8 @@ void HUD_RaceTimer (void)
                        }
                }
 
+               draw_beginBoldFont();
+
                if(forcetime != "")
                {
                        a = bound(0, (time - race_checkpointtime) / 0.5, 1);
@@ -2583,6 +2587,8 @@ void HUD_RaceTimer (void)
                        s = TIME_ENCODED_TOSTRING(TIME_ENCODE(time + TIME_DECODE(race_penaltyaccumulator) - race_laptime));
                        drawstring(pos + eX * 0.5 * mySize.x - '0.5 0 0' * stringwidth(s, false, '0.6 0.6 0' * mySize.y), s, '0.6 0.6 0' * mySize.y, '1 1 1', panel_fg_alpha * a, DRAWFLAG_NORMAL);
                }
+
+               draw_endBoldFont();
        }
        else
        {
@@ -2613,21 +2619,10 @@ void HUD_RaceTimer (void)
                        }
                }
        }
-
-       draw_endBoldFont();
 }
 
 // Vote window (#9)
 //
-float vote_yescount;
-float vote_nocount;
-float vote_needed;
-float vote_highlighted; // currently selected vote
-
-float vote_active; // is there an active vote?
-float vote_prev; // previous state of vote_active to check for a change
-float vote_alpha;
-float vote_change; // "time" when vote_active changed
 
 void HUD_Vote(void)
 {
@@ -2769,11 +2764,11 @@ void HUD_Vote(void)
 // Mod icons panel (#10)
 //
 
-float mod_active; // is there any active mod icon?
+bool mod_active; // is there any active mod icon?
 
-void DrawCAItem(vector myPos, vector mySize, float aspect_ratio, int layout, float i)
+void DrawCAItem(vector myPos, vector mySize, float aspect_ratio, int layout, int i)
 {
-       float stat = -1;
+       int stat = -1;
        string pic = "";
        vector color = '0 0 0';
        switch(i)
@@ -2833,7 +2828,8 @@ void HUD_Mod_CA(vector myPos, vector mySize)
                layout = autocvar_hud_panel_modicons_ca_layout;
        else //if(gametype == MAPINFO_TYPE_FREEZETAG)
                layout = autocvar_hud_panel_modicons_freezetag_layout;
-       float rows, columns, aspect_ratio;
+       int rows, columns;
+       float aspect_ratio;
        aspect_ratio = (layout) ? 2 : 1;
        rows = HUD_GetRowCount(team_count, mySize, aspect_ratio);
        columns = ceil(team_count/rows);
@@ -2859,7 +2855,7 @@ void HUD_Mod_CA(vector myPos, vector mySize)
 
 // CTF HUD modicon section
 float redflag_prevframe, blueflag_prevframe; // status during previous frame
-float redflag_prevstatus, blueflag_prevstatus; // last remembered status
+int redflag_prevstatus, blueflag_prevstatus; // last remembered status
 float redflag_statuschange_time, blueflag_statuschange_time; // time when the status changed
 
 void HUD_Mod_CTF_Reset(void)
@@ -2873,9 +2869,9 @@ void HUD_Mod_CTF(vector pos, vector mySize)
        vector flag_size;
        float f; // every function should have that
 
-       float redflag, blueflag; // current status
+       int redflag, blueflag; // current status
        float redflag_statuschange_elapsedtime, blueflag_statuschange_elapsedtime; // time since the status changed
-       float stat_items;
+       int stat_items;
 
        stat_items = getstati(STAT_ITEMS, 0, 24);
        redflag = (stat_items/IT_RED_FLAG_TAKEN) & 3;
@@ -3017,9 +3013,9 @@ void HUD_Mod_KH(vector pos, vector mySize)
 
        // Read current state
 
-       float state = getstati(STAT_KH_KEYS);
-       float i, key_state;
-       float all_keys, team1_keys, team2_keys, team3_keys, team4_keys, dropped_keys, carrying_keys;
+       int state = getstati(STAT_KH_KEYS);
+       int i, key_state;
+       int all_keys, team1_keys, team2_keys, team3_keys, team4_keys, dropped_keys, carrying_keys;
        all_keys = team1_keys = team2_keys = team3_keys = team4_keys = dropped_keys = carrying_keys = 0;
 
        for(i = 0; i < 4; ++i)
@@ -3138,7 +3134,7 @@ void HUD_Mod_KH(vector pos, vector mySize)
 }
 
 // Keepaway HUD mod icon
-float kaball_prevstatus; // last remembered status
+int kaball_prevstatus; // last remembered status
 float kaball_statuschange_time; // time when the status changed
 
 // we don't need to reset for keepaway since it immediately
@@ -3153,8 +3149,8 @@ void HUD_Mod_Keepaway(vector pos, vector mySize)
        float BLINK_FREQ = 5;
        float kaball_alpha = BLINK_BASE + BLINK_FACTOR * cos(time * BLINK_FREQ);
 
-       float stat_items = getstati(STAT_ITEMS, 0, 24);
-       float kaball = (stat_items/IT_KEY1) & 1;
+       int stat_items = getstati(STAT_ITEMS, 0, 24);
+       int kaball = (stat_items/IT_KEY1) & 1;
 
        if(kaball != kaball_prevstatus)
        {
@@ -3186,7 +3182,8 @@ void HUD_Mod_Keepaway(vector pos, vector mySize)
 // Nexball HUD mod icon
 void HUD_Mod_NexBall(vector pos, vector mySize)
 {
-       float stat_items, nb_pb_starttime, dt, p;
+       float nb_pb_starttime, dt, p;
+       int stat_items;
 
        stat_items = getstati(STAT_ITEMS, 0, 24);
        nb_pb_starttime = getstatf(STAT_NB_METERSTART);
@@ -3219,7 +3216,7 @@ float srecordtime_prev; // last remembered srecordtime
 float srecordtime_change_time; // time when srecordtime last changed
 
 float race_status_time;
-float race_status_prev;
+int race_status_prev;
 string race_status_name_prev;
 void HUD_Mod_Race(vector pos, vector mySize)
 {
@@ -3359,7 +3356,7 @@ void HUD_Mod_Race(vector pos, vector mySize)
        }
 }
 
-void DrawDomItem(vector myPos, vector mySize, float aspect_ratio, int layout, float i)
+void DrawDomItem(vector myPos, vector mySize, float aspect_ratio, int layout, int i)
 {
        float stat = -1;
        string pic = "";
@@ -3428,7 +3425,8 @@ void HUD_Mod_Dom(vector myPos, vector mySize)
        mod_active = 1; // required in each mod function that always shows something
 
        int layout = autocvar_hud_panel_modicons_dom_layout;
-       float rows, columns, aspect_ratio;
+       int rows, columns;
+       float aspect_ratio;
        aspect_ratio = (layout) ? 3 : 1;
        rows = HUD_GetRowCount(team_count, mySize, aspect_ratio);
        columns = ceil(team_count/rows);
@@ -3468,7 +3466,7 @@ void HUD_ModIcons_SetFunc()
        }
 }
 
-float mod_prev; // previous state of mod_active to check for a change
+int mod_prev; // previous state of mod_active to check for a change
 float mod_alpha;
 float mod_change; // "time" when mod_active changed
 
@@ -3662,7 +3660,7 @@ void HUD_Chat(void)
 //
 float prevfps;
 float prevfps_time;
-float framecounter;
+int framecounter;
 
 float frametimeavg;
 float frametimeavg1; // 1 frame ago
@@ -3908,6 +3906,7 @@ void HUD_InfoMessages(void)
 //
 vector acc_prevspeed;
 float acc_prevtime, acc_avg, top_speed, top_speed_time;
+float physics_update_time, discrete_speed, discrete_acceleration;
 void HUD_Physics(void)
 {
        if(!autocvar__hud_configure)
@@ -3995,8 +3994,23 @@ void HUD_Physics(void)
                acc_prevspeed = vel;
                acc_prevtime = time;
 
-               f = bound(0, f * 10, 1);
-               acc_avg = acc_avg * (1 - f) + acceleration * f;
+               if(autocvar_hud_panel_physics_acceleration_movingaverage)
+               {
+                       f = bound(0, f * 10, 1);
+                       acc_avg = acc_avg * (1 - f) + acceleration * f;
+                       acceleration = acc_avg;
+               }
+       }
+
+       int acc_decimals = 2;
+       if(time > physics_update_time)
+       {
+               // workaround for ftos_decimals returning a negative 0
+               if(discrete_acceleration > -1 / pow(10, acc_decimals) && discrete_acceleration < 0)
+                       discrete_acceleration = 0;
+               discrete_acceleration = acceleration;
+               discrete_speed = speed;
+               physics_update_time += autocvar_hud_panel_physics_update_interval;
        }
 
        //compute layout
@@ -4018,7 +4032,7 @@ void HUD_Physics(void)
                else
                        acceleration_offset.y = panel_size.y;
        }
-       float speed_baralign, acceleration_baralign;
+       int speed_baralign, acceleration_baralign;
        if (autocvar_hud_panel_physics_baralign == 1)
                acceleration_baralign = speed_baralign = 1;
     else if(autocvar_hud_panel_physics_baralign == 4)
@@ -4050,7 +4064,7 @@ void HUD_Physics(void)
                //else
                        //tmp_offset_x = 0;
                tmp_offset.y = (panel_size.y - tmp_size.y) / 2;
-               drawstring_aspect(panel_pos + speed_offset + tmp_offset, ftos(speed), tmp_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+               drawstring_aspect(panel_pos + speed_offset + tmp_offset, ftos(discrete_speed), tmp_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
 
                //draw speed unit
                if (speed_baralign)
@@ -4140,7 +4154,7 @@ void HUD_Physics(void)
 
                f = acceleration/autocvar_hud_panel_physics_acceleration_max;
                if (autocvar_hud_panel_physics_acceleration_progressbar_nonlinear)
-                       f = sqrt(f);
+                       f = (f >= 0 ? sqrt(f) : -sqrt(-f));
 
                if (acceleration_progressbar_scale) // allow progressbar to go out of panel bounds
                {
@@ -4162,33 +4176,37 @@ void HUD_Physics(void)
 
                HUD_Panel_DrawProgressBar(panel_pos + acceleration_offset + tmp_offset, tmp_size, "accelbar", f, 0, acceleration_baralign, progressbar_color, autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
        }
-       tmp_size.x = panel_size.x;
-       tmp_size.y = panel_size.y * text_scale;
-       tmp_offset.x = 0;
-       tmp_offset.y = (panel_size.y - tmp_size.y) / 2;
-       if (autocvar_hud_panel_physics_text == 1 || autocvar_hud_panel_physics_text == 3)
-               drawstring_aspect(panel_pos + acceleration_offset + tmp_offset, strcat(ftos_decimals(acceleration, 2), "g"), tmp_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+
+       if(autocvar_hud_panel_physics_text == 1 || autocvar_hud_panel_physics_text == 3)
+       {
+               tmp_size.x = panel_size.x;
+               tmp_size.y = panel_size.y * text_scale;
+               tmp_offset.x = 0;
+               tmp_offset.y = (panel_size.y - tmp_size.y) / 2;
+
+               drawstring_aspect(panel_pos + acceleration_offset + tmp_offset, strcat(ftos_decimals(discrete_acceleration, acc_decimals), "g"), tmp_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+       }
 
        draw_endBoldFont();
 }
 
 // CenterPrint (#16)
 //
-const float CENTERPRINT_MAX_MSGS = 10;
-const float CENTERPRINT_MAX_ENTRIES = 50;
+const int CENTERPRINT_MAX_MSGS = 10;
+const int CENTERPRINT_MAX_ENTRIES = 50;
 const float CENTERPRINT_SPACING = 0.7;
-float cpm_index;
+int cpm_index;
 string centerprint_messages[CENTERPRINT_MAX_MSGS];
-float centerprint_msgID[CENTERPRINT_MAX_MSGS];
+int centerprint_msgID[CENTERPRINT_MAX_MSGS];
 float centerprint_time[CENTERPRINT_MAX_MSGS];
 float centerprint_expire_time[CENTERPRINT_MAX_MSGS];
-float centerprint_countdown_num[CENTERPRINT_MAX_MSGS];
-float centerprint_showing;
+int centerprint_countdown_num[CENTERPRINT_MAX_MSGS];
+bool centerprint_showing;
 
-void centerprint_generic(float new_id, string strMessage, float duration, float countdown_num)
+void centerprint_generic(int new_id, string strMessage, float duration, int countdown_num)
 {
        //printf("centerprint_generic(%d, '%s^7', %d, %d);\n", new_id, strMessage, duration, countdown_num);
-       float i, j;
+       int i, j;
 
        if(strMessage == "" && new_id == 0)
                return;
@@ -4268,7 +4286,7 @@ void centerprint_hud(string strMessage)
 
 void reset_centerprint_messages(void)
 {
-       float i;
+       int i;
        for (i=0; i<CENTERPRINT_MAX_MSGS; ++i)
        {
                centerprint_expire_time[i] = 0;
@@ -4295,15 +4313,23 @@ void HUD_CenterPrint (void)
                        reset_centerprint_messages();
                if (time > hud_configure_cp_generation_time)
                {
-                       float r;
-                       r = random();
-                       if (r > 0.75)
-                               centerprint_generic(floor(r*1000), strcat(sprintf("^3Countdown message at time %s", seconds_tostring(time)), ", seconds left: ^COUNT"), 1, 10);
-                       else if (r > 0.5)
-                               centerprint_generic(0, sprintf("^1Multiline message at time %s that\n^1lasts longer than normal", seconds_tostring(time)), 20, 0);
+                       if(HUD_PANEL(CENTERPRINT) == highlightedPanel)
+                       {
+                               float r;
+                               r = random();
+                               if (r > 0.8)
+                                       centerprint_generic(floor(r*1000), strcat(sprintf("^3Countdown message at time %s", seconds_tostring(time)), ", seconds left: ^COUNT"), 1, 10);
+                               else if (r > 0.55)
+                                       centerprint_generic(0, sprintf("^1Multiline message at time %s that\n^1lasts longer than normal", seconds_tostring(time)), 20, 0);
+                               else
+                                       centerprint_hud(sprintf("Message at time %s", seconds_tostring(time)));
+                               hud_configure_cp_generation_time = time + 1 + random()*4;
+                       }
                        else
-                               centerprint_hud(sprintf("Message at time %s", seconds_tostring(time)));
-                       hud_configure_cp_generation_time = time + 1 + random()*4;
+                       {
+                               centerprint_generic(0, sprintf("Centerprint message", seconds_tostring(time)), 10, 0);
+                               hud_configure_cp_generation_time = time + 10 - random()*3;
+                       }
                }
        }
 
@@ -4345,7 +4371,8 @@ void HUD_CenterPrint (void)
                panel_size -= '2 2 0' * panel_bg_padding;
        }
 
-       float entries, height;
+       int entries;
+       float height;
        vector fontsize;
        // entries = bound(1, floor(CENTERPRINT_MAX_ENTRIES * 4 * panel_size_y/panel_size_x), CENTERPRINT_MAX_ENTRIES);
        // height = panel_size_y/entries;
@@ -4354,11 +4381,11 @@ void HUD_CenterPrint (void)
        fontsize = '1 1 0' * height;
        entries = bound(1, floor(panel_size.y/height), CENTERPRINT_MAX_ENTRIES);
 
-       float i, j, k, n, g;
+       int i, j, k, n, g;
        float a, sz, align, current_msg_posY = 0, msg_size;
        vector pos;
        string ts;
-       float all_messages_expired = true;
+       bool all_messages_expired = true;
 
        pos = panel_pos;
        if (autocvar_hud_panel_centerprint_flip)
@@ -4495,7 +4522,7 @@ void HUD_CenterPrint (void)
 //
 void HUD_Buffs(void)
 {
-       float buffs = getstati(STAT_BUFFS, 0, 24);
+       int buffs = getstati(STAT_BUFFS, 0, 24);
        if(!autocvar__hud_configure)
        {
                if(!autocvar_hud_panel_buffs) return;
@@ -4508,7 +4535,7 @@ void HUD_Buffs(void)
                buffs = Buff_Type_first.items; // force first buff
        }
 
-       float b = 0; // counter to tell other functions that we have buffs
+       int b = 0; // counter to tell other functions that we have buffs
        entity e;
        string s = "";
        for(e = Buff_Type_first; e; e = e.enemy) if(buffs & e.items)
@@ -4536,7 +4563,7 @@ void HUD_Buffs(void)
        }
 
        //float panel_ar = mySize_x/mySize_y;
-       //float is_vertical = (panel_ar < 1);
+       //bool is_vertical = (panel_ar < 1);
        //float buff_iconalign = autocvar_hud_panel_buffs_iconalign;
        vector buff_offset = '0 0 0';
 
@@ -4615,7 +4642,7 @@ void HUD_Main (void)
        // draw the dock
        if(autocvar_hud_dock != "" && autocvar_hud_dock != "0")
        {
-               float f;
+               int f;
                vector color;
                float hud_dock_color_team = autocvar_hud_dock_color_team;
                if((teamplay) && hud_dock_color_team) {
@@ -4658,13 +4685,14 @@ void HUD_Main (void)
                for(i = 0; i < HUD_PANEL_NUM; ++i)
                        panel_order[i] = -1;
                string s = "";
-               float p_num, warning = false;
-               float argc = tokenize_console(autocvar__hud_panelorder);
+               int p_num;
+               bool warning = false;
+               int argc = tokenize_console(autocvar__hud_panelorder);
                if (argc > HUD_PANEL_NUM)
                        warning = true;
                //first detect wrong/missing panel numbers
                for(i = 0; i < HUD_PANEL_NUM; ++i) {
-                       p_num = stof(argv(i));
+                       p_num = stoi(argv(i));
                        if (p_num >= 0 && p_num < HUD_PANEL_NUM) { //correct panel number?
                                if (panel_order[p_num] == -1) //found for the first time?
                                        s = strcat(s, ftos(p_num), " ");
index 16a7645fd991819a55fd1b8de4349d318ee15f30..3b61cb4539643c06b1e66dcc89b9fccbee6546f0 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef HUD_H
 #define HUD_H
 
-#include "../common/weapons/weapons.qh"
+#include "../common/weapons/all.qh"
 
 const int HUD_PANEL_MAX = 24;
 entity hud_panel[HUD_PANEL_MAX];
@@ -12,6 +12,19 @@ int HUD_PANEL_LAST;
 int panel_order[HUD_PANEL_MAX];
 string hud_panelorder_prev;
 
+void HUD_Reset (void);
+void HUD_Main (void);
+
+int vote_yescount;
+int vote_nocount;
+int vote_needed;
+int vote_highlighted; // currently selected vote
+
+int vote_active; // is there an active vote?
+int vote_prev; // previous state of vote_active to check for a change
+float vote_alpha;
+float vote_change; // "time" when vote_active changed
+
 float hud_draw_maximized;
 float hud_panel_radar_maximized;
 float chat_panel_modified;
@@ -69,18 +82,19 @@ vector panel_size_backup;
 vector panel_size_copied;
 
 entity panel;
-.string panel_name;
-.int panel_id;
-.vector current_panel_pos;
-.vector current_panel_size;
-.string current_panel_bg;
-.float current_panel_bg_alpha;
-.float current_panel_bg_border;
-.vector current_panel_bg_color;
-.float current_panel_bg_color_team;
-.float current_panel_bg_padding;
-.float current_panel_fg_alpha;
-.float update_time;
+entityclass(HUDPanel);
+class(HUDPanel) .string panel_name;
+class(HUDPanel) .int panel_id;
+class(HUDPanel) .vector current_panel_pos;
+class(HUDPanel) .vector current_panel_size;
+class(HUDPanel) .string current_panel_bg;
+class(HUDPanel) .float current_panel_bg_alpha;
+class(HUDPanel) .float current_panel_bg_border;
+class(HUDPanel) .vector current_panel_bg_color;
+class(HUDPanel) .float current_panel_bg_color_team;
+class(HUDPanel) .float current_panel_bg_padding;
+class(HUDPanel) .float current_panel_fg_alpha;
+class(HUDPanel) .float update_time;
 float panel_enabled;
 vector panel_pos;
 vector panel_size;
@@ -97,12 +111,31 @@ string panel_bg_border_str;
 float panel_bg_padding;
 string panel_bg_padding_str;
 
-.void() panel_draw;
+class(HUDPanel) .void() panel_draw;
 
 float current_player;
 
 float GetPlayerColorForce(int i);
 
+float stringwidth_colors(string s, vector theSize);
+int GetPlayerColor(int i);
+string GetPlayerName(int i);
+float stringwidth_nocolors(string s, vector theSize);
+void HUD_Panel_DrawProgressBar(vector theOrigin, vector theSize, string pic, float length_ratio, bool vertical, float baralign, vector theColor, float theAlpha, int drawflag);
+
+
+// prev_* vars contain the health/armor at the previous FRAME
+// set to -1 when player is dead or was not playing
+int prev_health, prev_armor;
+float health_damagetime, armor_damagetime;
+int health_beforedamage, armor_beforedamage;
+// old_p_* vars keep track of previous values when smoothing value changes of the progressbar
+int old_p_health, old_p_armor;
+float old_p_healthtime, old_p_armortime;
+// prev_p_* vars contain the health/armor progressbar value at the previous FRAME
+// set to -1 to forcedly stop effects when we switch spectated player (e.g. from playerX: 70h to playerY: 50h)
+int prev_p_health, prev_p_armor;
+
 
 #define HUD_PANELS(HUD_PANEL)                                                                                                                                                                          \
        HUD_PANEL(WEAPONS      , HUD_Weapons      , weapons)                                                                                                                    \
@@ -259,27 +292,18 @@ HUD_PANELS(HUD_PANEL)
 } while(0)
 
 // return smoothly faded pos and size of given panel when a dialog is active
-#define HUD_Panel_UpdatePosSize_ForMenu() do {                                                                      \
-       vector menu_enable_pos;                                                                                         \
-       vector menu_enable_size = '0 0 0';                                                                              \
-       float menu_enable_maxsize_x = 0.3 * vid_conwidth;                                                               \
-       float menu_enable_maxsize_y = 0.18 * vid_conheight;                                                             \
-       if (panel_size.x > panel_size.y) {                                                                              \
-               if (panel_size.y > menu_enable_maxsize_y) {                                                                 \
-                       menu_enable_size.y = menu_enable_maxsize_y;                                                             \
-                       menu_enable_size.x = panel_size.x * (menu_enable_maxsize_y/panel_size.y);                               \
-                       panel_size = (1 - autocvar__menu_alpha) * panel_size + (autocvar__menu_alpha) * menu_enable_size;       \
-               }                                                                                                           \
-               menu_enable_pos = eX * 0.5 * vid_conwidth - eX * 0.5 * panel_size.x + eY * (vid_conheight - menu_enable_maxsize_y);\
-       } else {                                                                                                        \
-               if (panel_size.x > menu_enable_maxsize_x) {                                                                 \
-                       menu_enable_size.x = menu_enable_maxsize_x;                                                             \
-                       menu_enable_size.y = panel_size.y * (menu_enable_maxsize_x/panel_size.x);                               \
-                       panel_size = (1 - autocvar__menu_alpha) * panel_size + (autocvar__menu_alpha) * menu_enable_size;       \
-               }                                                                                                           \
-               menu_enable_pos = eY * 0.5 * vid_conheight - eY * 0.5 * panel_size.y + eX * (vid_conwidth - menu_enable_maxsize_x);\
-       }                                                                                                               \
-       panel_pos = (1 - autocvar__menu_alpha) * panel_pos + (autocvar__menu_alpha) * menu_enable_pos;                  \
+// don't center too wide panels, it doesn't work with different resolutions
+#define HUD_Panel_UpdatePosSize_ForMenu() do { \
+       vector menu_enable_size = panel_size; \
+       float max_panel_width = 0.52 * vid_conwidth; \
+       if(panel_size.x > max_panel_width) \
+       { \
+               menu_enable_size.x = max_panel_width; \
+               menu_enable_size.y = panel_size.y * (menu_enable_size.x / panel_size.x); \
+       } \
+       vector menu_enable_pos = eX * (panel_bg_border + 0.5 * max_panel_width) + eY * 0.5 * vid_conheight - 0.5 * menu_enable_size; \
+       panel_pos = (1 - autocvar__menu_alpha) * panel_pos + (autocvar__menu_alpha) * menu_enable_pos; \
+       panel_size = (1 - autocvar__menu_alpha) * panel_size + (autocvar__menu_alpha) * menu_enable_size; \
 } while(0)
 
 // Scale the pos and size vectors to absolute coordinates
index 0b200490d232180d4a3970dd63998a936641a6c6..696b1e7059e4efb8947517680e7f57e2df717ff8 100644 (file)
@@ -1,13 +1,11 @@
-#if defined(CSQC)
-       #include "../dpdefs/csprogsdefs.qh"
-       #include "defs.qh"
-       #include "../dpdefs/keycodes.qh"
-       #include "../common/constants.qh"
-       #include "autocvars.qh"
-       #include "hud.qh"
-#elif defined(MENUQC)
-#elif defined(SVQC)
-#endif
+#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)
@@ -436,8 +434,7 @@ void HUD_Panel_SetPosSize(vector mySize)
 {
        panel = highlightedPanel;
        HUD_Panel_UpdatePosSize();
-       vector resizeorigin;
-       resizeorigin = panel_click_resizeorigin;
+       vector resizeorigin = panel_click_resizeorigin;
        vector myPos;
 
        // minimum panel size cap
@@ -570,7 +567,6 @@ void HUD_Panel_Arrow_Action(float nPrimary)
 
        if (hudShiftState & S_ALT) // resize
        {
-               highlightedAction = 1;
                if(nPrimary == K_UPARROW)
                        resizeCorner = 1;
                else if(nPrimary == K_RIGHTARROW)
@@ -607,7 +603,6 @@ void HUD_Panel_Arrow_Action(float nPrimary)
        }
        else // move
        {
-               highlightedAction = 2;
                vector pos;
                pos = panel_pos;
                if(nPrimary == K_UPARROW)
@@ -749,15 +744,14 @@ float HUD_Panel_InputEvent(float bInputType, float nPrimary, float nSecondary)
                if (!menu_enabled)
                        cvar_set("_hud_configure", "0");
        }
-       else if(nPrimary == K_TAB && hudShiftState & S_CTRL) // select and highlight another panel
+       else if(nPrimary == K_TAB && hudShiftState & S_CTRL) // switch panel
        {
                if (bInputType == 1 || mouseClicked)
                        return true;
 
-               //FIXME: if a panel is highlighted, has the same pos_x and lays in the same level
-               //of other panels then next consecutive ctrl-tab will select the highlighted panel too
-               //(it should only after every other panel of the hud)
-               //It's a minor bug anyway, we can live with it
+               // FIXME minor bug: if a panel is highlighted, has the same pos_x and
+               // lays in the same level of another panel then the next consecutive
+               // CTRL TAB presses will reselect once more the highlighted panel
 
                entity starting_panel;
                entity old_tab_panel = tab_panel;
@@ -902,6 +896,12 @@ float HUD_Panel_InputEvent(float bInputType, float nPrimary, float nSecondary)
                        highlightedPanel_backup = world;
                }
        }
+       else if(nPrimary == 's' && hudShiftState & S_CTRL) // save config
+       {
+               if (bInputType == 1 || mouseClicked)
+                       return true;
+               localcmd("hud save myconfig\n");
+       }
        else if(nPrimary == K_UPARROW || nPrimary == K_DOWNARROW || nPrimary == K_LEFTARROW || nPrimary == K_RIGHTARROW)
        {
                if (bInputType == 1)
@@ -922,7 +922,7 @@ float HUD_Panel_InputEvent(float bInputType, float nPrimary, float nSecondary)
                if (highlightedPanel)
                        HUD_Panel_EnableMenu();
        }
-       else if(hit_con_bind)
+       else if(hit_con_bind || nPrimary == K_PAUSE)
                return false;
 
        return true;
@@ -1181,6 +1181,8 @@ void HUD_Panel_Mouse()
        }
        else
        {
+               if(prevMouseClicked)
+                       highlightedAction = 0;
                if(menu_enabled == 2)
                        mouse_over_panel = 0;
                else
diff --git a/qcsrc/client/hud_config.qh b/qcsrc/client/hud_config.qh
new file mode 100644 (file)
index 0000000..cc1d4d5
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef HUD_CONFIG_H
+#define HUD_CONFIG_H
+
+void HUD_Panel_ExportCfg(string cfgname);
+
+void HUD_Panel_Mouse();
+
+void HUD_Configure_Frame();
+
+void HUD_Configure_PostDraw();
+
+float HUD_Panel_InputEvent(float bInputType, float nPrimary, float nSecondary);
+
+#endif
index a74c6683a26824b0d9ac091e48012d6fb0258ab1..f5b6d54a9b32bd8df2fe39d95591981d124a28c7 100644 (file)
@@ -1,25 +1,25 @@
-#if defined(CSQC)
-       #include "../dpdefs/csprogsdefs.qh"
-       #include "../common/buffs.qh"
-       #include "../csqcmodellib/interpolate.qh"
-       #include "main.qh"
-       #include "../csqcmodellib/cl_model.qh"
-#elif defined(MENUQC)
-#elif defined(SVQC)
-#endif
+#include "laser.qh"
+#include "_all.qh"
 
+#include "hook.qh"
+
+#include "../common/buffs.qh"
+
+#include "../csqcmodellib/cl_model.qh"
+#include "../csqcmodellib/interpolate.qh"
 
 // a laser goes from origin in direction angles
 // it has color 'colormod'
 // and stops when something is in the way
-.int cnt; // end effect
-.vector colormod;
-.int state; // on-off
-.int count; // flags for the laser
-.vector velocity;
-.float alpha;
-.float scale; // scaling factor of the thickness
-.float modelscale; // scaling factor of the dlight
+entityclass(Laser);
+class(Laser) .int cnt; // end effect
+class(Laser) .vector colormod;
+class(Laser) .int state; // on-off
+class(Laser) .int count; // flags for the laser
+class(Laser) .vector velocity;
+class(Laser) .float alpha;
+class(Laser) .float scale; // scaling factor of the thickness
+class(Laser) .float modelscale; // scaling factor of the dlight
 
 void Draw_Laser()
 {
diff --git a/qcsrc/client/laser.qh b/qcsrc/client/laser.qh
new file mode 100644 (file)
index 0000000..86210ee
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef LASER_H
+#define LASER_H
+
+void Ent_Laser();
+
+#endif
index 36ec4f7b8c2525c2712566410ae80be9977ab50f..982056fcbb13f363cac97a3dfc4bc00f787ac122 100644 (file)
@@ -1,21 +1,51 @@
+#include "main.qh"
+#include "_all.qh"
+
+#include "casings.qh"
+#include "csqcmodel_hooks.qh"
+#include "damage.qh"
+#include "effects.qh"
+#include "gibs.qh"
+#include "hook.qh"
+#include "hud.qh"
+#include "hud_config.qh"
+#include "laser.qh"
 #include "mapvoting.qh"
 #include "modeleffects.qh"
 #include "particles.qh"
+#include "prandom.qh"
 #include "scoreboard.qh"
 #include "shownames.qh"
-#include "target_music.qh"
+#include "sortlist.qh"
 #include "tturrets.qh"
 #include "tuba.qh"
+#include "t_items.qh"
 #include "wall.qh"
 #include "waypointsprites.qh"
 
-#include "vehicles/vehicles.qh"
+#include "vehicles/bumblebee.qh"
+#include "vehicles/all.qh"
 
-#include "../server/vehicles/bumblebee.qh"
+#include "weapons/projectile.qh"
 
+#include "../common/buffs.qh"
+#include "../common/deathtypes.qh"
+#include "../common/mapinfo.qh"
+#include "../common/monsters/all.qh"
+#include "../common/nades.qh"
 #include "../common/net_notice.qh"
+#include "../common/notifications.qh"
+#include "../common/stats.qh"
+#include "../common/teams.qh"
 
-#include "../common/monsters/monsters.qh"
+#include "../common/items/all.qh"
+
+#include "../common/weapons/all.qh"
+
+#include "../csqcmodellib/cl_model.qh"
+#include "../csqcmodellib/interpolate.qh"
+
+#include "../common/triggers/include.qh"
 
 #include "../warpzonelib/client.qh"
 
@@ -109,6 +139,7 @@ void CSQC_Init(void)
        // needs to be done so early because of the constants they create
        CALL_ACCUMULATED_FUNCTION(RegisterWeapons);
        CALL_ACCUMULATED_FUNCTION(RegisterMonsters);
+       CALL_ACCUMULATED_FUNCTION(RegisterItems);
        CALL_ACCUMULATED_FUNCTION(RegisterGametypes);
        CALL_ACCUMULATED_FUNCTION(RegisterNotifications);
        CALL_ACCUMULATED_FUNCTION(RegisterDeathtypes);
@@ -348,6 +379,7 @@ float CSQC_InputEvent(float bInputType, float nPrimary, float nSecondary)
 
 // --------------------------------------------------------------------------
 // BEGIN OPTIONAL CSQC FUNCTIONS
+
 void Ent_RemoveEntCS()
 {
        entcs_receiver[self.sv_entnum] = world;
@@ -665,7 +697,7 @@ void Ent_ReadSpawnPoint(float is_new) // entity for spawnpoint
        if(is_new)
        {
                self.origin = spn_origin;
-               setsize(self, PL_MIN, PL_MAX);
+               setsize(self, PL_MIN_CONST, PL_MAX_CONST);
                droptofloor();
 
                /*if(autocvar_cl_spawn_point_model) // needs a model first
@@ -829,6 +861,7 @@ void CSQC_Ent_Update(float bIsNewEntity)
                case ENT_CLIENT_WARPZONE_TELEPORTED: WarpZone_Teleported_Read(bIsNewEntity); break;
                case ENT_CLIENT_TRIGGER_MUSIC: Ent_ReadTriggerMusic(); break;
                case ENT_CLIENT_HOOK: Ent_ReadHook(bIsNewEntity, ENT_CLIENT_HOOK); break;
+               case ENT_CLIENT_INVENTORY: Inventory_Read(self); break;
                case ENT_CLIENT_ARC_BEAM: Ent_ReadArcBeam(bIsNewEntity); break;
                case ENT_CLIENT_ACCURACY: Ent_ReadAccuracy(); break;
                case ENT_CLIENT_AUXILIARYXHAIR: Net_AuXair2(bIsNewEntity); break;
@@ -840,6 +873,17 @@ void CSQC_Ent_Update(float bIsNewEntity)
                case ENT_CLIENT_SPAWNEVENT: Ent_ReadSpawnEvent(bIsNewEntity); break;
                case ENT_CLIENT_NOTIFICATION: Read_Notification(bIsNewEntity); break;
                case ENT_CLIENT_HEALING_ORB: ent_healer(); break;
+               case ENT_CLIENT_LADDER: ent_func_ladder(); break;
+               case ENT_CLIENT_TRIGGER_PUSH: ent_trigger_push(); break;
+               case ENT_CLIENT_TARGET_PUSH: ent_target_push(); break;
+               case ENT_CLIENT_CONVEYOR: ent_conveyor(); break;
+               case ENT_CLIENT_DOOR: ent_door(); break;
+               case ENT_CLIENT_PLAT: ent_plat(); break;
+               case ENT_CLIENT_SWAMP: ent_swamp(); break;
+               case ENT_CLIENT_CORNER: ent_corner(); break;
+               case ENT_CLIENT_KEYLOCK: ent_keylock(); break;
+               case ENT_CLIENT_TRAIN: ent_train(); break;
+               case ENT_CLIENT_TRIGGER_IMPULSE: ent_trigger_impulse(); break;
 
                default:
                        //error(strcat(_("unknown entity type in CSQC_Ent_Update: %d\n"), self.enttype));
index b8823e6296d4de67aed98f1f2da417aa00ff0381..0bc85a441db9d6e83570061748ba23efa7a05c9e 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef MAIN_H
 #define MAIN_H
 
+#include "../common/constants.qh"
+
 // --------------------------------------------------------------------------
 // MENU Functionality
 
@@ -106,6 +108,8 @@ float current_viewzoom;
 float zoomin_effect;
 float warmup_stage;
 
+void Fog_Force();
+
 string getcommandkey(string text, string command);
 
 string vote_called_vote;
index 28b81fc51ffc9e85c917ff69f34e748bbc18c3a9..f00ee544c059f76cd3ec85bdf5375914df4caa9e 100644 (file)
@@ -1,6 +1,49 @@
 #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;
+
+float mv_active;
+string mv_maps[MAPVOTE_COUNT];
+string mv_pics[MAPVOTE_COUNT];
+string mv_pk3[MAPVOTE_COUNT]; // map pk3 name or gametype human readable name
+string mv_desc[MAPVOTE_COUNT];
+float mv_preview[MAPVOTE_COUNT];
+float mv_votes[MAPVOTE_COUNT];
+float mv_flags[MAPVOTE_COUNT];
+float mv_flags_start[MAPVOTE_COUNT];
+entity mv_pk3list;
+float mv_abstain;
+float mv_ownvote;
+float mv_detail;
+float mv_timeout;
+float mv_top2_time;
+float mv_top2_alpha;
+
+vector mv_mousepos;
+int mv_selection;
+int mv_columns;
+int mv_mouse_selection;
+int mv_selection_keyboard;
+
+float gametypevote;
+string mapvote_chosenmap;
+vector gtv_text_size;
+vector gtv_text_size_small;
+
+const int NUM_SSDIRS = 4;
+string ssdirs[NUM_SSDIRS];
+int n_ssdirs;
+
 string MapVote_FormatMapItem(int id, string map, float _count, float maxwidth, vector fontsize)
 {
        string pre, post;
@@ -9,7 +52,7 @@ string MapVote_FormatMapItem(int id, string map, float _count, float maxwidth, v
        {
                if(_count == 1)
                        post = _(" (1 vote)");
-               else if(_count >= 0 && mv_avail[id] == GTV_AVAILABLE)
+               else if(_count >= 0 && (mv_flags[id] & GTV_AVAILABLE))
                        post = sprintf(_(" (%d votes)"), _count);
                else
                        post = "";
@@ -21,14 +64,9 @@ string MapVote_FormatMapItem(int id, string map, float _count, float maxwidth, v
        return strcat(pre, map, post);
 }
 
-string GameTypeVote_DescriptionByID(int id)
-{
-       return MapInfo_Type_Description(MapInfo_Type_FromString(mv_maps[id]));
-}
-
 vector MapVote_RGB(int id)
 {
-       if(mv_avail[id] != GTV_AVAILABLE)
+       if(!(mv_flags[id] & GTV_AVAILABLE))
                return '1 1 1';
        if(id == mv_ownvote)
                return '0 1 0';
@@ -40,55 +78,60 @@ vector MapVote_RGB(int id)
 
 void GameTypeVote_DrawGameTypeItem(vector pos, float maxh, float tsize, string gtype, string pic, float _count, int id)
 {
+       // Find the correct alpha
        float alpha;
-       float desc_padding = gtv_text_size.x * 3;
+       if(!(mv_flags_start[id] & GTV_AVAILABLE))
+               alpha = 0.2; // The gametype isn't supported by the map
+       else if ( !(mv_flags[id] & GTV_AVAILABLE) && mv_top2_alpha)
+               alpha = mv_top2_alpha; // Fade away if not one of the top 2 choice
+       else
+               alpha = 1; // Normal, full alpha
+
+       // Bounding box details
        float rect_margin = hud_fontsize.y / 2;
        vector rect_pos = pos - '0.5 0.5 0' * rect_margin;
        vector rect_size = '1 1 0';
        rect_size.x = tsize + rect_margin;
        rect_size.y = maxh + rect_margin;
-       vector rgb = MapVote_RGB(id);
-       vector offset = pos;
-       float nlines = 0;
-
-       if(mv_avail_start[id] != GTV_AVAILABLE)
-               alpha = 0.2;
-       else if ( mv_avail[id] != GTV_AVAILABLE && mv_top2_alpha)
-               alpha = mv_top2_alpha;
-       else
-               alpha = 1;
 
-       if(id == mv_selection && mv_avail[id] == GTV_AVAILABLE)
+       // Highlight selected item
+       if(id == mv_selection && (mv_flags[id] & GTV_AVAILABLE))
        {
                drawfill(rect_pos, rect_size, '1 1 1', 0.1, DRAWFLAG_NORMAL);
        }
+
+       // Highlight current vote
+       vector rgb = MapVote_RGB(id);
        if(id == mv_ownvote)
        {
                drawfill(rect_pos, rect_size, rgb, 0.1*alpha, DRAWFLAG_NORMAL);
                drawborderlines(autocvar_scoreboard_border_thickness, rect_pos, rect_size, rgb, alpha, DRAWFLAG_NORMAL);
        }
 
-       entity title;
-       title = spawn();
-       title.message = MapVote_FormatMapItem(id, MapInfo_Type_ToText(MapInfo_Type_FromString(gtype)),
-                                                                                 _count, tsize, gtv_text_size);
-       title.origin = pos-offset;
-
-       pos.y += gtv_text_size_small.y;
-       pos.y += gtv_text_size.y/2;
+       vector offset = pos;
 
-       maxh -= gtv_text_size.y;
+       float title_gap = gtv_text_size.y * 1.4; // distance between the title and the description
+       pos.y += title_gap;
+       maxh -= title_gap;
 
-       entity picent = spawn();
-       picent.origin = pos-offset;
-       picent.maxs = '1 1 0 ' * min(maxh, desc_padding) * 0.8;
+       // Evaluate the image size
+       vector image_size = '1 1 0' * gtv_text_size.x * 3;
+       if ( maxh < image_size.y )
+               image_size = '1 1 0' * maxh;
+       image_size *= 0.8;
+       float desc_padding = gtv_text_size.x * 0.6;
+       pos.x += image_size.x + desc_padding;
+       tsize -= image_size.x + desc_padding;
 
-       pos.x += desc_padding;
-       tsize -= desc_padding;
+       // Split the description into lines
+       entity title;
+       title = spawn();
+       title.message = MapVote_FormatMapItem(id, mv_pk3[id], _count, tsize, gtv_text_size);
 
-       string thelabel = GameTypeVote_DescriptionByID(id), ts;
+       string thelabel = mv_desc[id], ts;
        entity last = title;
        entity next = world;
+       float nlines = 0;
        if( thelabel != "")
        {
                float i,n = tokenizebyseparator(thelabel, "\n");
@@ -112,14 +155,19 @@ void GameTypeVote_DrawGameTypeItem(vector pos, float maxh, float tsize, string g
                }
        }
 
-       maxh -= max(nlines*gtv_text_size_small.y,picent.maxs.y);
+       // Center the contents in the bounding box
+       maxh -= max(nlines*gtv_text_size_small.y,image_size.y);
        if ( maxh > 0 )
                offset.y += maxh/2;
-       drawstring(title.origin+offset, title.message, gtv_text_size, rgb, alpha, DRAWFLAG_NORMAL);
 
+       // Draw the title
+       drawstring(offset, title.message, gtv_text_size, rgb, alpha, DRAWFLAG_NORMAL);
+
+       // Draw the icon
        if(pic != "")
-               drawpic(picent.origin+offset, pic, picent.maxs, '1 1 1', alpha, DRAWFLAG_NORMAL);
+               drawpic('0 1 0'*title_gap+'0.5 0 0'*desc_padding+offset, pic, image_size, '1 1 1', alpha, DRAWFLAG_NORMAL);
 
+       // Draw the description
        for ( last = title.chain; last ; )
        {
                drawstring(last.origin+offset, last.message, gtv_text_size_small, '1 1 1', alpha, DRAWFLAG_NORMAL);
@@ -128,7 +176,7 @@ void GameTypeVote_DrawGameTypeItem(vector pos, float maxh, float tsize, string g
                remove(next);
        }
 
-       remove(picent);
+       // Cleanup
        remove(title);
 }
 
@@ -153,7 +201,7 @@ void MapVote_DrawMapItem(vector pos, float isize, float tsize, string map, strin
        text_size = stringwidth(label, false, hud_fontsize);
 
        float theAlpha;
-       if (mv_avail[id] != GTV_AVAILABLE && mv_top2_alpha)
+       if (!(mv_flags[id] & GTV_AVAILABLE) && mv_top2_alpha)
                theAlpha = mv_top2_alpha;
        else
                theAlpha = 1;
@@ -183,7 +231,7 @@ void MapVote_DrawMapItem(vector pos, float isize, float tsize, string map, strin
        else
                drawborderlines(autocvar_scoreboard_border_thickness, pos, img_size, '0 0 0', theAlpha, DRAWFLAG_NORMAL);
 
-       if(id == mv_selection && mv_avail[id] == GTV_AVAILABLE)
+       if(id == mv_selection && (mv_flags[id] & GTV_AVAILABLE))
                drawfill(pos, img_size, '1 1 1', 0.1, DRAWFLAG_NORMAL);
 }
 
@@ -458,20 +506,68 @@ void MapVote_ReadMask()
                        mask = ReadLong();
 
                for(i = 0, power = 1; i < mv_num_maps; ++i, power *= 2)
-                       mv_avail[i] = (mask & power) ? GTV_AVAILABLE : GTV_FORBIDDEN;
+               {
+                       if ( mask & power )
+                               mv_flags[i] |= GTV_AVAILABLE;
+                       else
+                               mv_flags[i] &= ~GTV_AVAILABLE;
+               }
        }
        else
        {
                for(i = 0; i < mv_num_maps; ++i )
-                       mv_avail[i] = ReadByte();
+                       mv_flags[i] = ReadByte();
        }
 }
 
-void MapVote_Init()
+void MapVote_ReadOption(int i)
+{
+       string map = strzone(ReadString());
+       string pk3 = strzone(ReadString());
+       int j = bound(0, ReadByte(), n_ssdirs - 1);
+
+       mv_maps[i] = map;
+       mv_pk3[i] = pk3;
+       mv_flags[i] = GTV_AVAILABLE;
+
+       string pic = strzone(strcat(ssdirs[j], "/", map));
+       mv_pics[i] = pic;
+       mv_preview[i] = false;
+       MapVote_CheckPic(pic, pk3, i);
+}
+
+void GameTypeVote_ReadOption(int i)
 {
-       int i, j;
-       string map, pk3, s;
+       string gt = strzone(ReadString());
+
+       mv_maps[i] = gt;
+       mv_flags[i] = ReadByte();
 
+       string mv_picpath = sprintf("gfx/menu/%s/gametype_%s", autocvar_menu_skin, gt);
+       if(precache_pic(mv_picpath) == "")
+               mv_picpath = strcat("gfx/menu/default/gametype_", gt);
+       string pic = strzone(mv_picpath);
+       mv_pics[i] = pic;
+       mv_preview[i] = PreviewExists(pic);
+
+       if ( mv_flags[i] & GTV_CUSTOM )
+       {
+               string name = ReadString();
+               if ( strlen(name) < 1 )
+                       name = gt;
+               mv_pk3[i] = strzone(name);
+               mv_desc[i] = strzone(ReadString());
+       }
+       else
+       {
+               int type = MapInfo_Type_FromString(gt);
+               mv_pk3[i] = strzone(MapInfo_Type_ToText(type));
+               mv_desc[i] = MapInfo_Type_Description(type);
+       }
+}
+
+void MapVote_Init()
+{
        precache_sound ("misc/invshot.wav");
 
        mv_active = 1;
@@ -480,6 +576,7 @@ void MapVote_Init()
        mv_selection = -1;
        mv_selection_keyboard = 0;
 
+       string s;
        for(n_ssdirs = 0; ; ++n_ssdirs)
        {
                s = ReadString();
@@ -530,8 +627,9 @@ void MapVote_Init()
        }
 
        MapVote_ReadMask();
+       int i;
        for(i = 0; i < mv_num_maps; ++i )
-               mv_avail_start[i] = mv_avail[i];
+               mv_flags_start[i] = mv_flags[i];
 
        // Assume mv_pk3list is world, there should only be 1 mapvote per round
        mv_pk3list = world; // I'm still paranoid!
@@ -540,32 +638,10 @@ void MapVote_Init()
        {
                mv_votes[i] = 0;
 
-               map = strzone(ReadString());
-               pk3 = strzone(ReadString());
-               j = bound(0, ReadByte(), n_ssdirs - 1);
-
-               mv_maps[i] = map;
-               mv_pk3[i] = pk3;
-               mv_avail[i] = ReadByte();
-
-               if(gametypevote)
-               {
-                       //map = strzone(strcat("gfx/menu/default/gametype_", map));
-                       //map = strzone(sprintf("gfx/menu/%s/gametype_%s", autocvar_menu_skin, map));
-                       string mv_picpath = sprintf("gfx/menu/%s/gametype_%s", autocvar_menu_skin, map);
-                       if(precache_pic(mv_picpath) == "")
-                               mv_picpath = strcat("gfx/menu/default/gametype_", map);
-                       map = strzone(mv_picpath);
-                       mv_pics[i] = map;
-                       mv_preview[i] = PreviewExists(map);
-               }
+               if ( gametypevote )
+                       GameTypeVote_ReadOption(i);
                else
-               {
-                       map = strzone(strcat(ssdirs[j], "/", map));
-                       mv_pics[i] = map;
-                       mv_preview[i] = false;
-                       MapVote_CheckPic(map, pk3, i);
-               }
+                       MapVote_ReadOption(i);
        }
 
        for(i = 0; i < n_ssdirs; ++i)
@@ -585,7 +661,7 @@ int MapVote_MoveLeft(int pos)
                imp = mv_num_maps - 1;
        else
                imp = pos < 1 ? mv_num_maps - 1 : pos - 1;
-       if ( mv_avail[imp] != GTV_AVAILABLE && imp != mv_ownvote )
+       if ( !(mv_flags[imp] & GTV_AVAILABLE) && imp != mv_ownvote )
                imp = MapVote_MoveLeft(imp);
        return imp;
 }
@@ -596,7 +672,7 @@ int MapVote_MoveRight(int pos)
                imp = 0;
        else
                imp = pos >= mv_num_maps - 1 ? 0 : pos + 1;
-       if ( mv_avail[imp] != GTV_AVAILABLE && imp != mv_ownvote )
+       if ( !(mv_flags[imp] & GTV_AVAILABLE) && imp != mv_ownvote )
                imp = MapVote_MoveRight(imp);
        return imp;
 }
@@ -615,7 +691,7 @@ int MapVote_MoveUp(int pos)
                                imp -= mv_columns;
                }
        }
-       if ( mv_avail[imp] != GTV_AVAILABLE && imp != mv_ownvote )
+       if ( !(mv_flags[imp] & GTV_AVAILABLE) && imp != mv_ownvote )
                imp = MapVote_MoveUp(imp);
        return imp;
 }
@@ -630,7 +706,7 @@ int MapVote_MoveDown(int pos)
                if ( imp >= mv_num_maps )
                        imp = imp % mv_columns;
        }
-       if ( mv_avail[imp] != GTV_AVAILABLE && imp != mv_ownvote )
+       if ( !(mv_flags[imp] & GTV_AVAILABLE) && imp != mv_ownvote )
                imp = MapVote_MoveDown(imp);
        return imp;
 }
@@ -723,7 +799,7 @@ void MapVote_UpdateVotes()
        int i;
        for(i = 0; i < mv_num_maps; ++i)
        {
-               if(mv_avail[i] == GTV_AVAILABLE)
+               if(mv_flags[i] & GTV_AVAILABLE)
                {
                        if(mv_detail)
                                mv_votes[i] = ReadByte();
index 8a4133e50ab798a42708012525c11be11da895f9..9c7086efc10d6a0060f691718689aecc42508278 100644 (file)
@@ -1,80 +1,13 @@
 #ifndef MAPVOTING_H
 #define MAPVOTING_H
 
-int mv_num_maps;
-
-float mv_active;
-string mv_maps[MAPVOTE_COUNT];
-string mv_pics[MAPVOTE_COUNT];
-string mv_pk3[MAPVOTE_COUNT];
-float mv_preview[MAPVOTE_COUNT];
-float mv_votes[MAPVOTE_COUNT];
-float mv_avail[MAPVOTE_COUNT];
-float mv_avail_start[MAPVOTE_COUNT];
-entity mv_pk3list;
-float mv_abstain;
-float mv_ownvote;
-float mv_detail;
-float mv_timeout;
-float mv_top2_time;
-float mv_top2_alpha;
-
-vector mv_mousepos;
-int mv_selection;
-int mv_columns;
-int mv_mouse_selection;
-int mv_selection_keyboard;
-
-float gametypevote;
-string mapvote_chosenmap;
-vector gtv_text_size;
-vector gtv_text_size_small;
-
-string MapVote_FormatMapItem(int id, string map, float count, float maxwidth, vector fontsize);
-
-string GameTypeVote_DescriptionByID(int id);
-
-vector MapVote_RGB(int id);
-
-void GameTypeVote_DrawGameTypeItem(vector pos, float maxh, float tsize, string gtype, string pic, float count, int id);
-
-void MapVote_DrawMapItem(vector pos, float isize, float tsize, string map, string pic, float count, int id);
-
-void MapVote_DrawAbstain(vector pos, float isize, float tsize, float count, int id);
-
-vector MapVote_GridVec(vector gridspec, int i, int m);
-
-float MapVote_Selection(vector topleft, vector cellsize, float rows, float columns);
-
+#include "../common/constants.qh"
 void MapVote_Draw();
 
 void Cmd_MapVote_MapDownload(float argc);
 
-void MapVote_CheckPK3(string pic, string pk3, int id);
-
-void MapVote_CheckPic(string pic, string pk3, int id);
-
-void MapVote_ReadMask();
-
-const int NUM_SSDIRS = 4;
-string ssdirs[NUM_SSDIRS];
-int n_ssdirs;
-void MapVote_Init();
-
-void MapVote_SendChoice(float index);
-
-int MapVote_MoveLeft(int pos);
-int MapVote_MoveRight(int pos);
-int MapVote_MoveUp(int pos);
-
-int MapVote_MoveDown(int pos);
-
 float MapVote_InputEvent(float bInputType, float nPrimary, float nSecondary);
 
-void MapVote_UpdateMask();
-
-void MapVote_UpdateVotes();
-
 void Ent_MapVote();
 
 void Net_MapVote_Picture();
index d74a24a320142d35e7da242c19f24586ca1e08fe..845a5641067df16b639e047090b8b03b98e452f9 100644 (file)
@@ -1,9 +1,19 @@
 #include "miscfunctions.qh"
+#include "_all.qh"
 
-#include "../common/urllib.qh"
+#include "hud.qh"
+#include "sortlist.qh"
 
 #include "../common/command/generic.qh"
 
+#include "../common/teams.qh"
+#include "../common/urllib.qh"
+#include "../common/util.qh"
+
+#include "../csqcmodellib/cl_model.qh"
+
+#include "../warpzonelib/mathlib.qh"
+
 void AuditLists()
 {
        entity e;
@@ -349,11 +359,11 @@ void PolyDrawModel(entity e)
                        break;
 }
 
-void DrawCircleClippedPic(vector centre, float radius, string pic, float f, vector rgb, float a, float drawflag)
+void DrawCircleClippedPic(vector centre, float radi, string pic, float f, vector rgb, float a, float drawflag)
 {
        float x, y, q, d;
        vector ringsize, v, t;
-       ringsize = radius * '1 1 0';
+       ringsize = radi * '1 1 0';
 
        x = cos(f * 2 * M_PI);
        y = sin(f * 2 * M_PI);
index 6c643962a65678ab19643cc48a2300536aab2ee0..0c2be7fc54afa6dbab8782acb592f2af11125ace 100644 (file)
@@ -5,6 +5,15 @@ entity players;
 entity teams;
 float team_count; // real teams
 
+const int INITPRIO_FIRST                               = 0;
+const int INITPRIO_GAMETYPE                    = 0;
+const int INITPRIO_GAMETYPE_FALLBACK   = 1;
+const int INITPRIO_FINDTARGET                  = 10;
+const int INITPRIO_DROPTOFLOOR                         = 20;
+const int INITPRIO_SETLOCATION                         = 90;
+const int INITPRIO_LINKDOORS                   = 91;
+const int INITPRIO_LAST                                = 99;
+
 void AuditLists();
 
 float RegisterPlayer(entity player);
@@ -132,7 +141,7 @@ void drawcolorcodedstring_aspect_expanding(vector pos, string text, vector sz, f
 float PolyDrawModelSurface(entity e, float i_s);
 void PolyDrawModel(entity e);
 
-void DrawCircleClippedPic(vector centre, float radius, string pic, float f, vector rgb, float a, float drawflag);
+void DrawCircleClippedPic(vector centre, float radi, string pic, float f, vector rgb, float a, float drawflag);
 
 const vector GETPLAYERORIGIN_ERROR = '1123581321 2357111317 3141592653'; // way out of bounds for anything on the map
 vector getplayerorigin(int pl);
index c376085e07aaea1aa3b105e90ec7f06942014d91..c44fbe4dca452dfe702d72e96135a04212284a78 100644 (file)
@@ -1,4 +1,9 @@
 #include "modeleffects.qh"
+#include "_all.qh"
+
+.float cnt;
+.float scale;
+.float alpha;
 
 void ModelEffect_Draw()
 {
index f40cfef5597b5ee87f4c34d106e0cd1a66c001cb..22998f09d689d14c2951969493479c3811ccbbb6 100644 (file)
@@ -1,10 +1,11 @@
 #ifndef MODELEFFECTS_H
 #define MODELEFFECTS_H
 
-.float frame1time;
-.float lifetime, fadetime;
-.float teleport_time;
-.float scale1, scale2;
+entityclass(ModelEffect);
+class(ModelEffect) .float frame1time;
+class(ModelEffect) .float lifetime, fadetime;
+class(ModelEffect) .float teleport_time;
+class(ModelEffect) .float scale1, scale2;
 
 void ModelEffect_Draw();
 
diff --git a/qcsrc/client/movelib.qc b/qcsrc/client/movelib.qc
new file mode 100644 (file)
index 0000000..074f146
--- /dev/null
@@ -0,0 +1 @@
+#include "../server/movelib.qc"
diff --git a/qcsrc/client/movelib.qh b/qcsrc/client/movelib.qh
new file mode 100644 (file)
index 0000000..a0634f6
--- /dev/null
@@ -0,0 +1 @@
+#include "../server/movelib.qh"
diff --git a/qcsrc/client/movetypes.qc b/qcsrc/client/movetypes.qc
deleted file mode 100644 (file)
index 2f62ae6..0000000
+++ /dev/null
@@ -1,559 +0,0 @@
-#if defined(CSQC)
-       #include "../dpdefs/csprogsdefs.qh"
-       #include "defs.qh"
-       #include "../common/stats.qh"
-       #include "../common/util.qh"
-       #include "movetypes.qh"
-       #include "../csqcmodellib/common.qh"
-       #include "../server/t_items.qh"
-#elif defined(MENUQC)
-#elif defined(SVQC)
-#endif
-
-
-const int MOVEFLAG_GRAVITYUNAFFECTEDBYTICRATE = 4;
-#define GRAVITY_UNAFFECTED_BY_TICRATE (getstati(STAT_MOVEFLAGS) & MOVEFLAG_GRAVITYUNAFFECTEDBYTICRATE)
-
-.entity move_groundentity; // FIXME add move_groundnetworkentity?
-.float move_suspendedinair;
-.float move_didgravity;
-
-void _Movetype_CheckVelocity() // SV_CheckVelocity
-{
-}
-
-float _Movetype_CheckWater(entity ent) // SV_CheckWater
-{
-       vector point = ent.move_origin;
-       point.z += (ent.mins.z + 1);
-
-       int nativecontents = pointcontents(point);
-
-       if(ent.move_watertype)
-       if(ent.move_watertype != nativecontents)
-       {
-               //print(sprintf("_Movetype_CheckWater(): Original: '%d', New: '%d'\n", ent.move_watertype, nativecontents));
-               if(ent.contentstransition)
-                       ent.contentstransition(ent.move_watertype, nativecontents);
-       }
-
-       ent.move_waterlevel = 0;
-       ent.move_watertype = CONTENT_EMPTY;
-
-       int supercontents = Mod_Q1BSP_SuperContentsFromNativeContents(nativecontents);
-       if(supercontents & DPCONTENTS_LIQUIDSMASK)
-       {
-               ent.move_watertype = nativecontents;
-               ent.move_waterlevel = 1;
-               point.y = (ent.origin.y + ((ent.mins.z + ent.maxs.y) * 0.5));
-               if(Mod_Q1BSP_SuperContentsFromNativeContents(pointcontents(point)) & DPCONTENTS_LIQUIDSMASK)
-               {
-                       ent.move_waterlevel = 2;
-                       point.y = ent.origin.y + ent.view_ofs.y;
-                       if(Mod_Q1BSP_SuperContentsFromNativeContents(pointcontents(point)) & DPCONTENTS_LIQUIDSMASK)
-                               ent.move_waterlevel = 3;
-               }
-       }
-
-       return (ent.move_waterlevel > 1);
-}
-
-void _Movetype_CheckWaterTransition(entity ent) // SV_CheckWaterTransition
-{
-       float contents = pointcontents(ent.move_origin);
-
-       if(!ent.move_watertype)
-       {
-               // just spawned here
-               if(!autocvar_cl_gameplayfix_fixedcheckwatertransition)
-               {
-                       ent.move_watertype = contents;
-                       ent.move_waterlevel = 1;
-                       return;
-               }
-       }
-       else if(ent.move_watertype != contents)
-       {
-               //print(sprintf("_Movetype_CheckWaterTransition(): Origin: %s, Direct: '%d', Original: '%d', New: '%d'\n", vtos(ent.move_origin), pointcontents(ent.move_origin), ent.move_watertype, contents));
-               if(ent.contentstransition)
-                       ent.contentstransition(ent.move_watertype, contents);
-       }
-
-       if(contents <= CONTENT_WATER)
-       {
-               ent.move_watertype = contents;
-               ent.move_waterlevel = 1;
-       }
-       else
-       {
-               ent.move_watertype = CONTENT_EMPTY;
-               ent.move_waterlevel = (autocvar_cl_gameplayfix_fixedcheckwatertransition ? 0 : contents);
-       }
-}
-
-void _Movetype_Impact(entity oth) // SV_Impact
-{
-       entity oldother, oldself;
-
-       oldself = self;
-       oldother = other;
-
-       if(self.move_touch)
-       {
-               other = oth;
-
-               self.move_touch();
-
-               other = oldother;
-       }
-
-       if(oth.move_touch)
-       {
-               other = self;
-               self = oth;
-
-               self.move_touch();
-
-               self = oldself;
-               other = oldother;
-       }
-}
-
-void _Movetype_LinkEdict_TouchAreaGrid() // SV_LinkEdict_TouchAreaGrid
-{
-       entity e, oldself, oldother;
-
-       oldself = self;
-       oldother = other;
-
-       for(e = findradius(0.5 * (self.absmin + self.absmax), 0.5 * vlen(self.absmax - self.absmin)); e; e = e.chain)
-       {
-               if(e.move_touch)
-               if(boxesoverlap(e.absmin, e.absmax, oldself.absmin, oldself.absmax))
-               {
-                       self = e;
-                       other = oldself;
-
-                       trace_allsolid = false;
-                       trace_startsolid = false;
-                       trace_fraction = 1;
-                       trace_inwater = false;
-                       trace_inopen = true;
-                       trace_endpos = e.origin;
-                       trace_plane_normal = '0 0 1';
-                       trace_plane_dist = 0;
-                       trace_ent = oldself;
-
-                       e.move_touch();
-               }
-       }
-
-       other = oldother;
-       self = oldself;
-}
-
-void _Movetype_LinkEdict(float touch_triggers) // SV_LinkEdict
-{
-       vector mi, ma;
-       if(self.solid == SOLID_BSP)
-       {
-               // TODO set the absolute bbox
-               mi = self.mins;
-               ma = self.maxs;
-       }
-       else
-       {
-               mi = self.mins;
-               ma = self.maxs;
-       }
-       mi = mi + self.origin;
-       ma = ma + self.origin;
-
-       if(self.move_flags & FL_ITEM)
-       {
-               mi.x -= 15;
-               mi.y -= 15;
-               mi.z -= 1;
-               ma.x += 15;
-               ma.y += 15;
-               ma.z += 1;
-       }
-       else
-       {
-               mi.x -= 1;
-               mi.y -= 1;
-               mi.z -= 1;
-               ma.x += 1;
-               ma.y += 1;
-               ma.z += 1;
-       }
-
-       self.absmin = mi;
-       self.absmax = ma;
-
-       if(touch_triggers)
-               _Movetype_LinkEdict_TouchAreaGrid();
-}
-
-float _Movetype_TestEntityPosition(vector ofs) // SV_TestEntityPosition
-{
-       vector org;
-       org = self.move_origin + ofs;
-
-       int cont = self.dphitcontentsmask;
-       self.dphitcontentsmask = DPCONTENTS_SOLID;
-       tracebox(self.move_origin, self.mins, self.maxs, self.move_origin, MOVE_NOMONSTERS, self);
-       self.dphitcontentsmask = cont;
-
-       if(trace_startsolid)
-               return true;
-
-       if(vlen(trace_endpos - self.move_origin) > 0.0001)
-               self.move_origin = trace_endpos;
-       return false;
-}
-
-float _Movetype_UnstickEntity() // SV_UnstickEntity
-{
-       if(!_Movetype_TestEntityPosition('0 0 0'))
-               return true;
-       if(!_Movetype_TestEntityPosition('-1 0 0')) goto success;
-       if(!_Movetype_TestEntityPosition('1 0 0')) goto success;
-       if(!_Movetype_TestEntityPosition('0 -1 0')) goto success;
-       if(!_Movetype_TestEntityPosition('0 1 0')) goto success;
-       if(!_Movetype_TestEntityPosition('-1 -1 0')) goto success;
-       if(!_Movetype_TestEntityPosition('1 -1 0')) goto success;
-       if(!_Movetype_TestEntityPosition('-1 1 0')) goto success;
-       if(!_Movetype_TestEntityPosition('1 1 0')) goto success;
-       float i;
-       for(i = 1; i <= 17; ++i)
-       {
-               if(!_Movetype_TestEntityPosition('0 0 -1' * i)) goto success;
-               if(!_Movetype_TestEntityPosition('0 0 1' * i)) goto success;
-       }
-       dprintf("Can't unstick an entity (edict: %d, classname: %s, origin: %s)\n", num_for_edict(self), self.classname, vtos(self.move_origin));
-       return false;
-:success
-       dprintf("Sucessfully unstuck an entity (edict: %d, classname: %s, origin: %s)\n", num_for_edict(self), self.classname, vtos(self.move_origin));
-       _Movetype_LinkEdict(true);
-       return true;
-}
-
-vector _Movetype_ClipVelocity(vector vel, vector norm, float f) // SV_ClipVelocity
-{
-       vel = vel - ((vel * norm) * norm) * f;
-
-       if(vel.x > -0.1 && vel.x < 0.1) vel.x = 0;
-       if(vel.y > -0.1 && vel.y < 0.1) vel.y = 0;
-       if(vel.z > -0.1 && vel.z < 0.1) vel.z = 0;
-
-       return vel;
-}
-
-void _Movetype_PushEntityTrace(vector push)
-{
-       vector end;
-       float type;
-
-       end = self.move_origin + push;
-
-       if(self.move_nomonsters)
-               type = max(0, self.move_nomonsters);
-       else if(self.move_movetype == MOVETYPE_FLYMISSILE)
-               type = MOVE_MISSILE;
-       else if(self.solid == SOLID_TRIGGER || self.solid == SOLID_NOT)
-               type = MOVE_NOMONSTERS;
-       else
-               type = MOVE_NORMAL;
-
-       tracebox(self.move_origin, self.mins, self.maxs, end, type, self);
-}
-
-float _Movetype_PushEntity(vector push, float failonstartsolid) // SV_PushEntity
-{
-       _Movetype_PushEntityTrace(push);
-
-       if(trace_startsolid && failonstartsolid)
-               return trace_fraction;
-
-       self.move_origin = trace_endpos;
-
-       if(trace_fraction < 1)
-               if(self.solid >= SOLID_TRIGGER && (!(self.move_flags & FL_ONGROUND) || (self.move_groundentity != trace_ent)))
-                       _Movetype_Impact(trace_ent);
-
-       return trace_fraction;
-}
-
-const float MAX_CLIP_PLANES = 5;
-void _Movetype_Physics_Toss(float dt) // SV_Physics_Toss
-{
-       if(self.move_flags & FL_ONGROUND)
-       {
-               if(self.move_velocity.z >= 1/32)
-                       self.move_flags &= ~FL_ONGROUND;
-               else if(!self.move_groundentity)
-                       return;
-               else if(self.move_suspendedinair && wasfreed(self.move_groundentity))
-               {
-                       self.move_groundentity = world;
-                       return;
-               }
-       }
-
-       self.move_suspendedinair = false;
-
-       _Movetype_CheckVelocity();
-
-       if(self.move_movetype == MOVETYPE_BOUNCE || self.move_movetype == MOVETYPE_TOSS)
-       {
-               self.move_didgravity = 1;
-               if(GRAVITY_UNAFFECTED_BY_TICRATE)
-               {
-                       if(self.gravity)
-                               self.move_velocity_z -= 0.5 * dt * self.gravity * getstatf(STAT_MOVEVARS_GRAVITY);
-                       else
-                               self.move_velocity_z -= 0.5 * dt * getstatf(STAT_MOVEVARS_GRAVITY);
-               }
-               else
-               {
-                       if(self.gravity)
-                               self.move_velocity_z -= dt * self.gravity * getstatf(STAT_MOVEVARS_GRAVITY);
-                       else
-                               self.move_velocity_z -= dt * getstatf(STAT_MOVEVARS_GRAVITY);
-               }
-       }
-
-       self.move_angles = self.move_angles + self.move_avelocity * dt;
-
-       float movetime, bump;
-       movetime = dt;
-       for(bump = 0; bump < MAX_CLIP_PLANES && movetime > 0; ++bump)
-       {
-               vector move;
-               move = self.move_velocity * movetime;
-               _Movetype_PushEntity(move, true);
-               if(wasfreed(self))
-                       return;
-
-               if(trace_startsolid)
-               {
-                       _Movetype_UnstickEntity();
-                       _Movetype_PushEntity(move, false);
-                       if(wasfreed(self))
-                               return;
-               }
-
-               if(trace_fraction == 1)
-                       break;
-
-               movetime *= 1 - min(1, trace_fraction);
-
-               if(self.move_movetype == MOVETYPE_BOUNCEMISSILE)
-               {
-                       self.move_velocity = _Movetype_ClipVelocity(self.move_velocity, trace_plane_normal, 2.0);
-                       self.move_flags &= ~FL_ONGROUND;
-               }
-               else if(self.move_movetype == MOVETYPE_BOUNCE)
-               {
-                       float d, bouncefac, bouncestop;
-
-                       bouncefac = self.move_bounce_factor;     if(!bouncefac)  bouncefac = 0.5;
-                       bouncestop = self.move_bounce_stopspeed; if(!bouncestop) bouncestop = 60 / 800;
-                       if(self.gravity)
-                               bouncestop *= self.gravity * getstatf(STAT_MOVEVARS_GRAVITY);
-                       else
-                               bouncestop *= getstatf(STAT_MOVEVARS_GRAVITY);
-
-                       self.move_velocity = _Movetype_ClipVelocity(self.move_velocity, trace_plane_normal, 1 + bouncefac);
-
-                       d = trace_plane_normal * self.move_velocity;
-                       if(trace_plane_normal.z > 0.7 && d < bouncestop && d > -bouncestop)
-                       {
-                               self.move_flags |= FL_ONGROUND;
-                               self.move_groundentity = trace_ent;
-                               self.move_velocity = '0 0 0';
-                               self.move_avelocity = '0 0 0';
-                       }
-                       else
-                               self.move_flags &= ~FL_ONGROUND;
-               }
-               else
-               {
-                       self.move_velocity = _Movetype_ClipVelocity(self.move_velocity, trace_plane_normal, 1.0);
-                       if(trace_plane_normal.z > 0.7)
-                       {
-                               self.move_flags |= FL_ONGROUND;
-                               self.move_groundentity = trace_ent;
-                               if(trace_ent.solid == SOLID_BSP)
-                                       self.move_suspendedinair = true;
-                               self.move_velocity = '0 0 0';
-                               self.move_avelocity = '0 0 0';
-                       }
-                       else
-                               self.move_flags &= ~FL_ONGROUND;
-               }
-
-               // DP revision 8905 (just, WHY...)
-               if(self.move_movetype == MOVETYPE_BOUNCEMISSILE)
-                       break;
-
-               // DP revision 8918 (WHY...)
-               if(self.move_flags & FL_ONGROUND)
-                       break;
-       }
-
-       if(GRAVITY_UNAFFECTED_BY_TICRATE)
-       if(self.move_didgravity > 0)
-       if(!(self.move_flags & FL_ONGROUND))
-       {
-               if(self.gravity)
-                       self.move_velocity_z -= 0.5 * dt * self.gravity * getstatf(STAT_MOVEVARS_GRAVITY);
-               else
-                       self.move_velocity_z -= 0.5 * dt * getstatf(STAT_MOVEVARS_GRAVITY);
-       }
-
-       _Movetype_CheckWaterTransition(self);
-}
-
-void _Movetype_Physics_Frame(float movedt)
-{
-       self.move_didgravity = -1;
-       switch(self.move_movetype)
-       {
-               case MOVETYPE_PUSH:
-               case MOVETYPE_FAKEPUSH:
-                       error("SV_Physics_Pusher not implemented");
-                       break;
-               case MOVETYPE_NONE:
-                       break;
-               case MOVETYPE_FOLLOW:
-                       error("SV_Physics_Follow not implemented");
-                       break;
-               case MOVETYPE_NOCLIP:
-                       _Movetype_CheckWater(self);
-                       self.move_origin = self.move_origin + ticrate * self.move_velocity;
-                       self.move_angles = self.move_angles + ticrate * self.move_avelocity;
-                       _Movetype_LinkEdict(false);
-                       break;
-               case MOVETYPE_STEP:
-                       error("SV_Physics_Step not implemented");
-                       break;
-               case MOVETYPE_WALK:
-                       error("SV_Physics_Walk not implemented");
-                       break;
-               case MOVETYPE_TOSS:
-               case MOVETYPE_BOUNCE:
-               case MOVETYPE_BOUNCEMISSILE:
-               case MOVETYPE_FLYMISSILE:
-               case MOVETYPE_FLY:
-                       _Movetype_Physics_Toss(movedt);
-                       break;
-       }
-}
-
-void Movetype_Physics_NoMatchServer() // optimized
-{
-       float movedt;
-
-       movedt = time - self.move_time;
-       self.move_time = time;
-
-       _Movetype_Physics_Frame(movedt);
-       if(wasfreed(self))
-               return;
-
-       self.avelocity = self.move_avelocity;
-       self.velocity = self.move_velocity;
-       self.angles = self.move_angles;
-       setorigin(self, self.move_origin);
-}
-
-void Movetype_Physics_MatchServer(bool sloppy)
-{
-       Movetype_Physics_MatchTicrate(ticrate, sloppy);
-}
-
-void Movetype_Physics_MatchTicrate(float tr, bool sloppy) // SV_Physics_Entity
-{
-       float n, i, dt, movedt;
-
-       if(tr <= 0)
-       {
-               Movetype_Physics_NoMatchServer();
-               return;
-       }
-
-       dt = time - self.move_time;
-
-       movedt = tr;
-       n = max(0, floor(dt / tr));
-       dt -= n * tr;
-       self.move_time += n * tr;
-
-       if(!self.move_didgravity)
-               self.move_didgravity = ((self.move_movetype == MOVETYPE_BOUNCE || self.move_movetype == MOVETYPE_TOSS) && !(self.move_flags & FL_ONGROUND));
-
-       for(i = 0; i < n; ++i)
-       {
-               _Movetype_Physics_Frame(movedt);
-               if(wasfreed(self))
-                       return;
-       }
-
-       self.avelocity = self.move_avelocity;
-
-       if(dt > 0 && self.move_movetype != MOVETYPE_NONE && !(self.move_flags & FL_ONGROUND))
-       {
-               // now continue the move from move_time to time
-               self.velocity = self.move_velocity;
-
-               if(self.move_didgravity > 0)
-               {
-                       if(GRAVITY_UNAFFECTED_BY_TICRATE)
-                       {
-                               if(self.gravity)
-                                       self.velocity_z -= 0.5 * dt * self.gravity * getstatf(STAT_MOVEVARS_GRAVITY);
-                               else
-                                       self.velocity_z -= 0.5 * dt * getstatf(STAT_MOVEVARS_GRAVITY);
-                       }
-                       else
-                       {
-                               if(self.gravity)
-                                       self.velocity_z -= dt * self.gravity * getstatf(STAT_MOVEVARS_GRAVITY);
-                               else
-                                       self.velocity_z -= dt * getstatf(STAT_MOVEVARS_GRAVITY);
-                       }
-               }
-
-               self.angles = self.move_angles + dt * self.avelocity;
-
-               if(sloppy || self.movetype == MOVETYPE_NOCLIP)
-               {
-                       setorigin(self, self.move_origin + dt * self.velocity);
-               }
-               else
-               {
-                       _Movetype_PushEntityTrace(dt * self.velocity);
-                       if(!trace_startsolid)
-                               setorigin(self, trace_endpos);
-               }
-
-               if(self.move_didgravity > 0)
-               {
-                       if(GRAVITY_UNAFFECTED_BY_TICRATE)
-                       {
-                               if(self.gravity)
-                                       self.velocity_z -= 0.5 * dt * self.gravity * getstatf(STAT_MOVEVARS_GRAVITY);
-                               else
-                                       self.velocity_z -= 0.5 * dt * getstatf(STAT_MOVEVARS_GRAVITY);
-                       }
-               }
-       }
-       else
-       {
-               self.velocity = self.move_velocity;
-               self.angles = self.move_angles;
-               setorigin(self, self.move_origin);
-       }
-}
diff --git a/qcsrc/client/movetypes.qh b/qcsrc/client/movetypes.qh
deleted file mode 100644 (file)
index 3294ce4..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-#ifndef MOVETYPES_H
-#define MOVETYPES_H
-
-.float move_movetype;
-.float move_time;
-.vector move_origin;
-.vector move_angles;
-.vector move_velocity;
-.vector move_avelocity;
-.int move_flags;
-.int move_watertype;
-.int move_waterlevel;
-.void(void) move_touch;
-.void(float, float) contentstransition;
-.float move_bounce_factor;
-.float move_bounce_stopspeed;
-.float move_nomonsters; // -1 for MOVE_NORMAL, otherwise a MOVE_ constant
-
-// should match sv_gameplayfix_fixedcheckwatertransition
-float autocvar_cl_gameplayfix_fixedcheckwatertransition = 1;
-
-void Movetype_Physics_MatchTicrate(float tr, bool sloppy);
-void Movetype_Physics_MatchServer(bool sloppy);
-void Movetype_Physics_NoMatchServer();
-
-const int MOVETYPE_NONE                                = 0;
-const int MOVETYPE_ANGLENOCLIP     = 1;
-const int MOVETYPE_ANGLECLIP       = 2;
-const int MOVETYPE_WALK                                = 3;
-const int MOVETYPE_STEP                                = 4;
-const int MOVETYPE_FLY                         = 5;
-const int MOVETYPE_TOSS                                = 6;
-const int MOVETYPE_PUSH                                = 7;
-const int MOVETYPE_NOCLIP                  = 8;
-const int MOVETYPE_FLYMISSILE      = 9;
-const int MOVETYPE_BOUNCE                  = 10;
-const int MOVETYPE_BOUNCEMISSILE       = 11;   // Like bounce but doesn't lose speed on bouncing
-const int MOVETYPE_FOLLOW           = 12;
-const int MOVETYPE_FAKEPUSH         = 13;
-const int MOVETYPE_FLY_WORLDONLY    = 33;
-
-const int FL_ITEM                   = 256;
-const int FL_ONGROUND                          = 512;
-#endif
index 5635f3f99b44d51cf04af689f36849344c58ee2a..2047410a972c75722908739959645212174f3672 100644 (file)
@@ -1,15 +1,13 @@
-#if defined(CSQC)
-       #include "../dpdefs/csprogsdefs.qh"
-       #include "noise.qh"
-#elif defined(MENUQC)
-#elif defined(SVQC)
-#endif
+#include "noise.qh"
+#include "_all.qh"
+
+entityclass(Noise);
+class(Noise) .float noise_baccum;
+class(Noise) .float noise_paccum;
+class(Noise) .float noise_paccum2;
+class(Noise) .float noise_paccum3;
+class(Noise) .float noise_bstate;
 
-.float noise_baccum;
-.float noise_paccum;
-.float noise_paccum2;
-.float noise_paccum3;
-.float noise_bstate;
 float Noise_Brown(entity e, float dt)
 {
        e.noise_baccum += random() * sqrt(dt); // same stddev for all dt
index 6d2ddf87d5a431b3cf4c901b60881d868fb0e25b..e997d15600f835a1b40de4fac68618374d301886 100644 (file)
 #include "particles.qh"
+#include "_all.qh"
 
-void Draw_PointParticles()
-{
-       float n, i, fail;
-       vector p;
-       vector sz;
-       vector o;
-       o = self.origin;
-       sz = self.maxs - self.mins;
-       n = BGMScript(self);
-       if(self.absolute == 2)
-       {
-               if(n >= 0)
-                       n = self.just_toggled ? self.impulse : 0;
-               else
-                       n = self.impulse * drawframetime;
-       }
-       else
-       {
-               n *= self.impulse * drawframetime;
-               if(self.just_toggled)
-                       if(n < 1)
-                               n = 1;
-       }
-       if(n == 0)
-               return;
-       fail = 0;
-       for(i = random(); i <= n && fail <= 64*n; ++i)
-       {
-               p = o + self.mins;
-               p.x += random() * sz.x;
-               p.y += random() * sz.y;
-               p.z += random() * sz.z;
-               if(WarpZoneLib_BoxTouchesBrush(p, p, self, world))
-               {
-                       if(self.movedir != '0 0 0')
-                       {
-                               traceline(p, p + normalize(self.movedir) * 4096, 0, world);
-                               p = trace_endpos;
-                               pointparticles(self.cnt, p, trace_plane_normal * vlen(self.movedir) + self.velocity + randomvec() * self.waterlevel, self.count);
-                       }
-                       else
-                       {
-                               pointparticles(self.cnt, p, self.velocity + randomvec() * self.waterlevel, self.count);
-                       }
-                       if(self.noise != "")
-                       {
-                               setorigin(self, p);
-                               sound(self, CH_AMBIENT, self.noise, VOL_BASE * self.volume, self.atten);
-                       }
-                       self.just_toggled = 0;
-               }
-               else if(self.absolute)
-               {
-                       ++fail;
-                       --i;
-               }
-       }
-       setorigin(self, o);
-}
+#include "../common/stats.qh"
+#include "../common/util.qh"
 
-void Ent_PointParticles_Remove()
-{
-       if(self.noise)
-               strunzone(self.noise);
-       self.noise = string_null;
-       if(self.bgmscript)
-               strunzone(self.bgmscript);
-       self.bgmscript = string_null;
-}
-
-void Ent_PointParticles()
-{
-       float i;
-       vector v;
-       int f = ReadByte();
-       if(f & 2)
-       {
-               i = ReadCoord(); // density (<0: point, >0: volume)
-               if(i && !self.impulse && self.cnt) // self.cnt check is so it only happens if the ent already existed
-                       self.just_toggled = 1;
-               self.impulse = i;
-       }
-       if(f & 4)
-       {
-               self.origin_x = ReadCoord();
-               self.origin_y = ReadCoord();
-               self.origin_z = ReadCoord();
-       }
-       if(f & 1)
-       {
-               self.modelindex = ReadShort();
-               if(f & 0x80)
-               {
-                       if(self.modelindex)
-                       {
-                               self.mins_x = ReadCoord();
-                               self.mins_y = ReadCoord();
-                               self.mins_z = ReadCoord();
-                               self.maxs_x = ReadCoord();
-                               self.maxs_y = ReadCoord();
-                               self.maxs_z = ReadCoord();
-                       }
-                       else
-                       {
-                               self.mins    = '0 0 0';
-                               self.maxs_x = ReadCoord();
-                               self.maxs_y = ReadCoord();
-                               self.maxs_z = ReadCoord();
-                       }
-               }
-               else
-               {
-                       self.mins = self.maxs = '0 0 0';
-               }
-
-               self.cnt = ReadShort(); // effect number
-
-               if(f & 0x20)
-               {
-                       self.velocity = decompressShortVector(ReadShort());
-                       self.movedir = decompressShortVector(ReadShort());
-               }
-               else
-               {
-                       self.velocity = self.movedir = '0 0 0';
-               }
-               if(f & 0x40)
-               {
-                       self.waterlevel = ReadShort() / 16.0;
-                       self.count = ReadByte() / 16.0;
-               }
-               else
-               {
-                       self.waterlevel = 0;
-                       self.count = 1;
-               }
-               if(self.noise)
-                       strunzone(self.noise);
-               if(self.bgmscript)
-                       strunzone(self.bgmscript);
-               self.noise = strzone(ReadString());
-               if(self.noise != "")
-               {
-                       self.atten = ReadByte() / 64.0;
-                       self.volume = ReadByte() / 255.0;
-               }
-               self.bgmscript = strzone(ReadString());
-               if(self.bgmscript != "")
-               {
-                       self.bgmscriptattack = ReadByte() / 64.0;
-                       self.bgmscriptdecay = ReadByte() / 64.0;
-                       self.bgmscriptsustain = ReadByte() / 255.0;
-                       self.bgmscriptrelease = ReadByte() / 64.0;
-               }
-               BGMScript_InitEntity(self);
-       }
-
-       if(f & 2)
-       {
-               self.absolute = (self.impulse >= 0);
-               if(!self.absolute)
-               {
-                       v = self.maxs - self.mins;
-                       self.impulse *= -v.x * v.y * v.z / 262144; // relative: particles per 64^3 cube
-               }
-       }
-
-       if(f & 0x10)
-               self.absolute = 2;
-
-       setorigin(self, self.origin);
-       setsize(self, self.mins, self.maxs);
-       self.solid = SOLID_NOT;
-       self.draw = Draw_PointParticles;
-       self.entremove = Ent_PointParticles_Remove;
-}
-
-void Draw_Rain()
-{
-    te_particlerain(self.origin + self.mins, self.origin + self.maxs, self.velocity, floor(self.count * drawframetime + random()), self.glow_color);
-}
-
-void Draw_Snow()
-{
-    te_particlesnow(self.origin + self.mins, self.origin + self.maxs, self.velocity, floor(self.count * drawframetime + random()), self.glow_color);
-}
-
-void Ent_RainOrSnow()
-{
-       self.impulse = ReadByte(); // Rain, Snow, or Whatever
-       self.origin_x = ReadCoord();
-       self.origin_y = ReadCoord();
-       self.origin_z = ReadCoord();
-       self.maxs_x = ReadCoord();
-       self.maxs_y = ReadCoord();
-       self.maxs_z = ReadCoord();
-       self.velocity = decompressShortVector(ReadShort());
-       self.count = ReadShort() * 10;
-       self.glow_color = ReadByte(); // color
-
-       self.mins    = -0.5 * self.maxs;
-       self.maxs    =  0.5 * self.maxs;
-       self.origin  = self.origin - self.mins;
-
-       setorigin(self, self.origin);
-       setsize(self, self.mins, self.maxs);
-       self.solid = SOLID_NOT;
-       if(self.impulse)
-               self.draw = Draw_Rain;
-       else
-               self.draw = Draw_Snow;
-}
+#include "../warpzonelib/common.qh"
 
 void Net_ReadVortexBeamParticle()
 {
index 12c999ba2bec219d5fb0adb0089aa66a271bfec1..791313f50408de88ed712a9bd60d90b2a3c3cd3e 100644 (file)
@@ -1,18 +1,18 @@
 #ifndef PARTICLES_H
 #define PARTICLES_H
-
 .int dphitcontentsmask;
 
-.int cnt; // effect number
-.vector velocity; // particle velocity
-.float waterlevel; // direction jitter
-.int count; // count multiplier
-.int impulse; // density
-.string noise; // sound
-.float atten;
-.float volume;
-.float absolute; // 1 = count per second is absolute, 2 = only spawn at toggle
-.vector movedir; // trace direction
+entityclass(PointParticles);
+class(PointParticles) .int cnt; // effect number
+class(PointParticles) .vector velocity; // particle velocity
+class(PointParticles) .float waterlevel; // direction jitter
+class(PointParticles) .int count; // count multiplier
+class(PointParticles) .int impulse; // density
+class(PointParticles) .string noise; // sound
+class(PointParticles) .float atten;
+class(PointParticles) .float volume;
+class(PointParticles) .float absolute; // 1 = count per second is absolute, 2 = only spawn at toggle
+class(PointParticles) .vector movedir; // trace direction
 
 void Draw_PointParticles();
 
@@ -20,13 +20,7 @@ void Ent_PointParticles_Remove();
 
 void Ent_PointParticles();
 
-.float glow_color; // palette index
-
-void Draw_Rain();
-
-void Draw_Snow();
-
-void Ent_RainOrSnow();
+class(PointParticles) .float glow_color; // palette index
 
 void Net_ReadVortexBeamParticle();
 #endif
index 0a9ac8cacb9167ddf05fc7eb762aafc8b02b26ff..1d67e171ca667fa225e83644c7660254a60055af 100644 (file)
@@ -1,14 +1,16 @@
 #include "player_skeleton.qh"
 
+#include "../common/csqcmodel_settings.qh"
+
 #include "../warpzonelib/anglestransform.qh"
 
-.float skeleton_info_modelindex;
-.float skeleton_info_skin;
+class(Skeleton) .float skeleton_info_modelindex;
+class(Skeleton) .float skeleton_info_skin;
 const int BONETYPE_LOWER = 0;
 const int BONETYPE_UPPER = 1;
 const int MAX_BONES = 128;
-.float skeleton_bonetype[MAX_BONES];
-.float skeleton_numbones;
+class(Skeleton) .float skeleton_bonetype[MAX_BONES];
+class(Skeleton) .float skeleton_numbones;
 
 void skeleton_loadinfo(entity e)
 {
@@ -170,6 +172,8 @@ void skeleton_from_frames(entity e, float is_dead)
 
        if(!is_dead)
        {
+               if(self == csqcplayer)
+                       self.v_angle_x = input_angles_x;
                int i;
                for(i = 0; i < MAX_AIM_BONES; ++i)
                {
index 6c95ce231051fad1b7315e50476e82c7b280aa94..4a37df5e458b4923b3ca6fa298a3c34feb78aa89 100644 (file)
@@ -1,13 +1,16 @@
 #ifndef PLAYER_SKELETON
 #define PLAYER_SKELETON
 
+#include "../common/util.qh"
+
 void free_skeleton_from_frames(entity e);
 void skeleton_from_frames(entity e, float is_dead);
 void skeleton_loadinfo(entity e);
 
-.float bone_upperbody;
-.int bone_weapon;
-.float bone_aim[MAX_AIM_BONES];
-.float bone_aimweight[MAX_AIM_BONES];
-.float fixbone;
+entityclass(Skeleton);
+class(Skeleton) .float bone_upperbody;
+class(Skeleton) .int bone_weapon;
+class(Skeleton) .float bone_aim[MAX_AIM_BONES];
+class(Skeleton) .float bone_aimweight[MAX_AIM_BONES];
+class(Skeleton) .float fixbone;
 #endif
index 935f1421ed1379f26ce486ce56747fc8cf80385c..12e4e0ea5a23c365a5c8b23a4f6b9fdb09045a84 100644 (file)
@@ -1,10 +1,7 @@
-#if defined(CSQC)
-       #include "../dpdefs/csprogsdefs.qh"
-       #include "../warpzonelib/mathlib.qh"
-       #include "prandom.qh"
-#elif defined(MENUQC)
-#elif defined(SVQC)
-#endif
+#include "prandom.qh"
+#include "_all.qh"
+
+#include "../warpzonelib/mathlib.qh"
 
 // prandom - PREDICTABLE random number generator (not seeded yet)
 
index f80da18d67309ace7482be0dd4ac37ac784cd1c0..a9d0c565a7e1ffc3b627db8ca4b0b00abdc4f746 100644 (file)
@@ -11,14 +11,13 @@ damage.qc
 effects.qc
 gibs.qc
 hook.qc
-hud_config.qc
 hud.qc
-laser.qc
+hud_config.qc
 main.qc
 mapvoting.qc
 miscfunctions.qc
 modeleffects.qc
-movetypes.qc
+movelib.qc
 noise.qc
 particles.qc
 player_skeleton.qc
@@ -27,47 +26,50 @@ rubble.qc
 scoreboard.qc
 shownames.qc
 sortlist.qc
-target_music.qc
 teamradar.qc
 tturrets.qc
 tuba.qc
-vehicles/vehicles.qc
+t_items.qc
 view.qc
 wall.qc
 waypointsprites.qc
 
-command/cl_cmd.qc
+command/all.qc
+
+vehicles/bumblebee.qc
+vehicles/all.qc
 
 weapons/projectile.qc // TODO
 
 ../common/animdecide.qc
 ../common/buffs.qc
 ../common/mapinfo.qc
+../common/movetypes/include.qc
 ../common/nades.qc
 ../common/net_notice.qc
 ../common/notifications.qc
+../common/physics.qc
 ../common/playerstats.qc
 ../common/test.qc
 ../common/urllib.qc
 ../common/util.qc
 
-../common/command/generic.qc
-../common/command/markup.qc
-../common/command/rpn.qc
+../common/items/all.qc
+
+../common/monsters/all.qc
 
-../common/monsters/monsters.qc
+../common/weapons/all.qc // TODO
 
-../common/weapons/weapons.qc // TODO
+../common/triggers/include.qc
 
 ../csqcmodellib/cl_model.qc
 ../csqcmodellib/cl_player.qc
 ../csqcmodellib/interpolate.qc
 
-../server/movelib.qc
-../server/t_items.qc
-../server/vehicles/bumblebee.qc
+../server/mutators/mutator_multijump.qc
 
 ../warpzonelib/anglestransform.qc
 ../warpzonelib/client.qc
 ../warpzonelib/common.qc
 ../warpzonelib/mathlib.qc
+../warpzonelib/util_server.qc
index c09dd18aed4ed8bfe1cc3cc78256e869489efcc1..4e32c0c45490fc9451c17504c5bafb7483368701 100644 (file)
@@ -1,8 +1,4 @@
-#if defined(CSQC)
-       #include "rubble.qh"
-#elif defined(MENUQC)
-#elif defined(SVQC)
-#endif
+#include "rubble.qh"
 
 // LordHavoc: rewrote this file, it was really bad code
 
index 5ff1b55777e769f40b1446c0f71a1b1e5f1f70d8..b19406c77e3e0afc9ce1719aa49db9dd8db92295 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef RUBBLE_H
 #define RUBBLE_H
-.float creationtime;
+entityclass(Rubble);
+class(Rubble) .float creationtime;
 void RubbleLimit(string cname, float limit, void() deleteproc);
 entity RubbleNew(string cname);
 #endif
index c6d871807f2e7c190af068a4ff192b760d3de57b..418e1db08b2697239e7d81194fe91e82279d8ff6 100644 (file)
@@ -1,4 +1,15 @@
 #include "scoreboard.qh"
+#include "_all.qh"
+
+#include "hud.qh"
+#include "sortlist.qh"
+
+#include "../common/constants.qh"
+#include "../common/counting.qh"
+#include "../common/mapinfo.qh"
+#include "../common/stats.qh"
+#include "../common/teams.qh"
+#include "../common/util.qh"
 
 float scoreboard_alpha_bg;
 float scoreboard_alpha_fg;
@@ -349,7 +360,6 @@ void Cmd_HUD_SetFields(float argc)
 
        hud_fontsize = HUD_GetFontsize("hud_fontsize");
 
-       draw_beginBoldFont();
        for(i = 1; i < argc - 1; ++i)
        {
                float nocomplain;
@@ -488,7 +498,6 @@ void Cmd_HUD_SetFields(float argc)
        }
 
        hud_field[hud_num_fields] = SP_END;
-       draw_endBoldFont();
 }
 
 // MOVEUP::
@@ -868,7 +877,6 @@ vector HUD_Scoreboard_MakeTable(vector pos, entity tm, vector rgb, vector bg_siz
        }
 
        // print the strings of the columns headers and draw the columns
-       draw_beginBoldFont();
        int i;
        for(i = 0; i < hud_num_fields; ++i)
        {
@@ -912,7 +920,6 @@ vector HUD_Scoreboard_MakeTable(vector pos, entity tm, vector rgb, vector bg_siz
                        pos.x -= hud_fontsize.x;
                }
        }
-       draw_endBoldFont();
 
        pos.x = xmin;
        pos.y += 1.25 * hud_fontsize.y; // skip the header
index c0326eb786a854bb2fe69655614752d7dcd67953..e1c5addb49f0474861188f571b5f0520c7a2e181 100644 (file)
@@ -7,6 +7,7 @@ float scoreboard_active;
 float scoreboard_fade_alpha;
 
 void Cmd_HUD_SetFields(float argc);
+void HUD_DrawScoreboard();
 void HUD_InitScores();
 void HUD_UpdatePlayerPos(entity pl);
 void HUD_UpdateTeamPos(entity Team);
index c6edf5040dbd1056b6f639fb4123bdcd0514ffe6..fc4649537a4c689763d13e7452fe7ff0e4ecb1f4 100644 (file)
@@ -1,18 +1,14 @@
-#if defined(CSQC)
-       #include "../dpdefs/csprogsdefs.qh"
-       #include "defs.qh"
-       #include "../common/constants.qh"
-       #include "../common/teams.qh"
-       #include "../common/util.qh"
-       #include "../common/mapinfo.qh"
-       #include "autocvars.qh"
-       #include "main.qh"
-       #include "../csqcmodellib/cl_model.qh"
-       #include "shownames.qh"
-#elif defined(MENUQC)
-#elif defined(SVQC)
-#endif
+#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"
 
 // 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 f196f8f83340c75dfcffa464534dd2e61f5ca385..63fd92e041da6e2505d0d015e2cac576904f2f86 100644 (file)
@@ -1,9 +1,13 @@
 #ifndef SHOWNAMES_H
 #define SHOWNAMES_H
 
-.float healthvalue;
-.float armorvalue;
-.float sameteam;
-.float fadedelay;
-.float pointtime;
+entityclass(ShowNames);
+class(ShowNames) .float healthvalue;
+class(ShowNames) .float armorvalue;
+class(ShowNames) .float sameteam;
+class(ShowNames) .float fadedelay;
+class(ShowNames) .float pointtime;
+
+void Draw_ShowNames_All();
+
 #endif
index 1b84287139e570c77cd5bdad67ebb9863166528f..298314810063b5e5dfbbaf0e85d648750b2eff61 100644 (file)
@@ -1,8 +1,9 @@
 #ifndef SORTLIST_H
 #define SORTLIST_H
 
+entityclass(Sort);
 //.float(entity,entity) sort_cmp;
-.entity sort_next, sort_prev;
+class(Sort) .entity sort_next, sort_prev;
 
 entity Sort_Spawn();
 
diff --git a/qcsrc/client/t_items.qc b/qcsrc/client/t_items.qc
new file mode 100644 (file)
index 0000000..3981b29
--- /dev/null
@@ -0,0 +1,10 @@
+#include "_all.qh"
+
+#include "../common/buffs.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 "../server/t_items.qc"
diff --git a/qcsrc/client/t_items.qh b/qcsrc/client/t_items.qh
new file mode 100644 (file)
index 0000000..eb01624
--- /dev/null
@@ -0,0 +1 @@
+#include "../server/t_items.qh"
diff --git a/qcsrc/client/target_music.qc b/qcsrc/client/target_music.qc
deleted file mode 100644 (file)
index 662a673..0000000
+++ /dev/null
@@ -1,183 +0,0 @@
-#include "target_music.qh"
-
-void TargetMusic_Advance()
-{
-       // run AFTER all the thinks!
-       entity best, e;
-       float vol, vol0;
-       best = music_default;
-       if(music_target && time < music_target.lifetime)
-               best = music_target;
-       if(music_trigger)
-               best = music_trigger;
-       for(e = world; (e = findfloat(e, enttype, ENT_CLIENT_TRIGGER_MUSIC)); ) if(e.noise)
-       {
-               vol0 = e.lastvol;
-               if(getsoundtime(e, CH_BGM_SINGLE) < 0)
-               {
-                       vol0 = -1;
-               }
-               if(e == best)
-               {
-                       // increase volume
-                       if(e.fade_time > 0)
-                               e.state = bound(0, e.state + frametime / e.fade_time, 1);
-                       else
-                               e.state = 1;
-               }
-               else
-               {
-                       // decrease volume
-                       if(e.fade_rate > 0)
-                               e.state = bound(0, e.state - frametime / e.fade_rate, 1);
-                       else
-                               e.state = 0;
-               }
-               vol = e.state * e.volume * autocvar_bgmvolume;
-               if(vol != vol0)
-               {
-                       if(vol0 < 0)
-                               sound(e, CH_BGM_SINGLE, e.noise, vol, ATTEN_NONE); // restart
-                       else
-                               sound(e, CH_BGM_SINGLE, "", vol, ATTEN_NONE);
-                       e.lastvol = vol;
-               }
-       }
-       music_trigger = world;
-
-       if(best)
-               bgmtime = getsoundtime(best, CH_BGM_SINGLE);
-       else
-               bgmtime = gettime(GETTIME_CDTRACK);
-}
-
-void Net_TargetMusic()
-{
-       int id = ReadShort();
-       float vol = ReadByte() / 255.0;
-       float fai = ReadByte() / 16.0;
-       float fao = ReadByte() / 16.0;
-       float tim = ReadByte();
-       string noi = ReadString();
-
-       entity e;
-       for(e = world; (e = findfloat(e, enttype, ENT_CLIENT_TRIGGER_MUSIC)); )
-       {
-               if(e.count == id)
-                       break;
-       }
-       if(!e)
-       {
-               e = spawn();
-               e.enttype = ENT_CLIENT_TRIGGER_MUSIC;
-               e.count = id;
-       }
-       if(e.noise != noi)
-       {
-               if(e.noise)
-                       strunzone(e.noise);
-               e.noise = strzone(noi);
-               precache_sound(e.noise);
-               sound(e, CH_BGM_SINGLE, e.noise, 0, ATTEN_NONE);
-               if(getsoundtime(e, CH_BGM_SINGLE) < 0)
-               {
-                       dprintf("Cannot initialize sound %s\n", e.noise);
-                       strunzone(e.noise);
-                       e.noise = string_null;
-               }
-       }
-       e.volume = vol;
-       e.fade_time = fai;
-       e.fade_rate = fao;
-       if(vol > 0)
-       {
-               if(tim == 0)
-               {
-                       music_default = e;
-                       if(!music_disabled)
-                       {
-                               e.state = 2;
-                               cvar_settemp("music_playlist_index", "-1"); // don't use playlists
-                               localcmd("cd stop\n"); // just in case
-                               music_disabled = 1;
-                       }
-               }
-               else
-               {
-                       music_target = e;
-                       e.lifetime = time + tim;
-               }
-       }
-}
-
-void Ent_TriggerMusic_Think()
-{
-       if(WarpZoneLib_BoxTouchesBrush(view_origin, view_origin, self, world))
-       {
-               music_trigger = self;
-       }
-       self.nextthink = time;
-}
-
-void Ent_TriggerMusic_Remove()
-{
-       if(self.noise)
-               strunzone(self.noise);
-       self.noise = string_null;
-}
-
-void Ent_ReadTriggerMusic()
-{
-       int f = ReadByte();
-       if(f & 4)
-       {
-               self.origin_x = ReadCoord();
-               self.origin_y = ReadCoord();
-               self.origin_z = ReadCoord();
-       }
-       if(f & 1)
-       {
-               self.modelindex = ReadShort();
-               if(self.modelindex)
-               {
-                       self.mins_x = ReadCoord();
-                       self.mins_y = ReadCoord();
-                       self.mins_z = ReadCoord();
-                       self.maxs_x = ReadCoord();
-                       self.maxs_y = ReadCoord();
-                       self.maxs_z = ReadCoord();
-               }
-               else
-               {
-                       self.mins    = '0 0 0';
-                       self.maxs_x = ReadCoord();
-                       self.maxs_y = ReadCoord();
-                       self.maxs_z = ReadCoord();
-               }
-
-               self.volume = ReadByte() / 255.0;
-               self.fade_time = ReadByte() / 16.0;
-               self.fade_rate = ReadByte() / 16.0;
-               string s = self.noise;
-               if(self.noise)
-                       strunzone(self.noise);
-               self.noise = strzone(ReadString());
-               if(self.noise != s)
-               {
-                       precache_sound(self.noise);
-                       sound(self, CH_BGM_SINGLE, self.noise, 0, ATTEN_NONE);
-                       if(getsoundtime(self, CH_BGM_SINGLE) < 0)
-                       {
-                               dprintf("Cannot initialize sound %s\n", self.noise);
-                               strunzone(self.noise);
-                               self.noise = string_null;
-                       }
-               }
-       }
-
-       setorigin(self, self.origin);
-       setsize(self, self.mins, self.maxs);
-       self.cnt = 1;
-       self.think = Ent_TriggerMusic_Think;
-       self.nextthink = time;
-}
diff --git a/qcsrc/client/target_music.qh b/qcsrc/client/target_music.qh
deleted file mode 100644 (file)
index c685214..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-#ifndef TARGET_MUSIC_H
-#define TARGET_MUSIC_H
-
-float music_disabled;
-entity music_default;
-entity music_target;
-entity music_trigger;
-// FIXME also control bgmvolume here, to not require a target_music for the default track.
-
-.int state;
-.float lastvol;
-
-void TargetMusic_Advance();
-
-void Net_TargetMusic();
-
-void Ent_TriggerMusic_Think();
-
-void Ent_TriggerMusic_Remove();
-
-void Ent_ReadTriggerMusic();
-#endif
index 1822acb5e467a2934b7c60aa80353d5c7d019636..aa7923bafc7a74bddc21f3ac08c3dd29a100492b 100644 (file)
@@ -1,8 +1,11 @@
-#if defined(CSQC)
-       #include "teamradar.qh"
-#elif defined(MENUQC)
-#elif defined(SVQC)
-#endif
+#include "teamradar.qh"
+#include "_all.qh"
+
+#include "hud.qh"
+
+#include "../common/util.qh"
+
+#include "../csqcmodellib/interpolate.qh"
 
 float vlen2d(vector v)
 {
index 31defc8efbd6c3b3bb8f78d03eaf71fa7ee07da6..f7c186ac6258c119f75657e3cb0de13d189d1285 100644 (file)
@@ -3,11 +3,12 @@
 
 const int MAX_TEAMRADAR_TIMES = 32;
 
+entityclass(TeamRadar);
 // to make entities have dots on the team radar
-.float teamradar_icon;
-.float teamradar_times[MAX_TEAMRADAR_TIMES];
-.int teamradar_time_index;
-.vector teamradar_color;
+class(TeamRadar) .float teamradar_icon;
+class(TeamRadar) .float teamradar_times[MAX_TEAMRADAR_TIMES];
+class(TeamRadar) .int teamradar_time_index;
+class(TeamRadar) .vector teamradar_color;
 
 float teamradar_angle; // player yaw angle
 vector teamradar_origin3d_in_texcoord; // player origin
index d2469851ca53f21c813d5bd629b01833f57f1847..58c031e4d85027425e530aebf125a310882899d0 100644 (file)
@@ -1,7 +1,25 @@
 #include "tturrets.qh"
+#include "_all.qh"
+
+#include "hud.qh"
+#include "movelib.qh"
+#include "prandom.qh"
+#include "teamradar.qh"
 #include "waypointsprites.qh"
 
-#include "../server/movelib.qh"
+#include "../common/teams.qh"
+
+#include "../common/movetypes/movetypes.qh"
+
+#include "../server/tturrets/include/turrets_early.qh"
+
+#include "../warpzonelib/anglestransform.qh"
+#include "../warpzonelib/mathlib.qh"
+
+.vector colormod;
+.float cnt;
+.float alpha;
+.float gravity;
 
 string tid2info_base;
 string tid2info_head;
@@ -31,7 +49,6 @@ void turret_precache(int _tid)
         precache_model ("models/turrets/head-gib2.md3");
         precache_model ("models/turrets/head-gib3.md3");
         precache_model ("models/turrets/head-gib4.md3");
-        precache_model ("models/turrets/terrainbase.md3");
         precache_model ("models/turrets/base.md3");
         precache_model ("models/turrets/rocket.md3");
     }
@@ -163,7 +180,7 @@ void turret_remove()
     self.tur_head = world;
 }
 
-.vector glowmod;
+class(Turret) .vector glowmod;
 void turret_changeteam()
 {
        switch(self.team - 1)
index 6316d795b8899e0654a7e041073322a5329c496d..4cf9854c4656f3f69aa0e5abf333fecce6a0f36a 100644 (file)
@@ -1,9 +1,8 @@
 #ifndef TTURRETS_H
 #define TTURRETS_H
 
-#include "../server/tturrets/include/turrets_early.qh"
-
 void ent_turret();
 void turrets_precache();
-.entity tur_head;
+entityclass(Turret);
+class(Turret) .entity tur_head;
 #endif
index cd518e091d3c2ecdd3677aaf7c2ca50a5f6217aa..b9f372db9d9e128d64ecdfda23a2fc336aad33b3 100644 (file)
@@ -1,4 +1,10 @@
 #include "tuba.qh"
+#include "_all.qh"
+
+#include "../common/constants.qh"
+#include "../common/util.qh"
+
+#include "../warpzonelib/mathlib.qh"
 
 #define TUBA_STARTNOTE(i, n) strcat("weapons/tuba", (i ? ftos(i) : ""), "_loopnote", ftos(n), ".wav")
 
@@ -6,11 +12,11 @@ const int TUBA_MIN = -18;
 const int TUBA_MAX = 27;
 const int TUBA_INSTRUMENTS = 3;
 
-.int note;
-.bool tuba_attenuate;
-.float tuba_volume;
-.float tuba_volume_initial;
-.int tuba_instrument;
+class(Tuba) .int note;
+class(Tuba) .bool tuba_attenuate;
+class(Tuba) .float tuba_volume;
+class(Tuba) .float tuba_volume_initial;
+class(Tuba) .int tuba_instrument;
 
 int Tuba_PitchStep;
 
index bdc1386eab666e352dd4d1ed9413a5d5fe237de3..6fe103f70676c62ff4f156e30aadea7a8f4a075f 100644 (file)
@@ -2,4 +2,7 @@
 #define TUBA_H
 void Ent_TubaNote(bool isNew);
 void Tuba_Precache();
+
+entityclass(Tuba);
+
 #endif
diff --git a/qcsrc/client/vehicles/all.qc b/qcsrc/client/vehicles/all.qc
new file mode 100644 (file)
index 0000000..ba92d7c
--- /dev/null
@@ -0,0 +1,1054 @@
+#include "all.qh"
+#include "../_all.qh"
+
+#include "../../common/movetypes/movetypes.qh"
+#include "../prandom.qh"
+#include "../scoreboard.qh"
+#include "../t_items.qh"
+
+#include "../../common/buffs.qh"
+#include "../../common/constants.qh"
+#include "../../common/movetypes/movetypes.qh"
+#include "../../common/stats.qh"
+#include "../../common/util.qh"
+
+#include "../../csqcmodellib/cl_model.qh"
+
+.float cnt;
+
+const string hud_bg = "gfx/vehicles/frame.tga";
+const string hud_sh = "gfx/vehicles/vh-shield.tga";
+
+const string hud_hp_bar = "gfx/vehicles/bar_up_left.tga";
+const string hud_hp_ico = "gfx/vehicles/health.tga";
+const string hud_sh_bar = "gfx/vehicles/bar_dwn_left.tga";
+const string hud_sh_ico = "gfx/vehicles/shield.tga";
+
+const string hud_ammo1_bar = "gfx/vehicles/bar_up_right.tga";
+const string hud_ammo1_ico = "gfx/vehicles/bullets.tga";
+const string hud_ammo2_bar = "gfx/vehicles/bar_dwn_right.tga";
+const string hud_ammo2_ico = "gfx/vehicles/rocket.tga";
+const string hud_energy = "gfx/vehicles/energy.tga";
+
+const int SBRM_FIRST = 1;
+const int SBRM_VOLLY = 1;
+const int SBRM_GUIDE = 2;
+const int SBRM_ARTILLERY = 3;
+const int SBRM_LAST = 3;
+
+const int RSM_FIRST = 1;
+const int RSM_BOMB = 1;
+const int RSM_FLARE = 2;
+const int RSM_LAST = 2;
+
+entity dropmark;
+float autocvar_cl_vehicles_hudscale = 0.5;
+float autocvar_cl_vehicles_hudalpha = 0.75;
+
+const string raptor_ico =  "gfx/vehicles/raptor.tga";
+const string raptor_gun =  "gfx/vehicles/raptor_guns.tga";
+const string raptor_bomb = "gfx/vehicles/raptor_bombs.tga";
+const string raptor_drop = "gfx/vehicles/axh-dropcross.tga";
+string raptor_xhair;
+
+
+
+const int MAX_AXH = 4;
+entity AuxiliaryXhairs[MAX_AXH];
+
+entityclass(AuxiliaryXhair);
+class(AuxiliaryXhair) .string axh_image;
+class(AuxiliaryXhair) .float  axh_fadetime;
+class(AuxiliaryXhair) .float  axh_drawflag;
+class(AuxiliaryXhair) .float  axh_scale;
+
+const string bumb_ico =  "gfx/vehicles/bumb.tga";
+const string bumb_lgun =  "gfx/vehicles/bumb_lgun.tga";
+const string bumb_rgun =  "gfx/vehicles/bumb_rgun.tga";
+
+const string bumb_gun_ico =  "gfx/vehicles/bumb_side.tga";
+const string bumb_gun_gun =  "gfx/vehicles/bumb_side_gun.tga";
+
+const string spider_ico =  "gfx/vehicles/sbot.tga";
+const string spider_rkt =  "gfx/vehicles/sbot_rpods.tga";
+const string spider_mgun = "gfx/vehicles/sbot_mguns.tga";
+string spider_xhair; // = "gfx/vehicles/axh-special1.tga";
+
+const string waki_ico = "gfx/vehicles/waki.tga";
+const string waki_eng = "gfx/vehicles/waki_e.tga";
+const string waki_gun = "gfx/vehicles/waki_guns.tga";
+const string waki_rkt = "gfx/vehicles/waki_rockets.tga";
+const string waki_xhair = "gfx/vehicles/axh-special1.tga";
+
+float alarm1time;
+float alarm2time;
+int weapon2mode;
+
+void AuxiliaryXhair_Draw2D()
+{
+    vector loc, psize;
+
+    psize = self.axh_scale * draw_getimagesize(self.axh_image);
+    loc = project_3d_to_2d(self.move_origin) - 0.5 * psize;
+    if (!(loc.z < 0 || loc.x < 0 || loc.y < 0 || loc.x > vid_conwidth || loc.y > vid_conheight))
+    {
+        loc.z = 0;
+        psize.z = 0;
+        drawpic(loc, self.axh_image, psize, self.colormod, self.alpha, self.axh_drawflag);
+    }
+
+    if(time - self.cnt > self.axh_fadetime)
+        self.draw2d = func_null;
+}
+
+void Net_AuXair2(bool bIsNew)
+{
+    int axh_id = bound(0, ReadByte(), MAX_AXH);
+    entity axh                 = AuxiliaryXhairs[axh_id];
+
+    if(axh == world || wasfreed(axh))  // MADNESS? THIS IS QQQQCCCCCCCCC (wasfreed, why do you exsist?)
+    {
+        axh                                    = spawn();
+               axh.draw2d                      = func_null;
+               axh.drawmask            = MASK_NORMAL;
+               axh.axh_drawflag        = DRAWFLAG_ADDITIVE;
+               axh.axh_fadetime        = 0.1;
+               axh.axh_image           = "gfx/vehicles/axh-ring.tga";
+               axh.axh_scale           = 1;
+        axh.alpha                      = 1;
+               AuxiliaryXhairs[axh_id] = axh;
+    }
+
+       axh.move_origin_x = ReadCoord();
+       axh.move_origin_y = ReadCoord();
+       axh.move_origin_z = ReadCoord();
+       axh.colormod_x = ReadByte() / 255;
+       axh.colormod_y = ReadByte() / 255;
+       axh.colormod_z = ReadByte() / 255;
+    axh.cnt                    = time;
+    axh.draw2d                 = AuxiliaryXhair_Draw2D;
+}
+
+void Net_VehicleSetup()
+{
+    int hud_id = ReadByte();
+
+    // Weapon update?
+    if(hud_id > HUD_VEHICLE_LAST)
+    {
+        weapon2mode = hud_id - HUD_VEHICLE_LAST;
+        return;
+    }
+
+    // hud_id == 0 means we exited a vehicle, so stop alarm sound/s
+    if(hud_id == 0)
+    {
+        sound(self, CH_TRIGGER_SINGLE, "misc/null.wav", VOL_BASEVOICE, ATTEN_NONE);
+        sound(self, CH_PAIN_SINGLE, "misc/null.wav", VOL_BASEVOICE, ATTEN_NONE);
+        return;
+    }
+
+    hud_id  = bound(HUD_VEHICLE_FIRST, hud_id, HUD_VEHICLE_LAST);
+
+    // Init auxiliary crosshairs
+    int i;
+    for(i = 0; i < MAX_AXH; ++i)
+    {
+        entity axh = AuxiliaryXhairs[i];
+        if(axh != world && !wasfreed(axh))  // MADNESS? THIS IS QQQQCCCCCCCCC (wasfreed, why do you exsist?)
+            remove(axh);
+
+        axh                                    = spawn();
+               axh.draw2d                      = func_null;
+               axh.drawmask            = MASK_NORMAL;
+               axh.axh_drawflag        = DRAWFLAG_NORMAL;
+               axh.axh_fadetime        = 0.1;
+               axh.axh_image           = "gfx/vehicles/axh-ring.tga";
+               axh.axh_scale           = 1;
+        axh.alpha                      = 1;
+               AuxiliaryXhairs[i]      = axh;
+    }
+
+    switch(hud_id)
+    {
+        case HUD_SPIDERBOT:
+            // Minigun1
+            AuxiliaryXhairs[0].axh_image   = "gfx/vehicles/axh-ring.tga";
+            AuxiliaryXhairs[0].axh_scale   = 0.25;
+            // Minigun2
+            AuxiliaryXhairs[1].axh_image   = "gfx/vehicles/axh-ring.tga";
+            AuxiliaryXhairs[1].axh_scale   = 0.25;
+            // Rocket
+            AuxiliaryXhairs[2].axh_image   = "gfx/vehicles/axh-special1.tga";
+            AuxiliaryXhairs[2].axh_scale   = 0.5;
+            break;
+
+        case HUD_WAKIZASHI:
+            AuxiliaryXhairs[0].axh_image   = "gfx/vehicles/axh-bracket.tga";
+            AuxiliaryXhairs[0].axh_scale   = 0.25;
+            break;
+
+        case HUD_RAPTOR:
+            AuxiliaryXhairs[0].axh_image   = "gfx/vehicles/axh-special2.tga";
+            AuxiliaryXhairs[0].axh_scale   = 0.5;
+            //AuxiliaryXhair[0].alpha       = 0.5;
+
+            AuxiliaryXhairs[1].axh_image   = "gfx/vehicles/axh-bracket.tga";
+            AuxiliaryXhairs[1].axh_scale   = 0.25;
+            //AuxiliaryXhair[1].alpha       = 0.75;
+            //AuxiliaryXhair[1].axh_drawflag  = DRAWFLAG_NORMAL;
+            break;
+
+        case HUD_BUMBLEBEE:
+            // Raygun-locked
+            AuxiliaryXhairs[0].axh_image   = "gfx/vehicles/axh-bracket.tga";
+            AuxiliaryXhairs[0].axh_scale   = 0.5;
+
+            // Gunner1
+            AuxiliaryXhairs[1].axh_image   = "gfx/vehicles/axh-target.tga";
+            AuxiliaryXhairs[1].axh_scale   = 0.75;
+
+            // Gunner2
+            AuxiliaryXhairs[2].axh_image   = "gfx/vehicles/axh-target.tga";
+            AuxiliaryXhairs[2].axh_scale   = 0.75;
+            break;
+        case HUD_BUMBLEBEE_GUN:
+            // Plasma cannons
+            AuxiliaryXhairs[0].axh_image   = "gfx/vehicles/axh-bracket.tga";
+            AuxiliaryXhairs[0].axh_scale   = 0.25;
+            // Raygun
+            AuxiliaryXhairs[1].axh_image   = "gfx/vehicles/axh-bracket.tga";
+            AuxiliaryXhairs[1].axh_scale   = 0.25;
+            break;
+    }
+}
+#define HUD_GETSTATS \
+    int vh_health       = getstati(STAT_VEHICLESTAT_HEALTH);  \
+       float shield        = getstati(STAT_VEHICLESTAT_SHIELD);  \
+       noref int energy    = getstati(STAT_VEHICLESTAT_ENERGY);  \
+       noref float ammo1   = getstati(STAT_VEHICLESTAT_AMMO1);   \
+       noref float reload1 = getstati(STAT_VEHICLESTAT_RELOAD1); \
+       noref int ammo2     = getstati(STAT_VEHICLESTAT_AMMO2);   \
+       noref int reload2   = getstati(STAT_VEHICLESTAT_RELOAD2);
+
+void CSQC_BUMBLE_HUD()
+{
+/*
+    drawpic(hudloc, waki_s, picsize, '1 1 1', shield, DRAWFLAG_NORMAL);
+    drawpic(hudloc, waki_b, picsize, '0 1 0' * health + '1 0 0'  * (1 - health), 1, DRAWFLAG_NORMAL);
+    drawpic(hudloc, waki_r, picsize, '1 1 1' * reload1 + '1 0 0' * (1 - reload1), 1, DRAWFLAG_NORMAL);
+    drawpic(hudloc, waki_e, picsize, '1 1 1' * energy + '1 0 0'  * (1 - energy), 1, DRAWFLAG_NORMAL);
+*/
+       if(autocvar_r_letterbox)
+        return;
+
+    vector picsize, hudloc = '0 0 0', pic2size, picloc;
+
+    // Fetch health & ammo stats
+       HUD_GETSTATS
+
+    picsize = draw_getimagesize(hud_bg) * autocvar_cl_vehicles_hudscale;
+    hudloc.y = vid_conheight - picsize.y;
+    hudloc.x = vid_conwidth * 0.5 - picsize.x * 0.5;
+
+    drawpic(hudloc, hud_bg, picsize, '1 1 1', autocvar_cl_vehicles_hudalpha, DRAWFLAG_NORMAL);
+
+    shield  *= 0.01;
+    vh_health  *= 0.01;
+    energy  *= 0.01;
+    reload1 *= 0.01;
+
+    pic2size = draw_getimagesize(bumb_ico) * (autocvar_cl_vehicles_hudscale * 0.8);
+    picloc = picsize * 0.5 - pic2size * 0.5;
+
+    if(vh_health < 0.25)
+        drawpic(hudloc + picloc, bumb_ico, pic2size,  '1 0 0' + '0 1 1' * sin(time * 8),  1, DRAWFLAG_NORMAL);
+    else
+        drawpic(hudloc + picloc, bumb_ico, pic2size,  '1 1 1' * vh_health  + '1 0 0' * (1 - vh_health),  1, DRAWFLAG_NORMAL);
+
+    drawpic(hudloc + picloc, bumb_lgun, pic2size, '1 1 1' * energy   + '1 0 0' * (1 - energy),   1, DRAWFLAG_NORMAL);
+    drawpic(hudloc + picloc, bumb_lgun, pic2size, '1 1 1' * energy   + '1 0 0' * (1 - energy),   1, DRAWFLAG_NORMAL);
+    drawpic(hudloc + picloc, hud_sh, pic2size,  '1 1 1', shield, DRAWFLAG_NORMAL);
+
+// Health bar
+    picsize = draw_getimagesize(hud_hp_bar) * autocvar_cl_vehicles_hudscale;
+    picloc = '69 69 0' * autocvar_cl_vehicles_hudscale;
+    drawsetcliparea(hudloc.x + picloc.x + (picsize.x * (1 - vh_health)), 0, vid_conwidth, vid_conheight);
+    drawpic(hudloc + picloc, hud_hp_bar, picsize, '1 1 1', 1 , DRAWFLAG_NORMAL);
+    drawresetcliparea();
+// ..  and icon
+    picsize = draw_getimagesize(hud_hp_ico) * autocvar_cl_vehicles_hudscale;
+    picloc = '37 65 0' * autocvar_cl_vehicles_hudscale;
+    if(vh_health < 0.25)
+    {
+        if(alarm1time < time)
+        {
+            alarm1time = time + 2;
+            sound(self, CH_PAIN_SINGLE, "vehicles/alarm.wav", VOL_BASEVOICE, ATTEN_NONE);
+        }
+
+        drawpic(hudloc + picloc, hud_hp_ico, picsize, '1 0 0' + '0 1 1' * sin(time * 8), 1, DRAWFLAG_NORMAL);
+    }
+    else
+    {
+        drawpic(hudloc + picloc, hud_hp_ico, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
+        if(alarm1time)
+        {
+            sound(self, CH_PAIN_SINGLE, "misc/null.wav", VOL_BASEVOICE, ATTEN_NONE);
+            alarm1time = 0;
+        }
+    }
+
+// Shield bar
+    picsize = draw_getimagesize(hud_sh_bar) * autocvar_cl_vehicles_hudscale;
+    picloc = '69 140 0' * autocvar_cl_vehicles_hudscale;
+    drawsetcliparea(hudloc.x + picloc.x + (picsize.x * (1 - shield)), 0, vid_conwidth, vid_conheight);
+    drawpic(hudloc + picloc, hud_sh_bar, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
+    drawresetcliparea();
+// ..  and icon
+    picloc = '40 136 0' * autocvar_cl_vehicles_hudscale;
+    picsize = draw_getimagesize(hud_sh_ico) * autocvar_cl_vehicles_hudscale;
+    if(shield < 0.25)
+    {
+        if(alarm2time < time)
+        {
+            alarm2time = time + 1;
+            sound(self, CH_TRIGGER_SINGLE, "vehicles/alarm_shield.wav", VOL_BASEVOICE, ATTEN_NONE);
+        }
+        drawpic(hudloc + picloc, hud_sh_ico, picsize, '1 0 0' + '0 1 1' * sin(time * 8), 1, DRAWFLAG_NORMAL);
+    }
+    else
+    {
+        drawpic(hudloc + picloc, hud_sh_ico, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
+        if(alarm2time)
+        {
+            sound(self, CH_TRIGGER_SINGLE, "misc/null.wav", VOL_BASEVOICE, ATTEN_NONE);
+            alarm2time = 0;
+        }
+    }
+
+       ammo1 *= 0.01;
+       ammo2 *= 0.01;
+
+// Gunner1 bar
+    picsize = draw_getimagesize(hud_ammo1_bar) * autocvar_cl_vehicles_hudscale;
+    picloc = '450 69 0' * autocvar_cl_vehicles_hudscale;
+    drawsetcliparea(hudloc.x + picloc.x, picloc.y, picsize.x * ammo1, vid_conheight);
+    drawpic(hudloc + picloc, hud_ammo1_bar, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
+    drawresetcliparea();
+
+// Right gunner slot occupied?
+       if(!AuxiliaryXhairs[1].draw2d)
+       {
+               shield = (picsize.x * 0.5) - (0.5 * stringwidth(_("No right gunner!"), false, '1 0 0' * picsize.y + '0 1 0' * picsize.y));
+               drawfill(hudloc + picloc - '0.2 0.2 0', picsize + '0.4 0.4 0', '0.25 0.25 0.25', 0.75, DRAWFLAG_NORMAL);
+               drawstring(hudloc + picloc + '1 0 0' * shield, _("No right gunner!"), '1 0 0' * picsize.y + '0 1 0' * picsize.y, '1 0 0' + '0 1 1' * sin(time * 10), 1, DRAWFLAG_NORMAL);
+       }
+
+// ..  and icon
+    picsize = 1.5 * draw_getimagesize(hud_energy) * autocvar_cl_vehicles_hudscale;
+    picloc = '664 60 0' * autocvar_cl_vehicles_hudscale;
+    if(ammo1 < 0.2)
+        drawpic(hudloc + picloc, hud_energy, picsize, '1 0 0' + '0 1 1' * sin(time * 8), 1, DRAWFLAG_NORMAL);
+    else
+        drawpic(hudloc + picloc, hud_energy, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
+
+// Gunner2 bar
+    picsize = draw_getimagesize(hud_ammo2_bar) * autocvar_cl_vehicles_hudscale;
+    picloc = '450 140 0' * autocvar_cl_vehicles_hudscale;
+    drawsetcliparea(hudloc.x + picloc.x, picloc.y, picsize.x * ammo2, vid_conheight);
+    drawpic(hudloc + picloc, hud_ammo2_bar, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
+    drawresetcliparea();
+// Left gunner slot occupied?
+       if(!AuxiliaryXhairs[2].draw2d)
+       {
+               shield = (picsize.x * 0.5) - (0.5 * stringwidth(_("No left gunner!"), false, '1 0 0' * picsize.y + '0 1 0' * picsize.y));
+               drawfill(hudloc + picloc - '0.2 0.2 0', picsize + '0.4 0.4 0', '0.25 0.25 0.25', 0.75, DRAWFLAG_NORMAL);
+               drawstring(hudloc + picloc + '1 0 0' * shield, _("No left gunner!"), '1 0 0' * picsize.y + '0 1 0' * picsize.y, '1 0 0' + '0 1 1' * sin(time * 10), 1, DRAWFLAG_NORMAL);
+       }
+
+// ..  and icon
+    picsize = 1.5 * draw_getimagesize(hud_energy) * autocvar_cl_vehicles_hudscale;
+    picloc = '664 130 0' * autocvar_cl_vehicles_hudscale;
+    if(ammo2 < 0.2)
+        drawpic(hudloc + picloc, hud_energy, picsize, '1 0 0' + '0 1 1' * sin(time * 8), 1, DRAWFLAG_NORMAL);
+    else
+        drawpic(hudloc + picloc, hud_energy, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
+
+       if (scoreboard_showscores)
+               HUD_DrawScoreboard();
+    else
+    {
+        picsize = draw_getimagesize(waki_xhair);
+        picsize.x *= 0.5;
+        picsize.y *= 0.5;
+        drawpic('0.5 0 0' * (vid_conwidth - picsize.x) + '0 0.5 0' * (vid_conheight - picsize.y), waki_xhair, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
+    }
+
+}
+
+void CSQC_BUMBLE_GUN_HUD()
+{
+
+       if(autocvar_r_letterbox)
+        return;
+
+    vector picsize, hudloc = '0 0 0', pic2size, picloc;
+
+    // Fetch health & ammo stats
+       HUD_GETSTATS
+
+    picsize = draw_getimagesize(hud_bg) * autocvar_cl_vehicles_hudscale;
+    hudloc.y = vid_conheight - picsize.y;
+    hudloc.x = vid_conwidth * 0.5 - picsize.x * 0.5;
+
+    drawpic(hudloc, hud_bg, picsize, '1 1 1', autocvar_cl_vehicles_hudalpha, DRAWFLAG_NORMAL);
+
+    shield  *= 0.01;
+    vh_health  *= 0.01;
+    energy  *= 0.01;
+    reload1 *= 0.01;
+
+    pic2size = draw_getimagesize(bumb_gun_ico) * (autocvar_cl_vehicles_hudscale * 0.8);
+    picloc = picsize * 0.5 - pic2size * 0.5;
+
+    if(vh_health < 0.25)
+        drawpic(hudloc + picloc, bumb_gun_ico, pic2size,  '1 0 0' + '0 1 1' * sin(time * 8),  1, DRAWFLAG_NORMAL);
+    else
+        drawpic(hudloc + picloc, bumb_gun_ico, pic2size,  '1 1 1' * vh_health  + '1 0 0' * (1 - vh_health),  1, DRAWFLAG_NORMAL);
+
+    drawpic(hudloc + picloc, bumb_gun_gun, pic2size, '1 1 1' * energy   + '1 0 0' * (1 - energy),   1, DRAWFLAG_NORMAL);
+    drawpic(hudloc + picloc, hud_sh, pic2size,  '1 1 1', shield, DRAWFLAG_NORMAL);
+
+// Health bar
+    picsize = draw_getimagesize(hud_hp_bar) * autocvar_cl_vehicles_hudscale;
+    picloc = '69 69 0' * autocvar_cl_vehicles_hudscale;
+    drawsetcliparea(hudloc.x + picloc.x + (picsize.x * (1 - vh_health)), 0, vid_conwidth, vid_conheight);
+    drawpic(hudloc + picloc, hud_hp_bar, picsize, '1 1 1', 1 , DRAWFLAG_NORMAL);
+    drawresetcliparea();
+// ..  and icon
+    picsize = draw_getimagesize(hud_hp_ico) * autocvar_cl_vehicles_hudscale;
+    picloc = '37 65 0' * autocvar_cl_vehicles_hudscale;
+    if(vh_health < 0.25)
+    {
+        if(alarm1time < time)
+        {
+            alarm1time = time + 2;
+            sound(self, CH_PAIN_SINGLE, "vehicles/alarm.wav", VOL_BASEVOICE, ATTEN_NONE);
+        }
+
+        drawpic(hudloc + picloc, hud_hp_ico, picsize, '1 0 0' + '0 1 1' * sin(time * 8), 1, DRAWFLAG_NORMAL);
+    }
+    else
+    {
+        drawpic(hudloc + picloc, hud_hp_ico, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
+        if(alarm1time)
+        {
+            sound(self, CH_PAIN_SINGLE, "misc/null.wav", VOL_BASEVOICE, ATTEN_NONE);
+            alarm1time = 0;
+        }
+    }
+
+// Shield bar
+    picsize = draw_getimagesize(hud_sh_bar) * autocvar_cl_vehicles_hudscale;
+    picloc = '69 140 0' * autocvar_cl_vehicles_hudscale;
+    drawsetcliparea(hudloc.x + picloc.x + (picsize.x * (1 - shield)), 0, vid_conwidth, vid_conheight);
+    drawpic(hudloc + picloc, hud_sh_bar, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
+    drawresetcliparea();
+// ..  and icon
+    picloc = '40 136 0' * autocvar_cl_vehicles_hudscale;
+    picsize = draw_getimagesize(hud_sh_ico) * autocvar_cl_vehicles_hudscale;
+    if(shield < 0.25)
+    {
+        if(alarm2time < time)
+        {
+            alarm2time = time + 1;
+            sound(self, CH_TRIGGER_SINGLE, "vehicles/alarm_shield.wav", VOL_BASEVOICE, ATTEN_NONE);
+        }
+        drawpic(hudloc + picloc, hud_sh_ico, picsize, '1 0 0' + '0 1 1' * sin(time * 8), 1, DRAWFLAG_NORMAL);
+    }
+    else
+    {
+        drawpic(hudloc + picloc, hud_sh_ico, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
+        if(alarm2time)
+        {
+            sound(self, CH_TRIGGER_SINGLE, "misc/null.wav", VOL_BASEVOICE, ATTEN_NONE);
+            alarm2time = 0;
+        }
+    }
+
+// Gun bar
+    picsize = draw_getimagesize(hud_ammo1_bar) * autocvar_cl_vehicles_hudscale;
+    picloc = '450 69 0' * autocvar_cl_vehicles_hudscale;
+    drawsetcliparea(hudloc.x + picloc.x, picloc.y, picsize.x * energy, vid_conheight);
+    drawpic(hudloc + picloc, hud_ammo1_bar, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
+    drawresetcliparea();
+
+// ..  and icon
+    picsize = 1.5 * draw_getimagesize(hud_energy) * autocvar_cl_vehicles_hudscale;
+    picloc = '664 60 0' * autocvar_cl_vehicles_hudscale;
+    if(energy < 0.2)
+        drawpic(hudloc + picloc, hud_energy, picsize, '1 0 0' + '0 1 1' * sin(time * 8), 1, DRAWFLAG_NORMAL);
+    else
+        drawpic(hudloc + picloc, hud_energy, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
+
+       if (scoreboard_showscores)
+               HUD_DrawScoreboard();
+    /*
+    else
+    {
+        picsize = draw_getimagesize(waki_xhair);
+        picsize_x *= 0.5;
+        picsize_y *= 0.5;
+
+
+        drawpic('0.5 0 0' * (vid_conwidth - picsize_x) + '0 0.5 0' * (vid_conheight - picsize_y), waki_xhair, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
+    }
+    */
+}
+
+
+
+void CSQC_SPIDER_HUD()
+{
+       if(autocvar_r_letterbox)
+        return;
+
+    vector picsize, hudloc = '0 0 0', pic2size, picloc;
+    int i;
+
+    // Fetch health & ammo stats
+       HUD_GETSTATS
+
+    picsize = draw_getimagesize(hud_bg) * autocvar_cl_vehicles_hudscale;
+    hudloc.y = vid_conheight - picsize.y;
+    hudloc.x = vid_conwidth * 0.5 - picsize.x * 0.5;
+
+    drawpic(hudloc, hud_bg, picsize, '1 1 1', autocvar_cl_vehicles_hudalpha, DRAWFLAG_NORMAL);
+
+    ammo1   *= 0.01;
+    shield  *= 0.01;
+    vh_health  *= 0.01;
+    reload2 *= 0.01;
+
+    pic2size = draw_getimagesize(spider_ico) * (autocvar_cl_vehicles_hudscale * 0.8);
+    picloc = picsize * 0.5 - pic2size * 0.5;
+    if(vh_health < 0.25)
+        drawpic(hudloc + picloc, spider_ico, pic2size,  '1 0 0' + '0 1 1' * sin(time * 8),  1, DRAWFLAG_NORMAL);
+    else
+        drawpic(hudloc + picloc, spider_ico, pic2size,  '1 1 1' * vh_health  + '1 0 0' * (1 - vh_health),  1, DRAWFLAG_NORMAL);
+    drawpic(hudloc + picloc, spider_rkt, pic2size,  '1 1 1' * reload2 + '1 0 0' * (1 - reload2), 1, DRAWFLAG_NORMAL);
+    drawpic(hudloc + picloc, spider_mgun, pic2size, '1 1 1' * ammo1   + '1 0 0' * (1 - ammo1),   1, DRAWFLAG_NORMAL);
+    drawpic(hudloc + picloc, hud_sh, pic2size,  '1 1 1', shield, DRAWFLAG_NORMAL);
+
+// Health bar
+    picsize = draw_getimagesize(hud_hp_bar) * autocvar_cl_vehicles_hudscale;
+    picloc = '69 69 0' * autocvar_cl_vehicles_hudscale;
+    drawsetcliparea(hudloc.x + picloc.x + (picsize.x * (1 - vh_health)), 0, vid_conwidth, vid_conheight);
+    drawpic(hudloc + picloc, hud_hp_bar, picsize, '1 1 1', 1 , DRAWFLAG_NORMAL);
+    drawresetcliparea();
+// ..  and icon
+    picsize = draw_getimagesize(hud_hp_ico) * autocvar_cl_vehicles_hudscale;
+    picloc = '37 65 0' * autocvar_cl_vehicles_hudscale;
+    if(vh_health < 0.25)
+    {
+        if(alarm1time < time)
+        {
+            alarm1time = time + 2;
+            sound(self, CH_PAIN_SINGLE, "vehicles/alarm.wav", VOL_BASEVOICE, ATTEN_NONE);
+        }
+        drawpic(hudloc + picloc, hud_hp_ico, picsize, '1 0 0' + '0 1 1' * sin(time * 8), 1, DRAWFLAG_NORMAL);
+    }
+    else
+    {
+        drawpic(hudloc + picloc, hud_hp_ico, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
+        if(alarm1time)
+        {
+            sound(self, CH_PAIN_SINGLE, "misc/null.wav", VOL_BASEVOICE, ATTEN_NONE);
+            alarm1time = 0;
+        }
+    }
+// Shield bar
+    picsize = draw_getimagesize(hud_sh_bar) * autocvar_cl_vehicles_hudscale;
+    picloc = '69 140 0' * autocvar_cl_vehicles_hudscale;
+    drawsetcliparea(hudloc.x + picloc.x + (picsize.x * (1 - shield)), 0, vid_conwidth, vid_conheight);
+    drawpic(hudloc + picloc, hud_sh_bar, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
+    drawresetcliparea();
+// ..  and icon
+    picloc = '40 136 0' * autocvar_cl_vehicles_hudscale;
+    picsize = draw_getimagesize(hud_sh_ico) * autocvar_cl_vehicles_hudscale;
+    if(shield < 0.25)
+    {
+        if(alarm2time < time)
+        {
+            alarm2time = time + 1;
+            sound(self, CH_TRIGGER_SINGLE, "vehicles/alarm_shield.wav", VOL_BASEVOICE, ATTEN_NONE);
+        }
+        drawpic(hudloc + picloc, hud_sh_ico, picsize, '1 0 0' + '0 1 1' * sin(time * 8), 1, DRAWFLAG_NORMAL);
+    }
+    else
+    {
+        drawpic(hudloc + picloc, hud_sh_ico, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
+        if(alarm2time)
+        {
+            sound(self, CH_TRIGGER_SINGLE, "misc/null.wav", VOL_BASEVOICE, ATTEN_NONE);
+            alarm2time = 0;
+        }
+    }
+
+// Minigun bar
+    picsize = draw_getimagesize(hud_ammo1_bar) * autocvar_cl_vehicles_hudscale;
+    picloc = '450 69 0' * autocvar_cl_vehicles_hudscale;
+    drawsetcliparea(hudloc.x + picloc.x, picloc.y, picsize.x * ammo1, vid_conheight);
+    drawpic(hudloc + picloc, hud_ammo1_bar, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
+    drawresetcliparea();
+// ..  and icon
+    picsize = draw_getimagesize(hud_ammo1_ico) * autocvar_cl_vehicles_hudscale;
+    picloc = '664 60 0' * autocvar_cl_vehicles_hudscale;
+    if(ammo1 < 0.2)
+        drawpic(hudloc + picloc, hud_ammo1_ico, picsize, '1 0 0' + '0 1 1' * sin(time * 8), 1, DRAWFLAG_NORMAL);
+    else
+        drawpic(hudloc + picloc, hud_ammo1_ico, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
+
+// Rocket ammo bar
+    picsize = draw_getimagesize(hud_ammo2_bar) * autocvar_cl_vehicles_hudscale;
+    ammo1 = picsize.x / 8;
+    picloc = '450 140 0' * autocvar_cl_vehicles_hudscale;
+    drawsetcliparea(hudloc.x + picloc.x, hudloc.y + picloc.y, picsize.x * reload2, vid_conheight);
+    drawpic(hudloc + picloc, hud_ammo2_bar, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
+    drawresetcliparea();
+
+// ..  and icons
+    pic2size = 0.35 * draw_getimagesize(hud_ammo2_ico) * autocvar_cl_vehicles_hudscale;
+    picloc.x -= pic2size.x;
+    picloc.y += pic2size.y * 2.25;
+    if(ammo2 == 9)
+    {
+        for(i = 1; i < 9; ++i)
+        {
+            picloc.x += ammo1;
+            drawpic(hudloc + picloc, hud_ammo2_ico, pic2size, ((8 * reload2 <= i) ? '0 0 0' : '1 1 1'), 0.75, DRAWFLAG_NORMAL);
+        }
+    }
+    else
+    {
+        for(i = 1; i < 9; ++i)
+        {
+            picloc.x += ammo1;
+            drawpic(hudloc + picloc, hud_ammo2_ico, pic2size, ((i >= ammo2) ? '1 1 1' : '0 0 0'), 0.75, DRAWFLAG_NORMAL);
+        }
+    }
+    pic2size = draw_getimagesize(hud_ammo2_ico) * autocvar_cl_vehicles_hudscale;
+    picloc = '664 130 0' * autocvar_cl_vehicles_hudscale;
+    if(ammo2 == 9)
+        drawpic(hudloc + picloc, hud_ammo2_ico, pic2size, '1 0 0' + '0 1 1' * sin(time * 8), 1, DRAWFLAG_NORMAL);
+    else
+        drawpic(hudloc + picloc, hud_ammo2_ico, pic2size, '1 1 1', 1, DRAWFLAG_NORMAL);
+
+       if (scoreboard_showscores)
+               HUD_DrawScoreboard();
+    else
+    {
+        switch(weapon2mode)
+        {
+            case SBRM_VOLLY:
+                spider_xhair = "gfx/vehicles/axh-bracket.tga";
+                break;
+            case SBRM_GUIDE:
+                spider_xhair = "gfx/vehicles/axh-cross.tga";
+                break;
+            case SBRM_ARTILLERY:
+                spider_xhair = "gfx/vehicles/axh-tag.tga";
+                break;
+            default:
+                spider_xhair= "gfx/vehicles/axh-tag.tga";
+        }
+
+        picsize = draw_getimagesize(spider_xhair);
+        picsize.x *= autocvar_cl_vehicle_spiderbot_cross_size;
+        picsize.y *= autocvar_cl_vehicle_spiderbot_cross_size;
+
+        drawpic('0.5 0 0' * (vid_conwidth - picsize.x) + '0 0.5 0' * (vid_conheight - picsize.y), spider_xhair, picsize, '1 1 1', autocvar_cl_vehicle_spiderbot_cross_alpha, DRAWFLAG_ADDITIVE);
+    }
+}
+
+void CSQC_RAPTOR_HUD()
+{
+       if(autocvar_r_letterbox)
+        return;
+
+    vector picsize, hudloc = '0 0 0', pic2size, picloc;
+
+    // Fetch health & ammo stats
+       HUD_GETSTATS
+
+    picsize = draw_getimagesize(hud_bg) * autocvar_cl_vehicles_hudscale;
+    hudloc.y = vid_conheight - picsize.y;
+    hudloc.x = vid_conwidth * 0.5 - picsize.x * 0.5;
+
+    drawpic(hudloc, hud_bg, picsize, '1 1 1', autocvar_cl_vehicles_hudalpha, DRAWFLAG_NORMAL);
+
+    ammo1   *= 0.01;
+    ammo2   *= 0.01;
+    shield  *= 0.01;
+    vh_health  *= 0.01;
+    energy  *= 0.01;
+    reload1 = reload2 * 0.01;
+    //reload2 *= 0.01;
+
+    pic2size = draw_getimagesize(spider_ico) * (autocvar_cl_vehicles_hudscale * 0.8);
+    picloc = picsize * 0.5 - pic2size * 0.5;
+    if(vh_health < 0.25)
+        drawpic(hudloc + picloc, raptor_ico, pic2size,  '1 0 0' + '0 1 1' * sin(time * 8),  1, DRAWFLAG_NORMAL);
+    else
+        drawpic(hudloc + picloc, raptor_ico, pic2size,  '1 1 1' * vh_health  + '1 0 0' * (1 - vh_health),  1, DRAWFLAG_NORMAL);
+    drawpic(hudloc + picloc, raptor_bomb, pic2size,  '1 1 1' * reload1 + '1 0 0' * (1 - reload1), 1, DRAWFLAG_NORMAL);
+    drawpic(hudloc + picloc, raptor_gun, pic2size, '1 1 1' * energy   + '1 0 0' * (1 - energy),   1, DRAWFLAG_NORMAL);
+    drawpic(hudloc + picloc, hud_sh, pic2size,  '1 1 1', shield, DRAWFLAG_NORMAL);
+
+// Health bar
+    picsize = draw_getimagesize(hud_hp_bar) * autocvar_cl_vehicles_hudscale;
+    picloc = '69 69 0' * autocvar_cl_vehicles_hudscale;
+    drawsetcliparea(hudloc.x + picloc.x + (picsize.x * (1 - vh_health)), 0, vid_conwidth, vid_conheight);
+    drawpic(hudloc + picloc, hud_hp_bar, picsize, '1 1 1', 1 , DRAWFLAG_NORMAL);
+    drawresetcliparea();
+// ..  and icon
+    picsize = draw_getimagesize(hud_hp_ico) * autocvar_cl_vehicles_hudscale;
+    picloc = '37 65 0' * autocvar_cl_vehicles_hudscale;
+    if(vh_health < 0.25)
+    {
+        if(alarm1time < time)
+        {
+            alarm1time = time + 2;
+            sound(self, CH_PAIN_SINGLE, "vehicles/alarm.wav", VOL_BASEVOICE, ATTEN_NONE);
+        }
+
+        drawpic(hudloc + picloc, hud_hp_ico, picsize, '1 0 0' + '0 1 1' * sin(time * 8), 1, DRAWFLAG_NORMAL);
+    }
+    else
+    {
+        drawpic(hudloc + picloc, hud_hp_ico, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
+        if(alarm1time)
+        {
+            sound(self, CH_PAIN_SINGLE, "misc/null.wav", VOL_BASEVOICE, ATTEN_NONE);
+            alarm1time = 0;
+        }
+    }
+
+// Shield bar
+    picsize = draw_getimagesize(hud_sh_bar) * autocvar_cl_vehicles_hudscale;
+    picloc = '69 140 0' * autocvar_cl_vehicles_hudscale;
+    drawsetcliparea(hudloc.x + picloc.x + (picsize.x * (1 - shield)), 0, vid_conwidth, vid_conheight);
+    drawpic(hudloc + picloc, hud_sh_bar, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
+    drawresetcliparea();
+// ..  and icon
+    picloc = '40 136 0' * autocvar_cl_vehicles_hudscale;
+    picsize = draw_getimagesize(hud_sh_ico) * autocvar_cl_vehicles_hudscale;
+    if(shield < 0.25)
+    {
+        if(alarm2time < time)
+        {
+            alarm2time = time + 1;
+            sound(self, CH_TRIGGER_SINGLE, "vehicles/alarm_shield.wav", VOL_BASEVOICE, ATTEN_NONE);
+        }
+        drawpic(hudloc + picloc, hud_sh_ico, picsize, '1 0 0' + '0 1 1' * sin(time * 8), 1, DRAWFLAG_NORMAL);
+    }
+    else
+    {
+        drawpic(hudloc + picloc, hud_sh_ico, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
+        if(alarm2time)
+        {
+            sound(self, CH_TRIGGER_SINGLE, "misc/null.wav", VOL_BASEVOICE, ATTEN_NONE);
+            alarm2time = 0;
+        }
+    }
+
+// Gun bar
+    picsize = draw_getimagesize(hud_ammo1_bar) * autocvar_cl_vehicles_hudscale;
+    picloc = '450 69 0' * autocvar_cl_vehicles_hudscale;
+    drawsetcliparea(hudloc.x + picloc.x, picloc.y, picsize.x * energy, vid_conheight);
+    drawpic(hudloc + picloc, hud_ammo1_bar, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
+    drawresetcliparea();
+// ..  and icon
+    picsize = draw_getimagesize(hud_ammo1_ico) * autocvar_cl_vehicles_hudscale;
+    picloc = '664 60 0' * autocvar_cl_vehicles_hudscale;
+    if(energy < 0.2)
+        drawpic(hudloc + picloc, hud_ammo1_ico, picsize, '1 0 0' + '0 1 1' * sin(time * 8), 1, DRAWFLAG_NORMAL);
+    else
+        drawpic(hudloc + picloc, hud_ammo1_ico, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
+
+// Bomb bar
+    picsize = draw_getimagesize(hud_ammo2_bar) * autocvar_cl_vehicles_hudscale;
+    picloc = '450 140 0' * autocvar_cl_vehicles_hudscale;
+    drawsetcliparea(hudloc.x + picloc.x, hudloc.y + picloc.y, picsize.x * reload1, vid_conheight);
+    drawpic(hudloc + picloc, hud_ammo2_bar, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
+    drawresetcliparea();
+// ..  and icon
+    pic2size = draw_getimagesize(hud_ammo2_ico) * autocvar_cl_vehicles_hudscale;
+    picloc = '664 130 0' * autocvar_cl_vehicles_hudscale;
+    if(reload1 != 1)
+        drawpic(hudloc + picloc, hud_ammo2_ico, pic2size, '1 0 0' + '0 1 1' * sin(time * 8), 1, DRAWFLAG_NORMAL);
+    else
+        drawpic(hudloc + picloc, hud_ammo2_ico, pic2size, '1 1 1', 1, DRAWFLAG_NORMAL);
+
+    if(weapon2mode == RSM_FLARE)
+    {
+        raptor_xhair =  "gfx/vehicles/axh-bracket.tga";
+    }
+    else
+    {
+        raptor_xhair =  "gfx/vehicles/axh-ring.tga";
+
+        // Bombing crosshair
+        if(!dropmark)
+        {
+            dropmark = spawn();
+            dropmark.owner = self;
+            dropmark.gravity = 1;
+        }
+
+        if(reload2 == 100)
+        {
+            vector where;
+
+            setorigin(dropmark, pmove_org);
+            dropmark.velocity = pmove_vel;
+            tracetoss(dropmark, self);
+
+            where = project_3d_to_2d(trace_endpos);
+
+            setorigin(dropmark, trace_endpos);
+            picsize = draw_getimagesize(raptor_drop) * 0.2;
+
+            if (!(where.z < 0 || where.x < 0 || where.y < 0 || where.x > vid_conwidth || where.y > vid_conheight))
+            {
+                where.x -= picsize.x * 0.5;
+                where.y -= picsize.y * 0.5;
+                where.z = 0;
+                drawpic(where, raptor_drop, picsize, '0 2 0', 1, DRAWFLAG_ADDITIVE);
+            }
+            dropmark.cnt = time + 5;
+        }
+        else
+        {
+            vector where;
+            if(dropmark.cnt > time)
+            {
+                where = project_3d_to_2d(dropmark.origin);
+                picsize = draw_getimagesize(raptor_drop) * 0.25;
+
+                if (!(where.z < 0 || where.x < 0 || where.y < 0 || where.x > vid_conwidth || where.y > vid_conheight))
+                {
+                    where.x -= picsize.x * 0.5;
+                    where.y -= picsize.y * 0.5;
+                    where.z = 0;
+                    drawpic(where, raptor_drop, picsize, '2 0 0', 1, DRAWFLAG_ADDITIVE);
+                }
+            }
+        }
+    }
+
+       if (scoreboard_showscores)
+               HUD_DrawScoreboard();
+    else
+    {
+        picsize = draw_getimagesize(raptor_xhair);
+        picsize.x *= 0.5;
+        picsize.y *= 0.5;
+
+        drawpic('0.5 0 0' * (vid_conwidth - picsize.x) + '0 0.5 0' * (vid_conheight - picsize.y), raptor_xhair, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
+    }
+}
+
+void CSQC_WAKIZASHI_HUD()
+{
+/*
+    drawpic(hudloc, waki_s, picsize, '1 1 1', shield, DRAWFLAG_NORMAL);
+    drawpic(hudloc, waki_b, picsize, '0 1 0' * health + '1 0 0'  * (1 - health), 1, DRAWFLAG_NORMAL);
+    drawpic(hudloc, waki_r, picsize, '1 1 1' * reload1 + '1 0 0' * (1 - reload1), 1, DRAWFLAG_NORMAL);
+    drawpic(hudloc, waki_e, picsize, '1 1 1' * energy + '1 0 0'  * (1 - energy), 1, DRAWFLAG_NORMAL);
+*/
+       if(autocvar_r_letterbox)
+        return;
+
+    vector picsize, hudloc = '0 0 0', pic2size, picloc;
+
+    // Fetch health & ammo stats
+       HUD_GETSTATS
+
+    picsize = draw_getimagesize(hud_bg) * autocvar_cl_vehicles_hudscale;
+    hudloc.y = vid_conheight - picsize.y;
+    hudloc.x = vid_conwidth * 0.5 - picsize.x * 0.5;
+
+    drawpic(hudloc, hud_bg, picsize, '1 1 1', autocvar_cl_vehicles_hudalpha, DRAWFLAG_NORMAL);
+
+    shield  *= 0.01;
+    vh_health  *= 0.01;
+    energy  *= 0.01;
+    reload1 *= 0.01;
+
+    pic2size = draw_getimagesize(spider_ico) * (autocvar_cl_vehicles_hudscale * 0.8);
+    picloc = picsize * 0.5 - pic2size * 0.5;
+    if(vh_health < 0.25)
+        drawpic(hudloc + picloc, waki_ico, pic2size,  '1 0 0' + '0 1 1' * sin(time * 8),  1, DRAWFLAG_NORMAL);
+    else
+        drawpic(hudloc + picloc, waki_ico, pic2size,  '1 1 1' * vh_health  + '1 0 0' * (1 - vh_health),  1, DRAWFLAG_NORMAL);
+    drawpic(hudloc + picloc, waki_eng, pic2size, '1 1 1' * energy   + '1 0 0' * (1 - energy),   1, DRAWFLAG_NORMAL);
+    drawpic(hudloc + picloc, waki_gun, pic2size, '1 1 1' * energy   + '1 0 0' * (1 - energy),   1, DRAWFLAG_NORMAL);
+    drawpic(hudloc + picloc, waki_rkt, pic2size,  '1 1 1' * reload1 + '1 0 0' * (1 - reload1), 1, DRAWFLAG_NORMAL);
+    drawpic(hudloc + picloc, hud_sh, pic2size,  '1 1 1', shield, DRAWFLAG_NORMAL);
+
+// Health bar
+    picsize = draw_getimagesize(hud_hp_bar) * autocvar_cl_vehicles_hudscale;
+    picloc = '69 69 0' * autocvar_cl_vehicles_hudscale;
+    drawsetcliparea(hudloc.x + picloc.x + (picsize.x * (1 - vh_health)), 0, vid_conwidth, vid_conheight);
+    drawpic(hudloc + picloc, hud_hp_bar, picsize, '1 1 1', 1 , DRAWFLAG_NORMAL);
+    drawresetcliparea();
+// ..  and icon
+    picsize = draw_getimagesize(hud_hp_ico) * autocvar_cl_vehicles_hudscale;
+    picloc = '37 65 0' * autocvar_cl_vehicles_hudscale;
+    if(vh_health < 0.25)
+    {
+        if(alarm1time < time)
+        {
+            alarm1time = time + 2;
+            sound(self, CH_PAIN_SINGLE, "vehicles/alarm.wav", VOL_BASEVOICE, ATTEN_NONE);
+        }
+
+        drawpic(hudloc + picloc, hud_hp_ico, picsize, '1 0 0' + '0 1 1' * sin(time * 8), 1, DRAWFLAG_NORMAL);
+    }
+    else
+    {
+        drawpic(hudloc + picloc, hud_hp_ico, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
+        if(alarm1time)
+        {
+            sound(self, CH_PAIN_SINGLE, "misc/null.wav", VOL_BASEVOICE, ATTEN_NONE);
+            alarm1time = 0;
+        }
+    }
+
+
+// Shield bar
+    picsize = draw_getimagesize(hud_sh_bar) * autocvar_cl_vehicles_hudscale;
+    picloc = '69 140 0' * autocvar_cl_vehicles_hudscale;
+    drawsetcliparea(hudloc.x + picloc.x + (picsize.x * (1 - shield)), 0, vid_conwidth, vid_conheight);
+    drawpic(hudloc + picloc, hud_sh_bar, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
+    drawresetcliparea();
+// ..  and icon
+    picloc = '40 136 0' * autocvar_cl_vehicles_hudscale;
+    picsize = draw_getimagesize(hud_sh_ico) * autocvar_cl_vehicles_hudscale;
+    if(shield < 0.25)
+    {
+        if(alarm2time < time)
+        {
+            alarm2time = time + 1;
+            sound(self, CH_TRIGGER_SINGLE, "vehicles/alarm_shield.wav", VOL_BASEVOICE, ATTEN_NONE);
+        }
+        drawpic(hudloc + picloc, hud_sh_ico, picsize, '1 0 0' + '0 1 1' * sin(time * 8), 1, DRAWFLAG_NORMAL);
+    }
+    else
+    {
+        drawpic(hudloc + picloc, hud_sh_ico, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
+        if(alarm2time)
+        {
+            sound(self, CH_TRIGGER_SINGLE, "misc/null.wav", VOL_BASEVOICE, ATTEN_NONE);
+            alarm2time = 0;
+        }
+    }
+
+// Gun bar
+    picsize = draw_getimagesize(hud_ammo1_bar) * autocvar_cl_vehicles_hudscale;
+    picloc = '450 69 0' * autocvar_cl_vehicles_hudscale;
+    drawsetcliparea(hudloc.x + picloc.x, picloc.y, picsize.x * energy, vid_conheight);
+    drawpic(hudloc + picloc, hud_ammo1_bar, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
+    drawresetcliparea();
+// ..  and icon
+    picsize = draw_getimagesize(hud_ammo1_ico) * autocvar_cl_vehicles_hudscale;
+    picloc = '664 60 0' * autocvar_cl_vehicles_hudscale;
+    if(energy < 0.2)
+        drawpic(hudloc + picloc, hud_ammo1_ico, picsize, '1 0 0' + '0 1 1' * sin(time * 8), 1, DRAWFLAG_NORMAL);
+    else
+        drawpic(hudloc + picloc, hud_ammo1_ico, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
+
+// Bomb bar
+    picsize = draw_getimagesize(hud_ammo2_bar) * autocvar_cl_vehicles_hudscale;
+    picloc = '450 140 0' * autocvar_cl_vehicles_hudscale;
+    drawsetcliparea(hudloc.x + picloc.x, hudloc.y + picloc.y, picsize.x * reload1, vid_conheight);
+    drawpic(hudloc + picloc, hud_ammo2_bar, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
+    drawresetcliparea();
+// ..  and icon
+    pic2size = draw_getimagesize(hud_ammo2_ico) * autocvar_cl_vehicles_hudscale;
+    picloc = '664 130 0' * autocvar_cl_vehicles_hudscale;
+    if(reload1 != 1)
+        drawpic(hudloc + picloc, hud_ammo2_ico, pic2size, '1 0 0' + '0 1 1' * sin(time * 8), 1, DRAWFLAG_NORMAL);
+    else
+        drawpic(hudloc + picloc, hud_ammo2_ico, pic2size, '1 1 1', 1, DRAWFLAG_NORMAL);
+
+       if (scoreboard_showscores)
+               HUD_DrawScoreboard();
+    else
+    {
+        picsize = draw_getimagesize(waki_xhair);
+        picsize.x *= 0.5;
+        picsize.y *= 0.5;
+
+
+        drawpic('0.5 0 0' * (vid_conwidth - picsize.x) + '0 0.5 0' * (vid_conheight - picsize.y), waki_xhair, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
+    }
+}
+
+void Vehicles_Precache()
+{
+       precache_model("models/vehicles/bomblet.md3");
+       precache_model("models/vehicles/clusterbomb.md3");
+       precache_model("models/vehicles/clusterbomb_fragment.md3");
+       precache_model("models/vehicles/rocket01.md3");
+       precache_model("models/vehicles/rocket02.md3");
+
+       precache_sound ("vehicles/alarm.wav");
+       precache_sound ("vehicles/alarm_shield.wav");
+}
+
+void RaptorCBShellfragDraw()
+{
+       if(wasfreed(self))
+               return;
+
+       Movetype_Physics_MatchTicrate(autocvar_cl_gibs_ticrate, autocvar_cl_gibs_sloppy);
+       self.move_avelocity += randomvec() * 15;
+       self.renderflags = 0;
+
+       if(self.cnt < time)
+               self.alpha = bound(0, self.nextthink - time, 1);
+
+       if(self.alpha < ALPHA_MIN_VISIBLE)
+        remove(self);
+}
+
+void RaptorCBShellfragToss(vector _org, vector _vel, vector _ang)
+{
+    entity sfrag;
+
+    sfrag = spawn();
+    setmodel(sfrag, "models/vehicles/clusterbomb_fragment.md3");
+    setorigin(sfrag, _org);
+
+       sfrag.move_movetype = MOVETYPE_BOUNCE;
+       sfrag.gravity = 0.15;
+       sfrag.solid = SOLID_CORPSE;
+
+       sfrag.draw = RaptorCBShellfragDraw;
+
+       sfrag.move_origin = sfrag.origin = _org;
+       sfrag.move_velocity = _vel;
+       sfrag.move_avelocity = prandomvec() * vlen(sfrag.move_velocity);
+       sfrag.angles = self.move_angles = _ang;
+
+       sfrag.move_time = time;
+       sfrag.damageforcescale = 4;
+
+       sfrag.nextthink = time + 3;
+       sfrag.cnt = time + 2;
+       sfrag.alpha = 1;
+    sfrag.drawmask = MASK_NORMAL;
+}
diff --git a/qcsrc/client/vehicles/all.qh b/qcsrc/client/vehicles/all.qh
new file mode 100644 (file)
index 0000000..f92ab82
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef VEHICLES_ALL_H
+#define VEHICLES_ALL_H
+
+void RaptorCBShellfragDraw();
+void RaptorCBShellfragToss(vector _org, vector _vel, vector _ang);
+void Vehicles_Precache();
+void Net_AuXair2(bool bIsNew);
+void Net_VehicleSetup();
+
+void CSQC_WAKIZASHI_HUD();
+void CSQC_SPIDER_HUD();
+void CSQC_RAPTOR_HUD();
+void CSQC_BUMBLE_HUD();
+void CSQC_BUMBLE_GUN_HUD();
+
+#endif
diff --git a/qcsrc/client/vehicles/bumblebee.qc b/qcsrc/client/vehicles/bumblebee.qc
new file mode 100644 (file)
index 0000000..1304d3a
--- /dev/null
@@ -0,0 +1,12 @@
+#include "../damage.qh"
+#include "../defs.qh"
+#include "../gibs.qh"
+#include "../hook.qh"
+#include "../main.qh"
+#include "../wall.qh"
+
+#include "../weapons/projectile.qh"
+
+#include "../../common/movetypes/movetypes.qh"
+
+#include "../../server/vehicles/bumblebee.qc"
diff --git a/qcsrc/client/vehicles/bumblebee.qh b/qcsrc/client/vehicles/bumblebee.qh
new file mode 100644 (file)
index 0000000..411eb36
--- /dev/null
@@ -0,0 +1 @@
+#include "../../server/vehicles/bumblebee.qh"
diff --git a/qcsrc/client/vehicles/vehicles.qc b/qcsrc/client/vehicles/vehicles.qc
deleted file mode 100644 (file)
index 290385e..0000000
+++ /dev/null
@@ -1,1057 +0,0 @@
-#if defined(CSQC)
-    #include "../../dpdefs/csprogsdefs.qh"
-    #include "../defs.qh"
-    #include "../../common/constants.qh"
-    #include "../../common/stats.qh"
-    #include "../../common/util.qh"
-    #include "../../common/buffs.qh"
-    #include "../autocvars.qh"
-    #include "../movetypes.qh"
-    #include "../prandom.qh"
-    #include "../main.qh"
-    #include "vehicles.qh"
-    #include "../../csqcmodellib/cl_model.qh"
-    #include "../../server/t_items.qh"
-#elif defined(MENUQC)
-#elif defined(SVQC)
-#endif
-
-const string hud_bg = "gfx/vehicles/frame.tga";
-const string hud_sh = "gfx/vehicles/vh-shield.tga";
-
-const string hud_hp_bar = "gfx/vehicles/bar_up_left.tga";
-const string hud_hp_ico = "gfx/vehicles/health.tga";
-const string hud_sh_bar = "gfx/vehicles/bar_dwn_left.tga";
-const string hud_sh_ico = "gfx/vehicles/shield.tga";
-
-const string hud_ammo1_bar = "gfx/vehicles/bar_up_right.tga";
-const string hud_ammo1_ico = "gfx/vehicles/bullets.tga";
-const string hud_ammo2_bar = "gfx/vehicles/bar_dwn_right.tga";
-const string hud_ammo2_ico = "gfx/vehicles/rocket.tga";
-const string hud_energy = "gfx/vehicles/energy.tga";
-
-const int SBRM_FIRST = 1;
-const int SBRM_VOLLY = 1;
-const int SBRM_GUIDE = 2;
-const int SBRM_ARTILLERY = 3;
-const int SBRM_LAST = 3;
-
-const int RSM_FIRST = 1;
-const int RSM_BOMB = 1;
-const int RSM_FLARE = 2;
-const int RSM_LAST = 2;
-
-entity dropmark;
-float autocvar_cl_vehicles_hudscale = 0.5;
-float autocvar_cl_vehicles_hudalpha = 0.75;
-
-const string raptor_ico =  "gfx/vehicles/raptor.tga";
-const string raptor_gun =  "gfx/vehicles/raptor_guns.tga";
-const string raptor_bomb = "gfx/vehicles/raptor_bombs.tga";
-const string raptor_drop = "gfx/vehicles/axh-dropcross.tga";
-string raptor_xhair;
-
-void CSQC_WAKIZASHI_HUD();
-void CSQC_SPIDER_HUD();
-void CSQC_RAPTOR_HUD();
-void CSQC_BUMBLE_HUD();
-void CSQC_BUMBLE_GUN_HUD();
-
-const int MAX_AXH = 4;
-entity AuxiliaryXhair[MAX_AXH];
-
-.string axh_image;
-.float  axh_fadetime;
-.float  axh_drawflag;
-.float  axh_scale;
-
-const string bumb_ico =  "gfx/vehicles/bumb.tga";
-const string bumb_lgun =  "gfx/vehicles/bumb_lgun.tga";
-const string bumb_rgun =  "gfx/vehicles/bumb_rgun.tga";
-
-const string bumb_gun_ico =  "gfx/vehicles/bumb_side.tga";
-const string bumb_gun_gun =  "gfx/vehicles/bumb_side_gun.tga";
-
-const string spider_ico =  "gfx/vehicles/sbot.tga";
-const string spider_rkt =  "gfx/vehicles/sbot_rpods.tga";
-const string spider_mgun = "gfx/vehicles/sbot_mguns.tga";
-string spider_xhair; // = "gfx/vehicles/axh-special1.tga";
-
-const string waki_ico = "gfx/vehicles/waki.tga";
-const string waki_eng = "gfx/vehicles/waki_e.tga";
-const string waki_gun = "gfx/vehicles/waki_guns.tga";
-const string waki_rkt = "gfx/vehicles/waki_rockets.tga";
-const string waki_xhair = "gfx/vehicles/axh-special1.tga";
-
-float alarm1time;
-float alarm2time;
-int weapon2mode;
-
-void AuxiliaryXhair_Draw2D()
-{
-    vector loc, psize;
-
-    psize = self.axh_scale * draw_getimagesize(self.axh_image);
-    loc = project_3d_to_2d(self.move_origin) - 0.5 * psize;
-    if (!(loc.z < 0 || loc.x < 0 || loc.y < 0 || loc.x > vid_conwidth || loc.y > vid_conheight))
-    {
-        loc.z = 0;
-        psize.z = 0;
-        drawpic(loc, self.axh_image, psize, self.colormod, self.alpha, self.axh_drawflag);
-    }
-
-    if(time - self.cnt > self.axh_fadetime)
-        self.draw2d = func_null;
-}
-
-void Net_AuXair2(bool bIsNew)
-{
-    int axh_id = bound(0, ReadByte(), MAX_AXH);
-    entity axh                 = AuxiliaryXhair[axh_id];
-
-    if(axh == world || wasfreed(axh))  // MADNESS? THIS IS QQQQCCCCCCCCC (wasfreed, why do you exsist?)
-    {
-        axh                                    = spawn();
-               axh.draw2d                      = func_null;
-               axh.drawmask            = MASK_NORMAL;
-               axh.axh_drawflag        = DRAWFLAG_ADDITIVE;
-               axh.axh_fadetime        = 0.1;
-               axh.axh_image           = "gfx/vehicles/axh-ring.tga";
-               axh.axh_scale           = 1;
-        axh.alpha                      = 1;
-               AuxiliaryXhair[axh_id] = axh;
-    }
-
-       axh.move_origin_x = ReadCoord();
-       axh.move_origin_y = ReadCoord();
-       axh.move_origin_z = ReadCoord();
-       axh.colormod_x = ReadByte() / 255;
-       axh.colormod_y = ReadByte() / 255;
-       axh.colormod_z = ReadByte() / 255;
-    axh.cnt                    = time;
-    axh.draw2d                 = AuxiliaryXhair_Draw2D;
-}
-
-void Net_VehicleSetup()
-{
-    int hud_id = ReadByte();
-
-    // Weapon update?
-    if(hud_id > HUD_VEHICLE_LAST)
-    {
-        weapon2mode = hud_id - HUD_VEHICLE_LAST;
-        return;
-    }
-
-    // hud_id == 0 means we exited a vehicle, so stop alarm sound/s
-    if(hud_id == 0)
-    {
-        sound(self, CH_TRIGGER_SINGLE, "misc/null.wav", VOL_BASEVOICE, ATTEN_NONE);
-        sound(self, CH_PAIN_SINGLE, "misc/null.wav", VOL_BASEVOICE, ATTEN_NONE);
-        return;
-    }
-
-    hud_id  = bound(HUD_VEHICLE_FIRST, hud_id, HUD_VEHICLE_LAST);
-
-    // Init auxiliary crosshairs
-    int i;
-    for(i = 0; i < MAX_AXH; ++i)
-    {
-        entity axh = AuxiliaryXhair[i];
-        if(axh != world && !wasfreed(axh))  // MADNESS? THIS IS QQQQCCCCCCCCC (wasfreed, why do you exsist?)
-            remove(axh);
-
-        axh                                    = spawn();
-               axh.draw2d                      = func_null;
-               axh.drawmask            = MASK_NORMAL;
-               axh.axh_drawflag        = DRAWFLAG_NORMAL;
-               axh.axh_fadetime        = 0.1;
-               axh.axh_image           = "gfx/vehicles/axh-ring.tga";
-               axh.axh_scale           = 1;
-        axh.alpha                      = 1;
-               AuxiliaryXhair[i]       = axh;
-    }
-
-    switch(hud_id)
-    {
-        case HUD_SPIDERBOT:
-            // Minigun1
-            AuxiliaryXhair[0].axh_image   = "gfx/vehicles/axh-ring.tga";
-            AuxiliaryXhair[0].axh_scale   = 0.25;
-            // Minigun2
-            AuxiliaryXhair[1].axh_image   = "gfx/vehicles/axh-ring.tga";
-            AuxiliaryXhair[1].axh_scale   = 0.25;
-            // Rocket
-            AuxiliaryXhair[2].axh_image   = "gfx/vehicles/axh-special1.tga";
-            AuxiliaryXhair[2].axh_scale   = 0.5;
-            break;
-
-        case HUD_WAKIZASHI:
-            AuxiliaryXhair[0].axh_image   = "gfx/vehicles/axh-bracket.tga";
-            AuxiliaryXhair[0].axh_scale   = 0.25;
-            break;
-
-        case HUD_RAPTOR:
-            AuxiliaryXhair[0].axh_image   = "gfx/vehicles/axh-special2.tga";
-            AuxiliaryXhair[0].axh_scale   = 0.5;
-            //AuxiliaryXhair[0].alpha       = 0.5;
-
-            AuxiliaryXhair[1].axh_image   = "gfx/vehicles/axh-bracket.tga";
-            AuxiliaryXhair[1].axh_scale   = 0.25;
-            //AuxiliaryXhair[1].alpha       = 0.75;
-            //AuxiliaryXhair[1].axh_drawflag  = DRAWFLAG_NORMAL;
-            break;
-
-        case HUD_BUMBLEBEE:
-            // Raygun-locked
-            AuxiliaryXhair[0].axh_image   = "gfx/vehicles/axh-bracket.tga";
-            AuxiliaryXhair[0].axh_scale   = 0.5;
-
-            // Gunner1
-            AuxiliaryXhair[1].axh_image   = "gfx/vehicles/axh-target.tga";
-            AuxiliaryXhair[1].axh_scale   = 0.75;
-
-            // Gunner2
-            AuxiliaryXhair[2].axh_image   = "gfx/vehicles/axh-target.tga";
-            AuxiliaryXhair[2].axh_scale   = 0.75;
-            break;
-        case HUD_BUMBLEBEE_GUN:
-            // Plasma cannons
-            AuxiliaryXhair[0].axh_image   = "gfx/vehicles/axh-bracket.tga";
-            AuxiliaryXhair[0].axh_scale   = 0.25;
-            // Raygun
-            AuxiliaryXhair[1].axh_image   = "gfx/vehicles/axh-bracket.tga";
-            AuxiliaryXhair[1].axh_scale   = 0.25;
-            break;
-    }
-}
-#define HUD_GETSTATS \
-    int vh_health       = getstati(STAT_VEHICLESTAT_HEALTH);  \
-       float shield        = getstati(STAT_VEHICLESTAT_SHIELD);  \
-       noref int energy    = getstati(STAT_VEHICLESTAT_ENERGY);  \
-       noref float ammo1   = getstati(STAT_VEHICLESTAT_AMMO1);   \
-       noref float reload1 = getstati(STAT_VEHICLESTAT_RELOAD1); \
-       noref int ammo2     = getstati(STAT_VEHICLESTAT_AMMO2);   \
-       noref int reload2   = getstati(STAT_VEHICLESTAT_RELOAD2);
-
-void CSQC_BUMBLE_HUD()
-{
-/*
-    drawpic(hudloc, waki_s, picsize, '1 1 1', shield, DRAWFLAG_NORMAL);
-    drawpic(hudloc, waki_b, picsize, '0 1 0' * health + '1 0 0'  * (1 - health), 1, DRAWFLAG_NORMAL);
-    drawpic(hudloc, waki_r, picsize, '1 1 1' * reload1 + '1 0 0' * (1 - reload1), 1, DRAWFLAG_NORMAL);
-    drawpic(hudloc, waki_e, picsize, '1 1 1' * energy + '1 0 0'  * (1 - energy), 1, DRAWFLAG_NORMAL);
-*/
-       if(autocvar_r_letterbox)
-        return;
-
-    vector picsize, hudloc = '0 0 0', pic2size, picloc;
-
-    // Fetch health & ammo stats
-       HUD_GETSTATS
-
-    picsize = draw_getimagesize(hud_bg) * autocvar_cl_vehicles_hudscale;
-    hudloc.y = vid_conheight - picsize.y;
-    hudloc.x = vid_conwidth * 0.5 - picsize.x * 0.5;
-
-    drawpic(hudloc, hud_bg, picsize, '1 1 1', autocvar_cl_vehicles_hudalpha, DRAWFLAG_NORMAL);
-
-    shield  *= 0.01;
-    vh_health  *= 0.01;
-    energy  *= 0.01;
-    reload1 *= 0.01;
-
-    pic2size = draw_getimagesize(bumb_ico) * (autocvar_cl_vehicles_hudscale * 0.8);
-    picloc = picsize * 0.5 - pic2size * 0.5;
-
-    if(vh_health < 0.25)
-        drawpic(hudloc + picloc, bumb_ico, pic2size,  '1 0 0' + '0 1 1' * sin(time * 8),  1, DRAWFLAG_NORMAL);
-    else
-        drawpic(hudloc + picloc, bumb_ico, pic2size,  '1 1 1' * vh_health  + '1 0 0' * (1 - vh_health),  1, DRAWFLAG_NORMAL);
-
-    drawpic(hudloc + picloc, bumb_lgun, pic2size, '1 1 1' * energy   + '1 0 0' * (1 - energy),   1, DRAWFLAG_NORMAL);
-    drawpic(hudloc + picloc, bumb_lgun, pic2size, '1 1 1' * energy   + '1 0 0' * (1 - energy),   1, DRAWFLAG_NORMAL);
-    drawpic(hudloc + picloc, hud_sh, pic2size,  '1 1 1', shield, DRAWFLAG_NORMAL);
-
-// Health bar
-    picsize = draw_getimagesize(hud_hp_bar) * autocvar_cl_vehicles_hudscale;
-    picloc = '69 69 0' * autocvar_cl_vehicles_hudscale;
-    drawsetcliparea(hudloc.x + picloc.x + (picsize.x * (1 - vh_health)), 0, vid_conwidth, vid_conheight);
-    drawpic(hudloc + picloc, hud_hp_bar, picsize, '1 1 1', 1 , DRAWFLAG_NORMAL);
-    drawresetcliparea();
-// ..  and icon
-    picsize = draw_getimagesize(hud_hp_ico) * autocvar_cl_vehicles_hudscale;
-    picloc = '37 65 0' * autocvar_cl_vehicles_hudscale;
-    if(vh_health < 0.25)
-    {
-        if(alarm1time < time)
-        {
-            alarm1time = time + 2;
-            sound(self, CH_PAIN_SINGLE, "vehicles/alarm.wav", VOL_BASEVOICE, ATTEN_NONE);
-        }
-
-        drawpic(hudloc + picloc, hud_hp_ico, picsize, '1 0 0' + '0 1 1' * sin(time * 8), 1, DRAWFLAG_NORMAL);
-    }
-    else
-    {
-        drawpic(hudloc + picloc, hud_hp_ico, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
-        if(alarm1time)
-        {
-            sound(self, CH_PAIN_SINGLE, "misc/null.wav", VOL_BASEVOICE, ATTEN_NONE);
-            alarm1time = 0;
-        }
-    }
-
-// Shield bar
-    picsize = draw_getimagesize(hud_sh_bar) * autocvar_cl_vehicles_hudscale;
-    picloc = '69 140 0' * autocvar_cl_vehicles_hudscale;
-    drawsetcliparea(hudloc.x + picloc.x + (picsize.x * (1 - shield)), 0, vid_conwidth, vid_conheight);
-    drawpic(hudloc + picloc, hud_sh_bar, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
-    drawresetcliparea();
-// ..  and icon
-    picloc = '40 136 0' * autocvar_cl_vehicles_hudscale;
-    picsize = draw_getimagesize(hud_sh_ico) * autocvar_cl_vehicles_hudscale;
-    if(shield < 0.25)
-    {
-        if(alarm2time < time)
-        {
-            alarm2time = time + 1;
-            sound(self, CH_TRIGGER_SINGLE, "vehicles/alarm_shield.wav", VOL_BASEVOICE, ATTEN_NONE);
-        }
-        drawpic(hudloc + picloc, hud_sh_ico, picsize, '1 0 0' + '0 1 1' * sin(time * 8), 1, DRAWFLAG_NORMAL);
-    }
-    else
-    {
-        drawpic(hudloc + picloc, hud_sh_ico, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
-        if(alarm2time)
-        {
-            sound(self, CH_TRIGGER_SINGLE, "misc/null.wav", VOL_BASEVOICE, ATTEN_NONE);
-            alarm2time = 0;
-        }
-    }
-
-       ammo1 *= 0.01;
-       ammo2 *= 0.01;
-
-// Gunner1 bar
-    picsize = draw_getimagesize(hud_ammo1_bar) * autocvar_cl_vehicles_hudscale;
-    picloc = '450 69 0' * autocvar_cl_vehicles_hudscale;
-    drawsetcliparea(hudloc.x + picloc.x, picloc.y, picsize.x * ammo1, vid_conheight);
-    drawpic(hudloc + picloc, hud_ammo1_bar, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
-    drawresetcliparea();
-
-// Right gunner slot occupied?
-       if(!AuxiliaryXhair[1].draw2d)
-       {
-               shield = (picsize.x * 0.5) - (0.5 * stringwidth(_("No right gunner!"), false, '1 0 0' * picsize.y + '0 1 0' * picsize.y));
-               drawfill(hudloc + picloc - '0.2 0.2 0', picsize + '0.4 0.4 0', '0.25 0.25 0.25', 0.75, DRAWFLAG_NORMAL);
-               drawstring(hudloc + picloc + '1 0 0' * shield, _("No right gunner!"), '1 0 0' * picsize.y + '0 1 0' * picsize.y, '1 0 0' + '0 1 1' * sin(time * 10), 1, DRAWFLAG_NORMAL);
-       }
-
-// ..  and icon
-    picsize = 1.5 * draw_getimagesize(hud_energy) * autocvar_cl_vehicles_hudscale;
-    picloc = '664 60 0' * autocvar_cl_vehicles_hudscale;
-    if(ammo1 < 0.2)
-        drawpic(hudloc + picloc, hud_energy, picsize, '1 0 0' + '0 1 1' * sin(time * 8), 1, DRAWFLAG_NORMAL);
-    else
-        drawpic(hudloc + picloc, hud_energy, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
-
-// Gunner2 bar
-    picsize = draw_getimagesize(hud_ammo2_bar) * autocvar_cl_vehicles_hudscale;
-    picloc = '450 140 0' * autocvar_cl_vehicles_hudscale;
-    drawsetcliparea(hudloc.x + picloc.x, picloc.y, picsize.x * ammo2, vid_conheight);
-    drawpic(hudloc + picloc, hud_ammo2_bar, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
-    drawresetcliparea();
-// Left gunner slot occupied?
-       if(!AuxiliaryXhair[2].draw2d)
-       {
-               shield = (picsize.x * 0.5) - (0.5 * stringwidth(_("No left gunner!"), false, '1 0 0' * picsize.y + '0 1 0' * picsize.y));
-               drawfill(hudloc + picloc - '0.2 0.2 0', picsize + '0.4 0.4 0', '0.25 0.25 0.25', 0.75, DRAWFLAG_NORMAL);
-               drawstring(hudloc + picloc + '1 0 0' * shield, _("No left gunner!"), '1 0 0' * picsize.y + '0 1 0' * picsize.y, '1 0 0' + '0 1 1' * sin(time * 10), 1, DRAWFLAG_NORMAL);
-       }
-
-// ..  and icon
-    picsize = 1.5 * draw_getimagesize(hud_energy) * autocvar_cl_vehicles_hudscale;
-    picloc = '664 130 0' * autocvar_cl_vehicles_hudscale;
-    if(ammo2 < 0.2)
-        drawpic(hudloc + picloc, hud_energy, picsize, '1 0 0' + '0 1 1' * sin(time * 8), 1, DRAWFLAG_NORMAL);
-    else
-        drawpic(hudloc + picloc, hud_energy, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
-
-       if (scoreboard_showscores)
-               HUD_DrawScoreboard();
-    else
-    {
-        picsize = draw_getimagesize(waki_xhair);
-        picsize.x *= 0.5;
-        picsize.y *= 0.5;
-        drawpic('0.5 0 0' * (vid_conwidth - picsize.x) + '0 0.5 0' * (vid_conheight - picsize.y), waki_xhair, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
-    }
-
-}
-
-void CSQC_BUMBLE_GUN_HUD()
-{
-
-       if(autocvar_r_letterbox)
-        return;
-
-    vector picsize, hudloc = '0 0 0', pic2size, picloc;
-
-    // Fetch health & ammo stats
-       HUD_GETSTATS
-
-    picsize = draw_getimagesize(hud_bg) * autocvar_cl_vehicles_hudscale;
-    hudloc.y = vid_conheight - picsize.y;
-    hudloc.x = vid_conwidth * 0.5 - picsize.x * 0.5;
-
-    drawpic(hudloc, hud_bg, picsize, '1 1 1', autocvar_cl_vehicles_hudalpha, DRAWFLAG_NORMAL);
-
-    shield  *= 0.01;
-    vh_health  *= 0.01;
-    energy  *= 0.01;
-    reload1 *= 0.01;
-
-    pic2size = draw_getimagesize(bumb_gun_ico) * (autocvar_cl_vehicles_hudscale * 0.8);
-    picloc = picsize * 0.5 - pic2size * 0.5;
-
-    if(vh_health < 0.25)
-        drawpic(hudloc + picloc, bumb_gun_ico, pic2size,  '1 0 0' + '0 1 1' * sin(time * 8),  1, DRAWFLAG_NORMAL);
-    else
-        drawpic(hudloc + picloc, bumb_gun_ico, pic2size,  '1 1 1' * vh_health  + '1 0 0' * (1 - vh_health),  1, DRAWFLAG_NORMAL);
-
-    drawpic(hudloc + picloc, bumb_gun_gun, pic2size, '1 1 1' * energy   + '1 0 0' * (1 - energy),   1, DRAWFLAG_NORMAL);
-    drawpic(hudloc + picloc, hud_sh, pic2size,  '1 1 1', shield, DRAWFLAG_NORMAL);
-
-// Health bar
-    picsize = draw_getimagesize(hud_hp_bar) * autocvar_cl_vehicles_hudscale;
-    picloc = '69 69 0' * autocvar_cl_vehicles_hudscale;
-    drawsetcliparea(hudloc.x + picloc.x + (picsize.x * (1 - vh_health)), 0, vid_conwidth, vid_conheight);
-    drawpic(hudloc + picloc, hud_hp_bar, picsize, '1 1 1', 1 , DRAWFLAG_NORMAL);
-    drawresetcliparea();
-// ..  and icon
-    picsize = draw_getimagesize(hud_hp_ico) * autocvar_cl_vehicles_hudscale;
-    picloc = '37 65 0' * autocvar_cl_vehicles_hudscale;
-    if(vh_health < 0.25)
-    {
-        if(alarm1time < time)
-        {
-            alarm1time = time + 2;
-            sound(self, CH_PAIN_SINGLE, "vehicles/alarm.wav", VOL_BASEVOICE, ATTEN_NONE);
-        }
-
-        drawpic(hudloc + picloc, hud_hp_ico, picsize, '1 0 0' + '0 1 1' * sin(time * 8), 1, DRAWFLAG_NORMAL);
-    }
-    else
-    {
-        drawpic(hudloc + picloc, hud_hp_ico, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
-        if(alarm1time)
-        {
-            sound(self, CH_PAIN_SINGLE, "misc/null.wav", VOL_BASEVOICE, ATTEN_NONE);
-            alarm1time = 0;
-        }
-    }
-
-// Shield bar
-    picsize = draw_getimagesize(hud_sh_bar) * autocvar_cl_vehicles_hudscale;
-    picloc = '69 140 0' * autocvar_cl_vehicles_hudscale;
-    drawsetcliparea(hudloc.x + picloc.x + (picsize.x * (1 - shield)), 0, vid_conwidth, vid_conheight);
-    drawpic(hudloc + picloc, hud_sh_bar, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
-    drawresetcliparea();
-// ..  and icon
-    picloc = '40 136 0' * autocvar_cl_vehicles_hudscale;
-    picsize = draw_getimagesize(hud_sh_ico) * autocvar_cl_vehicles_hudscale;
-    if(shield < 0.25)
-    {
-        if(alarm2time < time)
-        {
-            alarm2time = time + 1;
-            sound(self, CH_TRIGGER_SINGLE, "vehicles/alarm_shield.wav", VOL_BASEVOICE, ATTEN_NONE);
-        }
-        drawpic(hudloc + picloc, hud_sh_ico, picsize, '1 0 0' + '0 1 1' * sin(time * 8), 1, DRAWFLAG_NORMAL);
-    }
-    else
-    {
-        drawpic(hudloc + picloc, hud_sh_ico, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
-        if(alarm2time)
-        {
-            sound(self, CH_TRIGGER_SINGLE, "misc/null.wav", VOL_BASEVOICE, ATTEN_NONE);
-            alarm2time = 0;
-        }
-    }
-
-// Gun bar
-    picsize = draw_getimagesize(hud_ammo1_bar) * autocvar_cl_vehicles_hudscale;
-    picloc = '450 69 0' * autocvar_cl_vehicles_hudscale;
-    drawsetcliparea(hudloc.x + picloc.x, picloc.y, picsize.x * energy, vid_conheight);
-    drawpic(hudloc + picloc, hud_ammo1_bar, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
-    drawresetcliparea();
-
-// ..  and icon
-    picsize = 1.5 * draw_getimagesize(hud_energy) * autocvar_cl_vehicles_hudscale;
-    picloc = '664 60 0' * autocvar_cl_vehicles_hudscale;
-    if(energy < 0.2)
-        drawpic(hudloc + picloc, hud_energy, picsize, '1 0 0' + '0 1 1' * sin(time * 8), 1, DRAWFLAG_NORMAL);
-    else
-        drawpic(hudloc + picloc, hud_energy, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
-
-       if (scoreboard_showscores)
-               HUD_DrawScoreboard();
-    /*
-    else
-    {
-        picsize = draw_getimagesize(waki_xhair);
-        picsize_x *= 0.5;
-        picsize_y *= 0.5;
-
-
-        drawpic('0.5 0 0' * (vid_conwidth - picsize_x) + '0 0.5 0' * (vid_conheight - picsize_y), waki_xhair, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
-    }
-    */
-}
-
-
-
-void CSQC_SPIDER_HUD()
-{
-       if(autocvar_r_letterbox)
-        return;
-
-    vector picsize, hudloc = '0 0 0', pic2size, picloc;
-    int i;
-
-    // Fetch health & ammo stats
-       HUD_GETSTATS
-
-    picsize = draw_getimagesize(hud_bg) * autocvar_cl_vehicles_hudscale;
-    hudloc.y = vid_conheight - picsize.y;
-    hudloc.x = vid_conwidth * 0.5 - picsize.x * 0.5;
-
-    drawpic(hudloc, hud_bg, picsize, '1 1 1', autocvar_cl_vehicles_hudalpha, DRAWFLAG_NORMAL);
-
-    ammo1   *= 0.01;
-    shield  *= 0.01;
-    vh_health  *= 0.01;
-    reload2 *= 0.01;
-
-    pic2size = draw_getimagesize(spider_ico) * (autocvar_cl_vehicles_hudscale * 0.8);
-    picloc = picsize * 0.5 - pic2size * 0.5;
-    if(vh_health < 0.25)
-        drawpic(hudloc + picloc, spider_ico, pic2size,  '1 0 0' + '0 1 1' * sin(time * 8),  1, DRAWFLAG_NORMAL);
-    else
-        drawpic(hudloc + picloc, spider_ico, pic2size,  '1 1 1' * vh_health  + '1 0 0' * (1 - vh_health),  1, DRAWFLAG_NORMAL);
-    drawpic(hudloc + picloc, spider_rkt, pic2size,  '1 1 1' * reload2 + '1 0 0' * (1 - reload2), 1, DRAWFLAG_NORMAL);
-    drawpic(hudloc + picloc, spider_mgun, pic2size, '1 1 1' * ammo1   + '1 0 0' * (1 - ammo1),   1, DRAWFLAG_NORMAL);
-    drawpic(hudloc + picloc, hud_sh, pic2size,  '1 1 1', shield, DRAWFLAG_NORMAL);
-
-// Health bar
-    picsize = draw_getimagesize(hud_hp_bar) * autocvar_cl_vehicles_hudscale;
-    picloc = '69 69 0' * autocvar_cl_vehicles_hudscale;
-    drawsetcliparea(hudloc.x + picloc.x + (picsize.x * (1 - vh_health)), 0, vid_conwidth, vid_conheight);
-    drawpic(hudloc + picloc, hud_hp_bar, picsize, '1 1 1', 1 , DRAWFLAG_NORMAL);
-    drawresetcliparea();
-// ..  and icon
-    picsize = draw_getimagesize(hud_hp_ico) * autocvar_cl_vehicles_hudscale;
-    picloc = '37 65 0' * autocvar_cl_vehicles_hudscale;
-    if(vh_health < 0.25)
-    {
-        if(alarm1time < time)
-        {
-            alarm1time = time + 2;
-            sound(self, CH_PAIN_SINGLE, "vehicles/alarm.wav", VOL_BASEVOICE, ATTEN_NONE);
-        }
-        drawpic(hudloc + picloc, hud_hp_ico, picsize, '1 0 0' + '0 1 1' * sin(time * 8), 1, DRAWFLAG_NORMAL);
-    }
-    else
-    {
-        drawpic(hudloc + picloc, hud_hp_ico, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
-        if(alarm1time)
-        {
-            sound(self, CH_PAIN_SINGLE, "misc/null.wav", VOL_BASEVOICE, ATTEN_NONE);
-            alarm1time = 0;
-        }
-    }
-// Shield bar
-    picsize = draw_getimagesize(hud_sh_bar) * autocvar_cl_vehicles_hudscale;
-    picloc = '69 140 0' * autocvar_cl_vehicles_hudscale;
-    drawsetcliparea(hudloc.x + picloc.x + (picsize.x * (1 - shield)), 0, vid_conwidth, vid_conheight);
-    drawpic(hudloc + picloc, hud_sh_bar, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
-    drawresetcliparea();
-// ..  and icon
-    picloc = '40 136 0' * autocvar_cl_vehicles_hudscale;
-    picsize = draw_getimagesize(hud_sh_ico) * autocvar_cl_vehicles_hudscale;
-    if(shield < 0.25)
-    {
-        if(alarm2time < time)
-        {
-            alarm2time = time + 1;
-            sound(self, CH_TRIGGER_SINGLE, "vehicles/alarm_shield.wav", VOL_BASEVOICE, ATTEN_NONE);
-        }
-        drawpic(hudloc + picloc, hud_sh_ico, picsize, '1 0 0' + '0 1 1' * sin(time * 8), 1, DRAWFLAG_NORMAL);
-    }
-    else
-    {
-        drawpic(hudloc + picloc, hud_sh_ico, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
-        if(alarm2time)
-        {
-            sound(self, CH_TRIGGER_SINGLE, "misc/null.wav", VOL_BASEVOICE, ATTEN_NONE);
-            alarm2time = 0;
-        }
-    }
-
-// Minigun bar
-    picsize = draw_getimagesize(hud_ammo1_bar) * autocvar_cl_vehicles_hudscale;
-    picloc = '450 69 0' * autocvar_cl_vehicles_hudscale;
-    drawsetcliparea(hudloc.x + picloc.x, picloc.y, picsize.x * ammo1, vid_conheight);
-    drawpic(hudloc + picloc, hud_ammo1_bar, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
-    drawresetcliparea();
-// ..  and icon
-    picsize = draw_getimagesize(hud_ammo1_ico) * autocvar_cl_vehicles_hudscale;
-    picloc = '664 60 0' * autocvar_cl_vehicles_hudscale;
-    if(ammo1 < 0.2)
-        drawpic(hudloc + picloc, hud_ammo1_ico, picsize, '1 0 0' + '0 1 1' * sin(time * 8), 1, DRAWFLAG_NORMAL);
-    else
-        drawpic(hudloc + picloc, hud_ammo1_ico, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
-
-// Rocket ammo bar
-    picsize = draw_getimagesize(hud_ammo2_bar) * autocvar_cl_vehicles_hudscale;
-    ammo1 = picsize.x / 8;
-    picloc = '450 140 0' * autocvar_cl_vehicles_hudscale;
-    drawsetcliparea(hudloc.x + picloc.x, hudloc.y + picloc.y, picsize.x * reload2, vid_conheight);
-    drawpic(hudloc + picloc, hud_ammo2_bar, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
-    drawresetcliparea();
-
-// ..  and icons
-    pic2size = 0.35 * draw_getimagesize(hud_ammo2_ico) * autocvar_cl_vehicles_hudscale;
-    picloc.x -= pic2size.x;
-    picloc.y += pic2size.y * 2.25;
-    if(ammo2 == 9)
-    {
-        for(i = 1; i < 9; ++i)
-        {
-            picloc.x += ammo1;
-            drawpic(hudloc + picloc, hud_ammo2_ico, pic2size, ((8 * reload2 <= i) ? '0 0 0' : '1 1 1'), 0.75, DRAWFLAG_NORMAL);
-        }
-    }
-    else
-    {
-        for(i = 1; i < 9; ++i)
-        {
-            picloc.x += ammo1;
-            drawpic(hudloc + picloc, hud_ammo2_ico, pic2size, ((i >= ammo2) ? '1 1 1' : '0 0 0'), 0.75, DRAWFLAG_NORMAL);
-        }
-    }
-    pic2size = draw_getimagesize(hud_ammo2_ico) * autocvar_cl_vehicles_hudscale;
-    picloc = '664 130 0' * autocvar_cl_vehicles_hudscale;
-    if(ammo2 == 9)
-        drawpic(hudloc + picloc, hud_ammo2_ico, pic2size, '1 0 0' + '0 1 1' * sin(time * 8), 1, DRAWFLAG_NORMAL);
-    else
-        drawpic(hudloc + picloc, hud_ammo2_ico, pic2size, '1 1 1', 1, DRAWFLAG_NORMAL);
-
-       if (scoreboard_showscores)
-               HUD_DrawScoreboard();
-    else
-    {
-        switch(weapon2mode)
-        {
-            case SBRM_VOLLY:
-                spider_xhair = "gfx/vehicles/axh-bracket.tga";
-                break;
-            case SBRM_GUIDE:
-                spider_xhair = "gfx/vehicles/axh-cross.tga";
-                break;
-            case SBRM_ARTILLERY:
-                spider_xhair = "gfx/vehicles/axh-tag.tga";
-                break;
-            default:
-                spider_xhair= "gfx/vehicles/axh-tag.tga";
-        }
-
-        picsize = draw_getimagesize(spider_xhair);
-        picsize.x *= autocvar_cl_vehicle_spiderbot_cross_size;
-        picsize.y *= autocvar_cl_vehicle_spiderbot_cross_size;
-
-        drawpic('0.5 0 0' * (vid_conwidth - picsize.x) + '0 0.5 0' * (vid_conheight - picsize.y), spider_xhair, picsize, '1 1 1', autocvar_cl_vehicle_spiderbot_cross_alpha, DRAWFLAG_ADDITIVE);
-    }
-}
-
-void CSQC_RAPTOR_HUD()
-{
-       if(autocvar_r_letterbox)
-        return;
-
-    vector picsize, hudloc = '0 0 0', pic2size, picloc;
-
-    // Fetch health & ammo stats
-       HUD_GETSTATS
-
-    picsize = draw_getimagesize(hud_bg) * autocvar_cl_vehicles_hudscale;
-    hudloc.y = vid_conheight - picsize.y;
-    hudloc.x = vid_conwidth * 0.5 - picsize.x * 0.5;
-
-    drawpic(hudloc, hud_bg, picsize, '1 1 1', autocvar_cl_vehicles_hudalpha, DRAWFLAG_NORMAL);
-
-    ammo1   *= 0.01;
-    ammo2   *= 0.01;
-    shield  *= 0.01;
-    vh_health  *= 0.01;
-    energy  *= 0.01;
-    reload1 = reload2 * 0.01;
-    //reload2 *= 0.01;
-
-    pic2size = draw_getimagesize(spider_ico) * (autocvar_cl_vehicles_hudscale * 0.8);
-    picloc = picsize * 0.5 - pic2size * 0.5;
-    if(vh_health < 0.25)
-        drawpic(hudloc + picloc, raptor_ico, pic2size,  '1 0 0' + '0 1 1' * sin(time * 8),  1, DRAWFLAG_NORMAL);
-    else
-        drawpic(hudloc + picloc, raptor_ico, pic2size,  '1 1 1' * vh_health  + '1 0 0' * (1 - vh_health),  1, DRAWFLAG_NORMAL);
-    drawpic(hudloc + picloc, raptor_bomb, pic2size,  '1 1 1' * reload1 + '1 0 0' * (1 - reload1), 1, DRAWFLAG_NORMAL);
-    drawpic(hudloc + picloc, raptor_gun, pic2size, '1 1 1' * energy   + '1 0 0' * (1 - energy),   1, DRAWFLAG_NORMAL);
-    drawpic(hudloc + picloc, hud_sh, pic2size,  '1 1 1', shield, DRAWFLAG_NORMAL);
-
-// Health bar
-    picsize = draw_getimagesize(hud_hp_bar) * autocvar_cl_vehicles_hudscale;
-    picloc = '69 69 0' * autocvar_cl_vehicles_hudscale;
-    drawsetcliparea(hudloc.x + picloc.x + (picsize.x * (1 - vh_health)), 0, vid_conwidth, vid_conheight);
-    drawpic(hudloc + picloc, hud_hp_bar, picsize, '1 1 1', 1 , DRAWFLAG_NORMAL);
-    drawresetcliparea();
-// ..  and icon
-    picsize = draw_getimagesize(hud_hp_ico) * autocvar_cl_vehicles_hudscale;
-    picloc = '37 65 0' * autocvar_cl_vehicles_hudscale;
-    if(vh_health < 0.25)
-    {
-        if(alarm1time < time)
-        {
-            alarm1time = time + 2;
-            sound(self, CH_PAIN_SINGLE, "vehicles/alarm.wav", VOL_BASEVOICE, ATTEN_NONE);
-        }
-
-        drawpic(hudloc + picloc, hud_hp_ico, picsize, '1 0 0' + '0 1 1' * sin(time * 8), 1, DRAWFLAG_NORMAL);
-    }
-    else
-    {
-        drawpic(hudloc + picloc, hud_hp_ico, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
-        if(alarm1time)
-        {
-            sound(self, CH_PAIN_SINGLE, "misc/null.wav", VOL_BASEVOICE, ATTEN_NONE);
-            alarm1time = 0;
-        }
-    }
-
-// Shield bar
-    picsize = draw_getimagesize(hud_sh_bar) * autocvar_cl_vehicles_hudscale;
-    picloc = '69 140 0' * autocvar_cl_vehicles_hudscale;
-    drawsetcliparea(hudloc.x + picloc.x + (picsize.x * (1 - shield)), 0, vid_conwidth, vid_conheight);
-    drawpic(hudloc + picloc, hud_sh_bar, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
-    drawresetcliparea();
-// ..  and icon
-    picloc = '40 136 0' * autocvar_cl_vehicles_hudscale;
-    picsize = draw_getimagesize(hud_sh_ico) * autocvar_cl_vehicles_hudscale;
-    if(shield < 0.25)
-    {
-        if(alarm2time < time)
-        {
-            alarm2time = time + 1;
-            sound(self, CH_TRIGGER_SINGLE, "vehicles/alarm_shield.wav", VOL_BASEVOICE, ATTEN_NONE);
-        }
-        drawpic(hudloc + picloc, hud_sh_ico, picsize, '1 0 0' + '0 1 1' * sin(time * 8), 1, DRAWFLAG_NORMAL);
-    }
-    else
-    {
-        drawpic(hudloc + picloc, hud_sh_ico, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
-        if(alarm2time)
-        {
-            sound(self, CH_TRIGGER_SINGLE, "misc/null.wav", VOL_BASEVOICE, ATTEN_NONE);
-            alarm2time = 0;
-        }
-    }
-
-// Gun bar
-    picsize = draw_getimagesize(hud_ammo1_bar) * autocvar_cl_vehicles_hudscale;
-    picloc = '450 69 0' * autocvar_cl_vehicles_hudscale;
-    drawsetcliparea(hudloc.x + picloc.x, picloc.y, picsize.x * energy, vid_conheight);
-    drawpic(hudloc + picloc, hud_ammo1_bar, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
-    drawresetcliparea();
-// ..  and icon
-    picsize = draw_getimagesize(hud_ammo1_ico) * autocvar_cl_vehicles_hudscale;
-    picloc = '664 60 0' * autocvar_cl_vehicles_hudscale;
-    if(energy < 0.2)
-        drawpic(hudloc + picloc, hud_ammo1_ico, picsize, '1 0 0' + '0 1 1' * sin(time * 8), 1, DRAWFLAG_NORMAL);
-    else
-        drawpic(hudloc + picloc, hud_ammo1_ico, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
-
-// Bomb bar
-    picsize = draw_getimagesize(hud_ammo2_bar) * autocvar_cl_vehicles_hudscale;
-    picloc = '450 140 0' * autocvar_cl_vehicles_hudscale;
-    drawsetcliparea(hudloc.x + picloc.x, hudloc.y + picloc.y, picsize.x * reload1, vid_conheight);
-    drawpic(hudloc + picloc, hud_ammo2_bar, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
-    drawresetcliparea();
-// ..  and icon
-    pic2size = draw_getimagesize(hud_ammo2_ico) * autocvar_cl_vehicles_hudscale;
-    picloc = '664 130 0' * autocvar_cl_vehicles_hudscale;
-    if(reload1 != 1)
-        drawpic(hudloc + picloc, hud_ammo2_ico, pic2size, '1 0 0' + '0 1 1' * sin(time * 8), 1, DRAWFLAG_NORMAL);
-    else
-        drawpic(hudloc + picloc, hud_ammo2_ico, pic2size, '1 1 1', 1, DRAWFLAG_NORMAL);
-
-    if(weapon2mode == RSM_FLARE)
-    {
-        raptor_xhair =  "gfx/vehicles/axh-bracket.tga";
-    }
-    else
-    {
-        raptor_xhair =  "gfx/vehicles/axh-ring.tga";
-
-        // Bombing crosshair
-        if(!dropmark)
-        {
-            dropmark = spawn();
-            dropmark.owner = self;
-            dropmark.gravity = 1;
-        }
-
-        if(reload2 == 100)
-        {
-            vector where;
-
-            setorigin(dropmark, pmove_org);
-            dropmark.velocity = pmove_vel;
-            tracetoss(dropmark, self);
-
-            where = project_3d_to_2d(trace_endpos);
-
-            setorigin(dropmark, trace_endpos);
-            picsize = draw_getimagesize(raptor_drop) * 0.2;
-
-            if (!(where.z < 0 || where.x < 0 || where.y < 0 || where.x > vid_conwidth || where.y > vid_conheight))
-            {
-                where.x -= picsize.x * 0.5;
-                where.y -= picsize.y * 0.5;
-                where.z = 0;
-                drawpic(where, raptor_drop, picsize, '0 2 0', 1, DRAWFLAG_ADDITIVE);
-            }
-            dropmark.cnt = time + 5;
-        }
-        else
-        {
-            vector where;
-            if(dropmark.cnt > time)
-            {
-                where = project_3d_to_2d(dropmark.origin);
-                picsize = draw_getimagesize(raptor_drop) * 0.25;
-
-                if (!(where.z < 0 || where.x < 0 || where.y < 0 || where.x > vid_conwidth || where.y > vid_conheight))
-                {
-                    where.x -= picsize.x * 0.5;
-                    where.y -= picsize.y * 0.5;
-                    where.z = 0;
-                    drawpic(where, raptor_drop, picsize, '2 0 0', 1, DRAWFLAG_ADDITIVE);
-                }
-            }
-        }
-    }
-
-       if (scoreboard_showscores)
-               HUD_DrawScoreboard();
-    else
-    {
-        picsize = draw_getimagesize(raptor_xhair);
-        picsize.x *= 0.5;
-        picsize.y *= 0.5;
-
-        drawpic('0.5 0 0' * (vid_conwidth - picsize.x) + '0 0.5 0' * (vid_conheight - picsize.y), raptor_xhair, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
-    }
-}
-
-void CSQC_WAKIZASHI_HUD()
-{
-/*
-    drawpic(hudloc, waki_s, picsize, '1 1 1', shield, DRAWFLAG_NORMAL);
-    drawpic(hudloc, waki_b, picsize, '0 1 0' * health + '1 0 0'  * (1 - health), 1, DRAWFLAG_NORMAL);
-    drawpic(hudloc, waki_r, picsize, '1 1 1' * reload1 + '1 0 0' * (1 - reload1), 1, DRAWFLAG_NORMAL);
-    drawpic(hudloc, waki_e, picsize, '1 1 1' * energy + '1 0 0'  * (1 - energy), 1, DRAWFLAG_NORMAL);
-*/
-       if(autocvar_r_letterbox)
-        return;
-
-    vector picsize, hudloc = '0 0 0', pic2size, picloc;
-
-    // Fetch health & ammo stats
-       HUD_GETSTATS
-
-    picsize = draw_getimagesize(hud_bg) * autocvar_cl_vehicles_hudscale;
-    hudloc.y = vid_conheight - picsize.y;
-    hudloc.x = vid_conwidth * 0.5 - picsize.x * 0.5;
-
-    drawpic(hudloc, hud_bg, picsize, '1 1 1', autocvar_cl_vehicles_hudalpha, DRAWFLAG_NORMAL);
-
-    shield  *= 0.01;
-    vh_health  *= 0.01;
-    energy  *= 0.01;
-    reload1 *= 0.01;
-
-    pic2size = draw_getimagesize(spider_ico) * (autocvar_cl_vehicles_hudscale * 0.8);
-    picloc = picsize * 0.5 - pic2size * 0.5;
-    if(vh_health < 0.25)
-        drawpic(hudloc + picloc, waki_ico, pic2size,  '1 0 0' + '0 1 1' * sin(time * 8),  1, DRAWFLAG_NORMAL);
-    else
-        drawpic(hudloc + picloc, waki_ico, pic2size,  '1 1 1' * vh_health  + '1 0 0' * (1 - vh_health),  1, DRAWFLAG_NORMAL);
-    drawpic(hudloc + picloc, waki_eng, pic2size, '1 1 1' * energy   + '1 0 0' * (1 - energy),   1, DRAWFLAG_NORMAL);
-    drawpic(hudloc + picloc, waki_gun, pic2size, '1 1 1' * energy   + '1 0 0' * (1 - energy),   1, DRAWFLAG_NORMAL);
-    drawpic(hudloc + picloc, waki_rkt, pic2size,  '1 1 1' * reload1 + '1 0 0' * (1 - reload1), 1, DRAWFLAG_NORMAL);
-    drawpic(hudloc + picloc, hud_sh, pic2size,  '1 1 1', shield, DRAWFLAG_NORMAL);
-
-// Health bar
-    picsize = draw_getimagesize(hud_hp_bar) * autocvar_cl_vehicles_hudscale;
-    picloc = '69 69 0' * autocvar_cl_vehicles_hudscale;
-    drawsetcliparea(hudloc.x + picloc.x + (picsize.x * (1 - vh_health)), 0, vid_conwidth, vid_conheight);
-    drawpic(hudloc + picloc, hud_hp_bar, picsize, '1 1 1', 1 , DRAWFLAG_NORMAL);
-    drawresetcliparea();
-// ..  and icon
-    picsize = draw_getimagesize(hud_hp_ico) * autocvar_cl_vehicles_hudscale;
-    picloc = '37 65 0' * autocvar_cl_vehicles_hudscale;
-    if(vh_health < 0.25)
-    {
-        if(alarm1time < time)
-        {
-            alarm1time = time + 2;
-            sound(self, CH_PAIN_SINGLE, "vehicles/alarm.wav", VOL_BASEVOICE, ATTEN_NONE);
-        }
-
-        drawpic(hudloc + picloc, hud_hp_ico, picsize, '1 0 0' + '0 1 1' * sin(time * 8), 1, DRAWFLAG_NORMAL);
-    }
-    else
-    {
-        drawpic(hudloc + picloc, hud_hp_ico, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
-        if(alarm1time)
-        {
-            sound(self, CH_PAIN_SINGLE, "misc/null.wav", VOL_BASEVOICE, ATTEN_NONE);
-            alarm1time = 0;
-        }
-    }
-
-
-// Shield bar
-    picsize = draw_getimagesize(hud_sh_bar) * autocvar_cl_vehicles_hudscale;
-    picloc = '69 140 0' * autocvar_cl_vehicles_hudscale;
-    drawsetcliparea(hudloc.x + picloc.x + (picsize.x * (1 - shield)), 0, vid_conwidth, vid_conheight);
-    drawpic(hudloc + picloc, hud_sh_bar, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
-    drawresetcliparea();
-// ..  and icon
-    picloc = '40 136 0' * autocvar_cl_vehicles_hudscale;
-    picsize = draw_getimagesize(hud_sh_ico) * autocvar_cl_vehicles_hudscale;
-    if(shield < 0.25)
-    {
-        if(alarm2time < time)
-        {
-            alarm2time = time + 1;
-            sound(self, CH_TRIGGER_SINGLE, "vehicles/alarm_shield.wav", VOL_BASEVOICE, ATTEN_NONE);
-        }
-        drawpic(hudloc + picloc, hud_sh_ico, picsize, '1 0 0' + '0 1 1' * sin(time * 8), 1, DRAWFLAG_NORMAL);
-    }
-    else
-    {
-        drawpic(hudloc + picloc, hud_sh_ico, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
-        if(alarm2time)
-        {
-            sound(self, CH_TRIGGER_SINGLE, "misc/null.wav", VOL_BASEVOICE, ATTEN_NONE);
-            alarm2time = 0;
-        }
-    }
-
-// Gun bar
-    picsize = draw_getimagesize(hud_ammo1_bar) * autocvar_cl_vehicles_hudscale;
-    picloc = '450 69 0' * autocvar_cl_vehicles_hudscale;
-    drawsetcliparea(hudloc.x + picloc.x, picloc.y, picsize.x * energy, vid_conheight);
-    drawpic(hudloc + picloc, hud_ammo1_bar, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
-    drawresetcliparea();
-// ..  and icon
-    picsize = draw_getimagesize(hud_ammo1_ico) * autocvar_cl_vehicles_hudscale;
-    picloc = '664 60 0' * autocvar_cl_vehicles_hudscale;
-    if(energy < 0.2)
-        drawpic(hudloc + picloc, hud_ammo1_ico, picsize, '1 0 0' + '0 1 1' * sin(time * 8), 1, DRAWFLAG_NORMAL);
-    else
-        drawpic(hudloc + picloc, hud_ammo1_ico, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
-
-// Bomb bar
-    picsize = draw_getimagesize(hud_ammo2_bar) * autocvar_cl_vehicles_hudscale;
-    picloc = '450 140 0' * autocvar_cl_vehicles_hudscale;
-    drawsetcliparea(hudloc.x + picloc.x, hudloc.y + picloc.y, picsize.x * reload1, vid_conheight);
-    drawpic(hudloc + picloc, hud_ammo2_bar, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
-    drawresetcliparea();
-// ..  and icon
-    pic2size = draw_getimagesize(hud_ammo2_ico) * autocvar_cl_vehicles_hudscale;
-    picloc = '664 130 0' * autocvar_cl_vehicles_hudscale;
-    if(reload1 != 1)
-        drawpic(hudloc + picloc, hud_ammo2_ico, pic2size, '1 0 0' + '0 1 1' * sin(time * 8), 1, DRAWFLAG_NORMAL);
-    else
-        drawpic(hudloc + picloc, hud_ammo2_ico, pic2size, '1 1 1', 1, DRAWFLAG_NORMAL);
-
-       if (scoreboard_showscores)
-               HUD_DrawScoreboard();
-    else
-    {
-        picsize = draw_getimagesize(waki_xhair);
-        picsize.x *= 0.5;
-        picsize.y *= 0.5;
-
-
-        drawpic('0.5 0 0' * (vid_conwidth - picsize.x) + '0 0.5 0' * (vid_conheight - picsize.y), waki_xhair, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
-    }
-}
-
-void Vehicles_Precache()
-{
-       precache_model("models/vehicles/bomblet.md3");
-       precache_model("models/vehicles/clusterbomb.md3");
-       precache_model("models/vehicles/clusterbomb_fragment.md3");
-       precache_model("models/vehicles/rocket01.md3");
-       precache_model("models/vehicles/rocket02.md3");
-
-       precache_sound ("vehicles/alarm.wav");
-       precache_sound ("vehicles/alarm_shield.wav");
-}
-
-void RaptorCBShellfragDraw()
-{
-       if(wasfreed(self))
-               return;
-
-       Movetype_Physics_MatchTicrate(autocvar_cl_gibs_ticrate, autocvar_cl_gibs_sloppy);
-       self.move_avelocity += randomvec() * 15;
-       self.renderflags = 0;
-
-       if(self.cnt < time)
-               self.alpha = bound(0, self.nextthink - time, 1);
-
-       if(self.alpha < ALPHA_MIN_VISIBLE)
-        remove(self);
-}
-
-void RaptorCBShellfragToss(vector _org, vector _vel, vector _ang)
-{
-    entity sfrag;
-
-    sfrag = spawn();
-    setmodel(sfrag, "models/vehicles/clusterbomb_fragment.md3");
-    setorigin(sfrag, _org);
-
-       sfrag.move_movetype = MOVETYPE_BOUNCE;
-       sfrag.gravity = 0.15;
-       sfrag.solid = SOLID_CORPSE;
-
-       sfrag.draw = RaptorCBShellfragDraw;
-
-       sfrag.move_origin = sfrag.origin = _org;
-       sfrag.move_velocity = _vel;
-       sfrag.move_avelocity = prandomvec() * vlen(sfrag.move_velocity);
-       sfrag.angles = self.move_angles = _ang;
-
-       sfrag.move_time = time;
-       sfrag.damageforcescale = 4;
-
-       sfrag.nextthink = time + 3;
-       sfrag.cnt = time + 2;
-       sfrag.alpha = 1;
-    sfrag.drawmask = MASK_NORMAL;
-}
diff --git a/qcsrc/client/vehicles/vehicles.qh b/qcsrc/client/vehicles/vehicles.qh
deleted file mode 100644 (file)
index 7e509e9..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef VEHICLES_H
-#define VEHICLES_H
-
-void RaptorCBShellfragDraw();
-void RaptorCBShellfragToss(vector _org, vector _vel, vector _ang);
-void Vehicles_Precache();
-void Net_AuXair2(bool bIsNew);
-void Net_VehicleSetup();
-#endif
index 26e709320778a9892ae0493a7452d3a8d5d28257..ffdde41a9e6094e01311cf3613f101675aa5a4b6 100644 (file)
@@ -1,25 +1,31 @@
-#if defined(CSQC)
-       #include "../dpdefs/csprogsdefs.qh"
-       #include "defs.qh"
-       #include "../common/constants.qh"
-       #include "../common/stats.qh"
-       #include "../warpzonelib/mathlib.qh"
-       #include "../warpzonelib/common.qh"
-       #include "../warpzonelib/client.qh"
-       #include "../common/teams.qh"
-       #include "../common/util.qh"
-       #include "../common/nades.qh"
-       #include "../common/weapons/weapons.qh"
-       #include "../common/mapinfo.qh"
-       #include "autocvars.qh"
-       #include "hud.qh"
-       #include "scoreboard.qh"
-       #include "noise.qh"
-       #include "main.qh"
-       #include "../csqcmodellib/cl_player.qh"
-#elif defined(MENUQC)
-#elif defined(SVQC)
-#endif
+#include "_all.qh"
+
+#include "announcer.qh"
+#include "hook.qh"
+#include "hud.qh"
+#include "hud_config.qh"
+#include "mapvoting.qh"
+#include "noise.qh"
+#include "scoreboard.qh"
+#include "shownames.qh"
+#include "vehicles/all.qh"
+#include "waypointsprites.qh"
+
+#include "../common/constants.qh"
+#include "../common/mapinfo.qh"
+#include "../common/nades.qh"
+#include "../common/stats.qh"
+#include "../common/triggers/target/music.qh"
+#include "../common/teams.qh"
+#include "../common/util.qh"
+
+#include "../common/weapons/all.qh"
+
+#include "../csqcmodellib/cl_player.qh"
+
+#include "../warpzonelib/client.qh"
+#include "../warpzonelib/common.qh"
+#include "../warpzonelib/mathlib.qh"
 
 entity porto;
 vector polyline[16];
index 1ae8fa85a311dccebaecdce7af6fd1216521d0b3..92c142435636a8113f973e486f3ec8ec406a084b 100644 (file)
@@ -1,4 +1,55 @@
 #include "wall.qh"
+#include "_all.qh"
+
+#include "bgmscript.qh"
+
+#include "../common/util.qh"
+
+#include "../csqcmodellib/interpolate.qh"
+
+.float alpha;
+.float scale;
+.vector movedir;
+
+void Ent_Wall_PreDraw()
+{
+       if (self.inactive)
+       {
+               self.alpha = 0;
+       }
+       else
+       {
+               vector org = getpropertyvec(VF_ORIGIN);
+               if(!checkpvs(org, self))
+                       self.alpha = 0;
+               else if(self.fade_start || self.fade_end) {
+                       vector offset = '0 0 0';
+                       offset_z = self.fade_vertical_offset;
+                       float player_dist = vlen(org - self.origin - 0.5 * (self.mins + self.maxs) + offset);
+                       if (self.fade_end == self.fade_start)
+                       {
+                               if (player_dist >= self.fade_start)
+                                       self.alpha = 0;
+                               else
+                                       self.alpha = 1;
+                       }
+                       else
+                       {
+                               self.alpha = (self.alpha_min + self.alpha_max * bound(0,
+                                                          (self.fade_end - player_dist)
+                                                          / (self.fade_end - self.fade_start), 1)) / 100.0;
+                       }
+               }
+               else
+               {
+                       self.alpha = 1;
+               }
+       }
+       if(self.alpha <= 0)
+               self.drawmask = 0;
+       else
+               self.drawmask = MASK_NORMAL;
+}
 
 void Ent_Wall_Draw()
 {
@@ -9,7 +60,7 @@ void Ent_Wall_Draw()
                fld = angles;
        else
                fld = origin;
-       self.fld = self.saved;
+       self.(fld) = self.saved;
 
        if(self.lodmodelindex1)
        {
@@ -38,16 +89,16 @@ void Ent_Wall_Draw()
 
        InterpolateOrigin_Do();
 
-       self.saved = self.fld;
+       self.saved = self.(fld);
 
-       f = BGMScript(self);
+       f = doBGMScript(self);
        if(f >= 0)
        {
                if(self.lip < 0) // < 0: alpha goes from 1 to 1-|lip| when toggled (toggling subtracts lip)
                        self.alpha = 1 + self.lip * f;
                else // > 0: alpha goes from 1-|lip| to 1 when toggled (toggling adds lip)
                        self.alpha = 1 - self.lip * (1 - f);
-               self.fld = self.fld + self.movedir * f;
+               self.(fld) = self.(fld) + self.movedir * f;
        }
        else
                self.alpha = 1;
@@ -77,7 +128,7 @@ void Ent_Wall()
                fld = angles;
        else
                fld = origin;
-       self.fld = self.saved;
+       self.(fld) = self.saved;
 
        f = ReadByte();
 
@@ -164,13 +215,20 @@ void Ent_Wall()
                        self.movedir_z = ReadCoord();
                        self.lip = ReadByte() / 255.0;
                }
+               self.fade_start = ReadShort();
+               self.fade_end = ReadShort();
+               self.alpha_max = ReadShort();
+               self.alpha_min = ReadShort();
+               self.inactive = ReadShort();
+               self.fade_vertical_offset = ReadShort();
                BGMScript_InitEntity(self);
        }
 
        InterpolateOrigin_Note();
 
-       self.saved = self.fld;
+       self.saved = self.(fld);
 
        self.entremove = Ent_Wall_Remove;
        self.draw = Ent_Wall_Draw;
+       self.predraw = Ent_Wall_PreDraw;
 }
index 984b54c88423d848bdc3356951f91d536aa0829a..04c0dce24f84326303bf3e57638da5e8329f2f67 100644 (file)
@@ -1,11 +1,20 @@
 #ifndef WALL_H
 #define WALL_H
 
-.float lip;
-.float bgmscriptangular;
-.int lodmodelindex0, lodmodelindex1, lodmodelindex2;
-.float loddistance1, loddistance2;
-.vector saved;
+entityclass(Wall);
+class(Wall) .float lip;
+class(Wall) .float bgmscriptangular;
+class(Wall) .int lodmodelindex0, lodmodelindex1, lodmodelindex2;
+class(Wall) .float loddistance1, loddistance2;
+class(Wall) .vector saved;
+
+// Needed for interactive clientwalls
+.float inactive; // Clientwall disappears when inactive
+.float alpha_max, alpha_min;
+// If fade_start > fade_end, fadeout will be inverted
+// fade_vertical_offset is a vertival offset for player position
+.float fade_start, fade_end, fade_vertical_offset;
+.float default_solid;
 
 void Ent_Wall_Draw();
 
index 788dd871eed84f74e2050375211ef9eca122ee20..0b32de7e920b5e598d1a3aaed844f8f1f22941cb 100644 (file)
@@ -1,4 +1,20 @@
 #include "waypointsprites.qh"
+#include "_all.qh"
+
+#include "hud.qh"
+#include "teamradar.qh"
+
+#include "../common/buffs.qh"
+#include "../common/constants.qh"
+#include "../common/teams.qh"
+
+#include "../common/weapons/all.qh"
+
+#include "../csqcmodellib/interpolate.qh"
+
+#include "../warpzonelib/mathlib.qh"
+
+.float alpha;
 
 void drawrotpic(vector org, float rot, string pic, vector sz, vector hotspot, vector rgb, float a, float f)
 {
@@ -38,7 +54,7 @@ void drawquad(vector o, vector ri, vector up, string pic, vector rgb, float a, f
        R_EndPolygon();
 }
 
-void drawhealthbar(vector org, float rot, float h, vector sz, vector hotspot, float width, float height, float margin, float border, float align, vector rgb, float a, vector hrgb, float ha, float f)
+void drawhealthbar(vector org, float rot, float h, vector sz, vector hotspot, float width, float theheight, float margin, float border, float align, vector rgb, float a, vector hrgb, float ha, float f)
 {
        vector o, ri, up;
        float owidth; // outer width
@@ -56,13 +72,13 @@ void drawhealthbar(vector org, float rot, float h, vector sz, vector hotspot, fl
        up = rotate(up, rot);
 
        owidth = width + 2 * border;
-       o = o - up * (margin + border + height) + ri * (sz.x - owidth) * 0.5;
+       o = o - up * (margin + border + theheight) + ri * (sz.x - owidth) * 0.5;
 
        drawquad(o - up * border,                               ri * owidth,    up * border, "", rgb,  a,  f);
-       drawquad(o + up * height,                               ri * owidth,    up * border, "", rgb,  a,  f);
-       drawquad(o,                                             ri * border,    up * height, "", rgb,  a,  f);
-       drawquad(o + ri * (owidth - border),                    ri * border,    up * height, "", rgb,  a,  f);
-       drawquad(o + ri * (border + align * ((1 - h) * width)), ri * width * h, up * height, "", hrgb, ha, f);
+       drawquad(o + up * theheight,                               ri * owidth,    up * border, "", rgb,  a,  f);
+       drawquad(o,                                             ri * border,    up * theheight, "", rgb,  a,  f);
+       drawquad(o + ri * (owidth - border),                    ri * border,    up * theheight, "", rgb,  a,  f);
+       drawquad(o + ri * (border + align * ((1 - h) * width)), ri * width * h, up * theheight, "", hrgb, ha, f);
 }
 
 // returns location of sprite text
index 3822793da1d0ef2b34260a07a850af138e9ab601..adea76ca7e47a6df9053f7c9edf1d87d24436946 100644 (file)
@@ -26,21 +26,22 @@ float waypointsprite_distancefadescale;
 float waypointsprite_distancefadedistance;
 float waypointsprite_alpha;
 
-.float helpme;
-.float rule;
-.string netname; // primary picture
-.string netname2; // secondary picture
-.string netname3; // tertiary picture
-.float team; // team that gets netname2
-.float lifetime;
-.float fadetime;
-.float maxdistance;
-.int hideflags;
-.float spawntime;
-.float health;
-.float build_started;
-.float build_starthealth;
-.float build_finished;
+entityclass(WaypointSprite);
+class(WaypointSprite) .float helpme;
+class(WaypointSprite) .float rule;
+class(WaypointSprite) .string netname; // primary picture
+class(WaypointSprite) .string netname2; // secondary picture
+class(WaypointSprite) .string netname3; // tertiary picture
+class(WaypointSprite) .int team; // team that gets netname2
+class(WaypointSprite) .float lifetime;
+class(WaypointSprite) .float fadetime;
+class(WaypointSprite) .float maxdistance;
+class(WaypointSprite) .int hideflags;
+class(WaypointSprite) .float spawntime;
+class(WaypointSprite) .float health;
+class(WaypointSprite) .float build_started;
+class(WaypointSprite) .float build_starthealth;
+class(WaypointSprite) .float build_finished;
 
 const float SPRITE_HEALTHBAR_WIDTH = 144;
 const float SPRITE_HEALTHBAR_HEIGHT = 9;
index 1d306fede6d6ce8733529821d373a7e16a371a0f..efa6509c7060e2085458923b33e668e0d2e4fc39 100644 (file)
@@ -1,5 +1,22 @@
 #include "projectile.qh"
 
+#include "../autocvars.qh"
+#include "../defs.qh"
+#include "../main.qh"
+
+#include "../../common/constants.qh"
+#include "../../common/nades.qh"
+#include "../../common/movetypes/movetypes.qh"
+#include "../../common/util.qh"
+
+#include "../../csqcmodellib/interpolate.qh"
+
+#include "../../warpzonelib/anglestransform.qh"
+
+.float alpha;
+.float scale;
+.vector colormod;
+
 void SUB_Stop()
 {
        self.move_velocity = self.move_avelocity = '0 0 0';
@@ -469,6 +486,7 @@ void Ent_Projectile()
        if(!(self.count & 0x80))
                InterpolateOrigin_Note();
 
+       self.classname = "csqcprojectile";
        self.draw = Projectile_Draw;
        self.entremove = Ent_RemoveProjectile;
 }
index 3a4cdcb0432614006f9bd74de807dd06fdf13c21..67e08c224bfd6f2a5f35dd8f3354c36e7d79be07 100644 (file)
@@ -1,20 +1,21 @@
 #ifndef PROJECTILE_H
 #define PROJECTILE_H
 
-.int traileffect;
-
-.vector iorigin1, iorigin2;
-.float spawntime;
-.vector trail_oldorigin;
-.float trail_oldtime;
-.float fade_time, fade_rate;
-
-.float alphamod;
-.int count; // set if clientside projectile
-.int cnt; // sound index
-.float gravity;
-.int snd_looping;
-.bool silent;
+entityclass(Projectile);
+class(Projectile) .int traileffect;
+
+class(Projectile) .vector iorigin1, iorigin2;
+class(Projectile) .float spawntime;
+class(Projectile) .vector trail_oldorigin;
+class(Projectile) .float trail_oldtime;
+class(Projectile) .float fade_time, fade_rate;
+
+class(Projectile) .float alphamod;
+class(Projectile) .int count; // set if clientside projectile
+class(Projectile) .int cnt; // sound index
+class(Projectile) .float gravity;
+class(Projectile) .int snd_looping;
+class(Projectile) .bool silent;
 
 void SUB_Stop();
 
index ecc840f6fbbe41358d381d26a8c12ffaac59de2d..0cba5d7f38b4d49b54f5d779e087571fe1bb7399 100644 (file)
@@ -295,10 +295,10 @@ void animdecide_setframes(entity e, float support_blending, .float fld_frame, .f
                        upper = lower;
                if(e.frame1time != upper.y || e.frame2time != lower.y)
                        BITXOR_ASSIGN(e.effects, EF_RESTARTANIM_BIT);
-               e.fld_frame = upper.x;
-               e.fld_frame1time = upper.y;
-               e.fld_frame2 = lower.x;
-               e.fld_frame2time = lower.y;
+               e.(fld_frame) = upper.x;
+               e.(fld_frame1time) = upper.y;
+               e.(fld_frame2) = lower.x;
+               e.(fld_frame2time) = lower.y;
        }
        else
        {
@@ -308,8 +308,8 @@ void animdecide_setframes(entity e, float support_blending, .float fld_frame, .f
                        upper = lower;
                if(e.frame1time != upper.y)
                        BITXOR_ASSIGN(e.effects, EF_RESTARTANIM_BIT);
-               e.fld_frame = upper.x;
-               e.fld_frame1time = upper.y;
+               e.(fld_frame) = upper.x;
+               e.(fld_frame1time) = upper.y;
        }
 }
 
index bebf5ec59ac2808068a916bfba1da9f6ffc2a999..bf388df65040453c3ea060554962a97228eb47dd 100644 (file)
@@ -5,6 +5,9 @@
 // Add new buffs here!
 // Note: Buffs also need spawnfuncs, which are set below
 
+#include "teams.qh"
+#include "util.qh"
+
 entity Buff_Type_first;
 entity Buff_Type_last;
 .entity enemy; // internal next pointer
diff --git a/qcsrc/common/command/all.qc b/qcsrc/common/command/all.qc
new file mode 100644 (file)
index 0000000..dc1c044
--- /dev/null
@@ -0,0 +1,3 @@
+#include "generic.qc"
+#include "markup.qc"
+#include "rpn.qc"
diff --git a/qcsrc/common/command/all.qh b/qcsrc/common/command/all.qh
new file mode 100644 (file)
index 0000000..7eeb5c3
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef COMMON_COMMANDS_ALL_H
+#define COMMON_COMMANDS_ALL_H
+
+#include "generic.qh"
+#include "markup.qh"
+#include "rpn.qh"
+
+#endif
diff --git a/qcsrc/common/command/command.qh b/qcsrc/common/command/command.qh
new file mode 100644 (file)
index 0000000..fa310fd
--- /dev/null
@@ -0,0 +1,12 @@
+#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;
+#endif
index 7f302e0a27e3e25eff4a196eca39d71bfd7179f5..6aa93a024ed209475f9a4b5d673e4654b46312a5 100644 (file)
@@ -1,5 +1,28 @@
+#include "command.qh"
 #include "generic.qh"
-#include "shared_defs.qh"
+
+#include "markup.qh"
+#include "rpn.qh"
+
+#include "../mapinfo.qh"
+#include "../test.qh"
+
+#ifndef MENUQC
+       #include "../notifications.qh"
+#endif
+
+#ifdef CSQC
+       #include "../../client/command/cl_cmd.qh"
+#endif
+
+#ifdef SVQC
+       #include "../../server/command/banning.qh"
+       #include "../../server/command/cmd.qh"
+       #include "../../server/command/common.qh"
+       #include "../../server/command/sv_cmd.qh"
+
+       #include "../../common/weapons/config.qh"
+#endif
 
 // =========================================================
 //  Generic program common command code, written by Samual
@@ -218,6 +241,25 @@ void GenericCommand_dumpcommands(float request)
        }
 }
 
+void GenericCommand_dumpitems(float request)
+{
+       switch(request)
+       {
+               case CMD_REQUEST_COMMAND:
+               {
+                       Dump_Items();
+                       return;
+               }
+
+               default:
+               case CMD_REQUEST_USAGE:
+               {
+                       printf("\nUsage:^3 %s dumpitems", GetProgramCommandPrefix());
+                       return;
+               }
+       }
+}
+
 void GenericCommand_dumpnotifs(float request)
 {
        switch(request)
@@ -628,6 +670,7 @@ void GenericCommand_(float request)
 #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("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("dumpweapons", GenericCommand_dumpweapons(request), "Dump all weapons into weapons_dump.txt") \
        GENERIC_COMMAND("maplist", GenericCommand_maplist(request, arguments), "Automatic control of maplist") \
index 0bb09b4e737a9eea3a87a2f20f9f65ff8bf7e6ea..e419824ec8eb8d0aadf82735805bf1193c5bc713 100644 (file)
@@ -1,8 +1,7 @@
-#ifndef GENERIC_H
-#define GENERIC_H
+#ifndef COMMAND_GENERIC_H
+#define COMMAND_GENERIC_H
 
-#include "markup.qh"
-#include "rpn.qh"
+#include "../constants.qh"
 
 // =========================================================
 //  Declarations for common command code, written by Samual
index 8030f9e0076d9a7f128cabdb2c672d4a02f5152b..9f0883bd61ba0ea6696dc9a9e443f1f1e733addb 100644 (file)
@@ -1,3 +1,4 @@
+#include "command.qh"
 #include "markup.qh"
 
 // =========================================================
index e6ac7cfbd3c810eb6e0aa5f40ba3095b567da606..bccc78d0bcd3537d43c4aaa1c91410d47fad7a26 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef MARKUP_H
-#define MARKUP_H
+#ifndef COMMAND_MARKUP_H
+#define COMMAND_MARKUP_H
 
 // ==========================================================
 //  Declarations for markup command code, reworked by Samual
index bb920d697e91ce9e2dfc10b1bc4f4fd2e1a2c4a5..700ceb46ea02dc5fa5c210b5fc3e3a5074f98a28 100644 (file)
@@ -1,5 +1,8 @@
+#include "command.qh"
 #include "rpn.qh"
 
+#include "../../warpzonelib/mathlib.qh"
+
 // ========================================
 //  RPN command code, written by divVerent
 //  Last updated: December 28th, 2011
index a28f2946a904250f5c46dac92d609bb9194f8fce..3c5a8019b2a0cfee52c3ab8e9c500edde24563fa 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef RPN_H
-#define RPN_H
+#ifndef COMMAND_RPN_H
+#define COMMAND_RPN_H
 
 // =========================================================
 //  Declarations for RPN command code, written by divVerent
diff --git a/qcsrc/common/command/shared_defs.qh b/qcsrc/common/command/shared_defs.qh
deleted file mode 100644 (file)
index 0056565..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef SHARED_DEFS_H
-#define SHARED_DEFS_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;
-#endif
index 45a65abbe96bd904bae1c3e93007637ba5d8b581..939c6d7c17ffaf882155ac46c63ffed740fd7e86 100644 (file)
@@ -1,6 +1,31 @@
 #ifndef CONSTANTS_H
 #define CONSTANTS_H
 
+// COMMIT-TODO: Update if necessary before committing
+// Revision 1: additional statistics sent (flag caps, returns, deaths)
+// Revision 2: Mapvote preview pictures
+// Revision 3: optimized map vote protocol
+// Revision 4: CSQC config var system
+// Revision 5: mapvote time fix
+// Revision 6: more robust against packet loss/delays, also show not yet connected clients
+// Revision 7: packet loss column
+// Revision 8: race
+// Revision 9: race delta
+// Revision 10: scoreboard force
+// Revision 11: scoreboard unforce; spectator support beginning
+// Revision 12: smaller scores updates (SERVER: requires new engine)
+// Revision 13: pointparticles
+// Revision 14: laser
+// Revision 15: zoom
+// Revision 16: multi-weapons
+// Revision 17: multi-weaponimpulses
+// Revision 18: warmup
+// Revision 19: fog
+// Revision 20: naggers
+// Revision 21: entcs for players optimized (position data down from 12 to 7 bytes); waypointsprites in csqc for team radar
+// Revision 22: hook shot origin
+#define CSQC_REVISION 22
+
 const int AS_STRING = 1;
 const int AS_INT = 2;
 const int AS_FLOAT_TRUNCATED = 2;
@@ -64,6 +89,7 @@ const int ENT_CLIENT_WARPZONE = 24;
 const int ENT_CLIENT_WARPZONE_CAMERA = 25;
 const int ENT_CLIENT_TRIGGER_MUSIC = 26;
 const int ENT_CLIENT_HOOK = 27;
+const int ENT_CLIENT_INVENTORY = 28;
 const int ENT_CLIENT_ARC_BEAM = 29; // WEAPONTODO: fix numbers
 const int ENT_CLIENT_ACCURACY = 30;
 const int ENT_CLIENT_SHOWNAMES = 31;
@@ -78,6 +104,17 @@ const int ENT_CLIENT_ELIMINATEDPLAYERS = 39;
 const int ENT_CLIENT_TURRET = 40;
 const int ENT_CLIENT_AUXILIARYXHAIR = 50;
 const int ENT_CLIENT_VEHICLE = 60;
+const int ENT_CLIENT_LADDER = 61;
+const int ENT_CLIENT_TRIGGER_PUSH = 62;
+const int ENT_CLIENT_TARGET_PUSH = 63;
+const int ENT_CLIENT_CONVEYOR = 64;
+const int ENT_CLIENT_DOOR = 65;
+const int ENT_CLIENT_TRAIN = 66;
+const int ENT_CLIENT_PLAT = 67;
+const int ENT_CLIENT_TRIGGER_IMPULSE = 68;
+const int ENT_CLIENT_SWAMP = 69;
+const int ENT_CLIENT_CORNER = 70;
+const int ENT_CLIENT_KEYLOCK = 71;
 
 const int ENT_CLIENT_HEALING_ORB = 80;
 
@@ -276,7 +313,7 @@ const int SERVERFLAG_ALLOW_FULLBRIGHT = 1;
 const int SERVERFLAG_TEAMPLAY = 2;
 const int SERVERFLAG_PLAYERSTATS = 4;
 
-// FIXME/EXPLAINME: why?
+// FIXME/EXPLAINME: why? Mario: because
 vector autocvar_sv_player_maxs = '16 16 45';
 vector autocvar_sv_player_mins = '-16 -16 -24';
 vector autocvar_sv_player_viewoffset = '0 0 20';
@@ -285,6 +322,9 @@ vector autocvar_sv_player_crouch_mins = '-16 -16 -24';
 vector autocvar_sv_player_crouch_viewoffset = '0 0 20';
 vector autocvar_sv_player_headsize = '24 24 12';
 
+
+// not so constant
+#ifdef SVQC
 #define PL_VIEW_OFS autocvar_sv_player_viewoffset
 #define PL_MIN autocvar_sv_player_mins
 #define PL_MAX autocvar_sv_player_maxs
@@ -292,16 +332,18 @@ vector autocvar_sv_player_headsize = '24 24 12';
 #define PL_CROUCH_MIN autocvar_sv_player_crouch_mins
 #define PL_CROUCH_MAX autocvar_sv_player_crouch_maxs
 #define PL_HEAD autocvar_sv_player_headsize
+#elif defined(CSQC)
+#define PL_VIEW_OFS vec3(getstatf(STAT_PL_VIEW_OFS1), getstatf(STAT_PL_VIEW_OFS2), getstatf(STAT_PL_VIEW_OFS3))
+#define PL_MIN vec3(getstatf(STAT_PL_MIN1), getstatf(STAT_PL_MIN2), getstatf(STAT_PL_MIN3))
+#define PL_MAX vec3(getstatf(STAT_PL_MAX1), getstatf(STAT_PL_MAX2), getstatf(STAT_PL_MAX3))
+#define PL_CROUCH_VIEW_OFS vec3(getstatf(STAT_PL_CROUCH_VIEW_OFS1), getstatf(STAT_PL_CROUCH_VIEW_OFS2), getstatf(STAT_PL_CROUCH_VIEW_OFS3))
+#define PL_CROUCH_MIN vec3(getstatf(STAT_PL_CROUCH_MIN1), getstatf(STAT_PL_CROUCH_MIN2), getstatf(STAT_PL_CROUCH_MIN3))
+#define PL_CROUCH_MAX vec3(getstatf(STAT_PL_CROUCH_MAX1), getstatf(STAT_PL_CROUCH_MAX2), getstatf(STAT_PL_CROUCH_MAX3))
+#endif
 
-// helpers
-#define PL_VIEW_OFS_z autocvar_sv_player_viewoffset.z
-#define PL_MIN_z autocvar_sv_player_mins.z
-#define PL_MAX_z autocvar_sv_player_maxs.z
-#define PL_CROUCH_VIEW_OFS_z autocvar_sv_player_crouch_viewoffset.z
-#define PL_CROUCH_MIN_z autocvar_sv_player_mins.z
-#define PL_HEAD_x autocvar_sv_player_headsize.x
-#define PL_HEAD_y autocvar_sv_player_headsize.y
-#define PL_HEAD_z autocvar_sv_player_headsize.z
+// a bit more constant
+const vector PL_MAX_CONST = '16 16 45';
+const vector PL_MIN_CONST = '-16 -16 -24';
 
 // spawnpoint prios
 const int SPAWN_PRIO_NEAR_TEAMMATE_FOUND = 200;
@@ -319,8 +361,8 @@ const int URI_GET_UPDATENOTIFICATION = 33;
 const int URI_GET_URLLIB = 128;
 const int URI_GET_URLLIB_END = 191;
 
-// gametype votes
-const int GTV_AVAILABLE = 0;
-// for later use in per-map gametype filtering
-const int GTV_FORBIDDEN = 2;
+// gametype vote flags
+const int GTV_FORBIDDEN = 0; // Cannot be voted
+const int GTV_AVAILABLE = 1; // Can be voted
+const int GTV_CUSTOM    = 2; // Custom entry
 #endif
index 17c5f89bcddf9968f07ddef29f0e0fadd99abc33..f464cdc32c5b8dce7efa1c7de08ce2ad78deaf79 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef COUNTING_H
 #define COUNTING_H
 
+#include "util.qh"
+
 // ===============================================
 //  Time processing and counting functions/macros
 // ===============================================
index fdc555e2460e69fd7f344de9f15dfcf65b2533f0..5e5ff42eb47e2893ca4699626fef5bfece9abe13 100644 (file)
@@ -8,7 +8,7 @@
 //#define CSQCMODEL_SUPPORT_GETTAGINFO_BEFORE_DRAW
 
 // server decides crouching, this lags, but so be it
-#define CSQCMODEL_SERVERSIDE_CROUCH
+//#define CSQCMODEL_SERVERSIDE_CROUCH
 
 // a hack for Xonotic
 #ifdef CSQC
@@ -52,7 +52,8 @@
                CSQCMODEL_PROPERTY(512, float, ReadApproxPastTime, WriteApproxPastTime, anim_upper_time) \
        CSQCMODEL_ENDIF \
        CSQCMODEL_PROPERTY(1024, float, ReadAngle, WriteAngle, v_angle_x) \
-       CSQCMODEL_PROPERTY_SCALED(4096, float, ReadByte, WriteByte, scale, 16, 0, 255)
+       CSQCMODEL_PROPERTY_SCALED(4096, float, ReadByte, WriteByte, scale, 16, 0, 255) \
+       CSQCMODEL_PROPERTY(8192, int, ReadInt24_t, WriteInt24_t, dphitcontentsmask)
 // TODO get rid of colormod/glowmod here, find good solution for vortex charge glowmod hack; also get rid of some useless properties on non-players that only exist for CopyBody
 
 // add hook function calls here
diff --git a/qcsrc/common/items/all.inc b/qcsrc/common/items/all.inc
new file mode 100644 (file)
index 0000000..93901a1
--- /dev/null
@@ -0,0 +1,9 @@
+/** If you register a new item, make sure to add it to this list */
+#include "item/ammo.qc"
+#include "item/armor.qc"
+#include "item/buff.qc"
+#include "item/health.qc"
+#include "item/jetpack.qc"
+#include "item/pickup.qc"
+#include "item/powerup.qc"
+#include "../../server/mutators/mutator_instagib_items.qc"
diff --git a/qcsrc/common/items/all.qc b/qcsrc/common/items/all.qc
new file mode 100644 (file)
index 0000000..fa198bb
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef ALL_C
+#define ALL_C
+#include "all.qh"
+
+#include "all.inc"
+
+void Dump_Items()
+{
+    ITEMS_FOREACH(true, LAMBDA({
+        ITEM_HANDLE(Show, it);
+    }));
+}
+
+#endif
diff --git a/qcsrc/common/items/all.qh b/qcsrc/common/items/all.qh
new file mode 100644 (file)
index 0000000..1786b42
--- /dev/null
@@ -0,0 +1,19 @@
+#ifndef ALL_H
+#define ALL_H
+
+const int MAX_ITEMS = 24;
+entity ITEMS[MAX_ITEMS];
+
+#define ITEMS_FOREACH(pred, body) do {      \
+    for (int i = 0; i < ITEM_COUNT; i++) {  \
+        const noref entity it = ITEMS[i];   \
+        if (pred) { body }                  \
+    }                                       \
+} while(0)
+
+void RegisterItems();
+void Dump_Items();
+
+#endif
+
+#include "inventory.qh"
diff --git a/qcsrc/common/items/inventory.qh b/qcsrc/common/items/inventory.qh
new file mode 100644 (file)
index 0000000..89abc97
--- /dev/null
@@ -0,0 +1,65 @@
+#ifndef INVENTORY_H
+#define INVENTORY_H
+
+#include "all.qh"
+#include "item/pickup.qh"
+
+entityclass(Inventory);
+/** Stores counts of items, the id being the index */
+class(Inventory) .int inv_items[MAX_ITEMS];
+
+/** Player inventory; Inventories also have one inventory for storing the previous state */
+.Inventory inventory;
+
+#ifdef CSQC
+void Inventory_Read(Inventory data)
+{
+    const int bits = ReadInt24_t();
+    ITEMS_FOREACH(bits & BIT(i), LAMBDA({
+        .int fld = inv_items[i];
+        int prev = data.(fld);
+        int next = data.(fld) = ReadByte();
+        dprintf("%s: %.0f -> %.0f\n", ITEMS[i].m_name, prev, next);
+    }));
+}
+#endif
+
+#ifdef SVQC
+void Inventory_Write(Inventory data)
+{
+    int bits = 0;
+    ITEMS_FOREACH(true, LAMBDA({
+        .int fld = inv_items[i];
+        bits = BITSET(bits, BIT(i), data.inventory.(fld) != (data.inventory.(fld) = data.(fld)));
+    }));
+    WriteInt24_t(MSG_ENTITY, bits);
+    ITEMS_FOREACH(bits & BIT(i), LAMBDA({
+        WriteByte(MSG_ENTITY, data.inv_items[i]);
+    }));
+}
+#endif
+
+#ifdef SVQC
+bool Inventory_Send(entity to, int sf)
+{
+    WriteByte(MSG_ENTITY, ENT_CLIENT_INVENTORY);
+    entity e = self.owner;
+    if (IS_SPEC(e)) e = e.enemy;
+    Inventory data = e.inventory;
+    Inventory_Write(data);
+    return true;
+}
+
+void Inventory_new(entity e)
+{
+    Inventory inv = new(Inventory), bak = new(Inventory);
+    inv.classname = "inventory", bak.classname = "inventory";
+    inv.inventory = bak;
+    inv.drawonlytoclient = e;
+    Net_LinkEntity((inv.owner = e).inventory = inv, false, 0, Inventory_Send);
+}
+void Inventory_delete(entity e) { remove(e.inventory.inventory); remove(e.inventory); }
+void Inventory_update(entity e) { e.inventory.SendFlags = 0xFFFFFF; }
+#endif
+
+#endif
diff --git a/qcsrc/common/items/item.qh b/qcsrc/common/items/item.qh
new file mode 100644 (file)
index 0000000..354bed2
--- /dev/null
@@ -0,0 +1,26 @@
+#ifndef GAMEITEM_H
+#define GAMEITEM_H
+#include "../oo.qh"
+#define ITEM_HANDLE(signal, ...) __Item_Send_##signal(__VA_ARGS__)
+CLASS(GameItem, Object)
+    ATTRIB(GameItem, m_id, int, 0)
+    METHOD(GameItem, show, void(entity this))
+    void GameItem_show(entity this) { print("A game item\n"); }
+    void ITEM_HANDLE(Show, entity this) { this.show(this); }
+ENDCLASS(GameItem)
+
+
+int ITEM_COUNT;
+/** If you register a new item, make sure to add it to all.inc */
+#define REGISTER_ITEM(id, class, body)          \
+    entity ITEM_##id;                           \
+    void RegisterItems_##id() {                 \
+        const entity this = NEW(class);         \
+        ITEM_##id = this;                       \
+        this.m_id = ITEM_COUNT;                 \
+        ITEMS[ITEM_COUNT++] = this;             \
+        body                                    \
+    }                                           \
+    ACCUMULATE_FUNCTION(RegisterItems, RegisterItems_##id)
+
+#endif
diff --git a/qcsrc/common/items/item/ammo.qc b/qcsrc/common/items/item/ammo.qc
new file mode 100644 (file)
index 0000000..032fcc3
--- /dev/null
@@ -0,0 +1,70 @@
+#include "ammo.qh"
+#ifdef SVQC
+    #include "../../../server/t_items.qh"
+#endif
+
+#define WITH(it) this.m_##it;
+#define CONFIGURE(...) MAP(WITH, __VA_ARGS__)
+#define DEFINE(id, ...)                                                 \
+    REGISTER_ITEM(id, Ammo, LAMBDA(                                     \
+        IF(SV, CONFIGURE                                                \
+        ,   respawntime         =       GET(g_pickup_respawntime_ammo)  \
+        ,   respawntimejitter   = GET(g_pickup_respawntimejitter_ammo)  \
+        )                                                               \
+        UNWORDS(__VA_ARGS__)                                            \
+    ))
+
+DEFINE(Bullets
+    ,APPLY(CONFIGURE
+    ,   model               =   "models/items/a_bullets.mdl"
+    ,   name                =   "bullets"
+    )
+    ,IF(SV, CONFIGURE
+    ,   botvalue            =   2000
+    ,   itemid              =   IT_NAILS
+    )
+)
+DEFINE(Cells
+    ,APPLY(CONFIGURE
+    ,   model               =   "models/items/a_cells.md3"
+    ,   name                =   "cells"
+    )
+    ,IF(SV, CONFIGURE
+    ,   botvalue            =   2000
+    ,   itemid              =   IT_CELLS
+    )
+)
+DEFINE(Plasma
+    ,APPLY(CONFIGURE
+    ,   model               =   "models/items/a_cells.md3"
+    ,   name                =   "plasma"
+    )
+    ,IF(SV, CONFIGURE
+    ,   botvalue            =   2000
+    ,   itemid              =   IT_PLASMA
+    )
+)
+DEFINE(Rockets
+    ,APPLY(CONFIGURE
+    ,   model               =   "models/items/a_rockets.md3"
+    ,   name                =   "rockets"
+    )
+    ,IF(SV, CONFIGURE
+    ,   botvalue            =   3000
+    ,   itemid              =   IT_ROCKETS
+    )
+)
+DEFINE(Shells
+    ,APPLY(CONFIGURE
+    ,   model               =   "models/items/a_shells.md3"
+    ,   name                =   "shells"
+    )
+    ,IF(SV, CONFIGURE
+    ,   botvalue            =   500
+    ,   itemid              =   IT_SHELLS
+    )
+)
+
+#undef WITH
+#undef CONFIGURE
+#undef DEFINE
diff --git a/qcsrc/common/items/item/ammo.qh b/qcsrc/common/items/item/ammo.qh
new file mode 100644 (file)
index 0000000..41e2ac8
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef AMMO_H
+#define AMMO_H
+#include "pickup.qh"
+CLASS(Ammo, Pickup)
+#ifdef SVQC
+    ATTRIB(Ammo, m_pickupevalfunc, float(entity player, entity item), commodity_pickupevalfunc)
+#endif
+ENDCLASS(Ammo)
+#endif
diff --git a/qcsrc/common/items/item/armor.qc b/qcsrc/common/items/item/armor.qc
new file mode 100644 (file)
index 0000000..8fed098
--- /dev/null
@@ -0,0 +1,68 @@
+#include "armor.qh"
+#ifdef SVQC
+    #include "../../../server/t_items.qh"
+#endif
+
+#define WITH(it) this.m_##it;
+#define CONFIGURE(...) MAP(WITH, __VA_ARGS__)
+#define DEFINE(id, ...) REGISTER_ITEM(id, Armor, UNWORDS(__VA_ARGS__))
+
+DEFINE(ArmorSmall
+    ,APPLY(CONFIGURE
+    ,   model               =   "models/items/item_armor_small.md3"
+    ,   sound               =   "misc/armor1.wav"
+    ,   name                =   "5 Armor"
+    )
+    ,IF(SV, CONFIGURE
+    ,   botvalue            =   BOT_PICKUP_RATING_LOW
+    ,   itemid              =   IT_ARMOR_SHARD
+    ,   respawntime         =         GET(g_pickup_respawntime_short)
+    ,   respawntimejitter   =   GET(g_pickup_respawntimejitter_short)
+    )
+)
+
+DEFINE(ArmorMedium
+    ,APPLY(CONFIGURE
+    ,   model               =   "models/items/item_armor_medium.md3"
+    ,   sound               =   "misc/armor10.wav"
+    ,   name                =   "25 Armor"
+    )
+    ,IF(SV, CONFIGURE
+    ,   botvalue            =   BOT_PICKUP_RATING_MID
+    ,   itemid              =   IT_ARMOR
+    ,   respawntime         =         GET(g_pickup_respawntime_medium)
+    ,   respawntimejitter   =   GET(g_pickup_respawntimejitter_medium)
+    )
+)
+
+DEFINE(ArmorBig
+    ,APPLY(CONFIGURE
+    ,   model               =   "models/items/item_armor_big.md3"
+    ,   sound               =   "misc/armor17_5.wav"
+    ,   name                =   "50 Armor"
+    )
+    ,IF(SV, CONFIGURE
+    ,   botvalue            =   20000 // FIXME: higher than BOT_PICKUP_RATING_HIGH?
+    ,   itemid              =   IT_ARMOR
+    ,   respawntime         =         GET(g_pickup_respawntime_long)
+    ,   respawntimejitter   =   GET(g_pickup_respawntimejitter_long)
+    )
+)
+
+DEFINE(ArmorLarge
+    ,APPLY(CONFIGURE
+    ,   model               =   "models/items/item_armor_large.md3"
+    ,   sound               =   "misc/armor25.wav"
+    ,   name                =   "100 Armor"
+    )
+    ,IF(SV, CONFIGURE
+    ,   botvalue            =   BOT_PICKUP_RATING_HIGH
+    ,   itemid              =   IT_ARMOR
+    ,   respawntime         =         GET(g_pickup_respawntime_long)
+    ,   respawntimejitter   =   GET(g_pickup_respawntimejitter_long)
+    )
+)
+
+#undef WITH
+#undef CONFIGURE
+#undef DEFINE
diff --git a/qcsrc/common/items/item/armor.qh b/qcsrc/common/items/item/armor.qh
new file mode 100644 (file)
index 0000000..48a80f8
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef ARMOR_H
+#define ARMOR_H
+#include "pickup.qh"
+CLASS(Armor, Pickup)
+#ifdef SVQC
+    ATTRIB(Armor, m_pickupevalfunc, float(entity player, entity item), commodity_pickupevalfunc)
+#endif
+ENDCLASS(Armor)
+#endif
diff --git a/qcsrc/common/items/item/buff.qc b/qcsrc/common/items/item/buff.qc
new file mode 100644 (file)
index 0000000..d9420d1
--- /dev/null
@@ -0,0 +1,3 @@
+#include "buff.qh"
+
+REGISTER_ITEM(DefaultBuff, Buff, LAMBDA())
diff --git a/qcsrc/common/items/item/buff.qh b/qcsrc/common/items/item/buff.qh
new file mode 100644 (file)
index 0000000..4ad93cb
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef BUFF_H
+#define BUFF_H
+#include "pickup.qh"
+CLASS(Buff, Pickup)
+    ATTRIB(Buff, m_name, string, "Buff")
+ENDCLASS(Buff)
+#endif
diff --git a/qcsrc/common/items/item/health.qc b/qcsrc/common/items/item/health.qc
new file mode 100644 (file)
index 0000000..08b422d
--- /dev/null
@@ -0,0 +1,68 @@
+#include "health.qh"
+#ifdef SVQC
+    #include "../../../server/t_items.qh"
+#endif
+
+#define WITH(it) this.m_##it;
+#define CONFIGURE(...) MAP(WITH, __VA_ARGS__)
+#define DEFINE(id, ...) REGISTER_ITEM(id, Health, UNWORDS(__VA_ARGS__))
+
+DEFINE(HealthSmall
+    ,APPLY(CONFIGURE
+    ,   model               =   "models/items/g_h1.md3"
+    ,   sound               =   "misc/minihealth.wav"
+    ,   name                =   "5 Health"
+    )
+    ,IF(SV, CONFIGURE
+    ,   botvalue            =   BOT_PICKUP_RATING_LOW
+    ,   itemid              =   IT_5HP
+    ,   respawntime         =         GET(g_pickup_respawntime_short)
+    ,   respawntimejitter   =   GET(g_pickup_respawntimejitter_short)
+    )
+)
+
+DEFINE(HealthMedium
+    ,APPLY(CONFIGURE
+    ,   model               =   "models/items/g_h25.md3"
+    ,   sound               =   "misc/mediumhealth.wav"
+    ,   name                =   "25 Health"
+    )
+    ,IF(SV, CONFIGURE
+    ,   botvalue            =   BOT_PICKUP_RATING_MID
+    ,   itemid              =   IT_25HP
+    ,   respawntime         =         GET(g_pickup_respawntime_short)
+    ,   respawntimejitter   =   GET(g_pickup_respawntimejitter_short)
+    )
+)
+
+DEFINE(HealthLarge
+    ,APPLY(CONFIGURE
+    ,   model               =   "models/items/g_h50.md3"
+    ,   sound               =   "misc/mediumhealth.wav"
+    ,   name                =   "50 Health"
+    )
+    ,IF(SV, CONFIGURE
+    ,   botvalue            =   BOT_PICKUP_RATING_MID
+    ,   itemid              =   IT_25HP
+    ,   respawntime         =         GET(g_pickup_respawntime_medium)
+    ,   respawntimejitter   =   GET(g_pickup_respawntimejitter_medium)
+    )
+)
+
+DEFINE(HealthMega
+    ,APPLY(CONFIGURE
+    ,   model               =   "models/items/g_h100.md3"
+    ,   sound               =   "misc/megahealth.wav"
+    ,   name                =   "100 Health"
+    )
+    ,IF(SV, CONFIGURE
+    ,   botvalue            =   BOT_PICKUP_RATING_HIGH
+    ,   itemid              =   IT_HEALTH
+    ,   respawntime         =         GET(g_pickup_respawntime_long)
+    ,   respawntimejitter   =   GET(g_pickup_respawntimejitter_long)
+    )
+)
+
+#undef WITH
+#undef CONFIGURE
+#undef DEFINE
diff --git a/qcsrc/common/items/item/health.qh b/qcsrc/common/items/item/health.qh
new file mode 100644 (file)
index 0000000..15f1f8d
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef HEALTH_H
+#define HEALTH_H
+#include "pickup.qh"
+CLASS(Health, Pickup)
+#ifdef SVQC
+    ATTRIB(Health, m_pickupevalfunc, float(entity player, entity item), commodity_pickupevalfunc)
+#endif
+ENDCLASS(Health)
+#endif
diff --git a/qcsrc/common/items/item/jetpack.qc b/qcsrc/common/items/item/jetpack.qc
new file mode 100644 (file)
index 0000000..9ff4ed0
--- /dev/null
@@ -0,0 +1,56 @@
+#ifdef SVQC
+    #include "../../../server/t_items.qh"
+    #include "../../../server/constants.qh"
+#endif
+
+#define WITH(it) this.m_##it;
+#define CONFIGURE(...) MAP(WITH, __VA_ARGS__)
+#define DEFINE(id, ...) REGISTER_ITEM(id, Pickup, UNWORDS(__VA_ARGS__))
+
+DEFINE(Jetpack
+    ,APPLY(CONFIGURE
+    ,   model               =   "models/items/g_jetpack.md3"
+    ,   name                =   "Jet pack"
+    )
+    ,IF(SV, CONFIGURE
+    ,   botvalue            =   BOT_PICKUP_RATING_LOW
+    ,   itemflags           =   FL_POWERUP
+    ,   itemid              =   IT_JETPACK
+    ,   pickupevalfunc      =   commodity_pickupevalfunc
+    ,   respawntime         =         GET(g_pickup_respawntime_powerup)
+    ,   respawntimejitter   =   GET(g_pickup_respawntimejitter_powerup)
+    )
+)
+
+DEFINE(JetpackFuel
+    ,APPLY(CONFIGURE
+    ,   model               =   "models/items/g_fuel.md3"
+    ,   name                =   "Fuel"
+    )
+    ,IF(SV, CONFIGURE
+    ,   botvalue            =   BOT_PICKUP_RATING_LOW
+    ,   itemid              =   IT_FUEL
+    ,   pickupevalfunc      =   commodity_pickupevalfunc
+    ,   respawntime         =         GET(g_pickup_respawntime_ammo)
+    ,   respawntimejitter   =   GET(g_pickup_respawntimejitter_ammo)
+    )
+)
+
+DEFINE(JetpackRegen
+    ,APPLY(CONFIGURE
+    ,   model               =   "models/items/g_fuelregen.md3"
+    ,   name                =   "Fuel regenerator"
+    )
+    ,IF(SV, CONFIGURE
+    ,   botvalue            =   BOT_PICKUP_RATING_LOW
+    ,   itemflags           =   FL_POWERUP
+    ,   itemid              =   IT_FUEL_REGEN
+    ,   pickupevalfunc      =   commodity_pickupevalfunc
+    ,   respawntime         =         GET(g_pickup_respawntime_powerup)
+    ,   respawntimejitter   =   GET(g_pickup_respawntimejitter_powerup)
+    )
+)
+
+#undef WITH
+#undef CONFIGURE
+#undef DEFINE
diff --git a/qcsrc/common/items/item/pickup.qc b/qcsrc/common/items/item/pickup.qc
new file mode 100644 (file)
index 0000000..35aac2b
--- /dev/null
@@ -0,0 +1,13 @@
+#include "pickup.qh"
+
+#ifdef SVQC
+bool ITEM_HANDLE(Pickup, entity this, entity item, entity player) {
+    bool b = this.giveTo(this, item, player);
+    if (b) {
+        dprintf("entity %i picked up %s\n", player, this.m_name);
+        player.inventory.inv_items[this.m_id]++;
+        Inventory_update(player);
+    }
+    return b;
+}
+#endif
diff --git a/qcsrc/common/items/item/pickup.qh b/qcsrc/common/items/item/pickup.qh
new file mode 100644 (file)
index 0000000..1875517
--- /dev/null
@@ -0,0 +1,44 @@
+#ifndef PICKUP_H
+#define PICKUP_H
+#include "../item.qh"
+CLASS(Pickup, GameItem)
+    ATTRIB(Pickup, m_model, string, string_null)
+    ATTRIB(Pickup, m_sound, string, "misc/itempickup.wav")
+    ATTRIB(Pickup, m_name, string, string_null)
+    METHOD(Pickup, show, void(entity this))
+    void Pickup_show(entity this) { printf("%s: %s\n", etos(this), this.m_name); }
+#ifdef SVQC
+    ATTRIB(Pickup, m_botvalue, int, 0)
+    ATTRIB(Pickup, m_itemflags, int, 0)
+    ATTRIB(Pickup, m_itemid, int, 0)
+    ATTRIB(Pickup, m_pickupevalfunc, float(entity player, entity item), generic_pickupevalfunc)
+    ATTRIB(Pickup, m_respawntime, float(), func_null)
+    ATTRIB(Pickup, m_respawntimejitter, float(), func_null)
+    METHOD(Pickup, giveTo, bool(entity this, entity item, entity player))
+    bool Pickup_giveTo(entity this, entity item, entity player) { return Item_GiveTo(item, player); }
+    bool ITEM_HANDLE(Pickup, entity this, entity item, entity player);
+#endif
+ENDCLASS(Pickup)
+
+#ifdef SVQC
+// For g_pickup_respawntime
+#include "../../../server/defs.qh"
+// Getters to dynamically retrieve the values of g_pickup_respawntime*
+GETTER(float, g_pickup_respawntime_weapon)
+GETTER(float, g_pickup_respawntime_superweapon)
+GETTER(float, g_pickup_respawntime_ammo)
+GETTER(float, g_pickup_respawntime_short)
+GETTER(float, g_pickup_respawntime_medium)
+GETTER(float, g_pickup_respawntime_long)
+GETTER(float, g_pickup_respawntime_powerup)
+GETTER(float, g_pickup_respawntimejitter_weapon)
+GETTER(float, g_pickup_respawntimejitter_superweapon)
+GETTER(float, g_pickup_respawntimejitter_ammo)
+GETTER(float, g_pickup_respawntimejitter_short)
+GETTER(float, g_pickup_respawntimejitter_medium)
+GETTER(float, g_pickup_respawntimejitter_long)
+GETTER(float, g_pickup_respawntimejitter_powerup)
+
+#endif
+
+#endif
diff --git a/qcsrc/common/items/item/powerup.qc b/qcsrc/common/items/item/powerup.qc
new file mode 100644 (file)
index 0000000..f10a97e
--- /dev/null
@@ -0,0 +1,40 @@
+#include "powerup.qh"
+#include "../../../server/t_items.qh"
+
+#define WITH(it) this.m_##it;
+#define CONFIGURE(...) MAP(WITH, __VA_ARGS__)
+#define DEFINE(id, ...)                                                     \
+    REGISTER_ITEM(id, Ammo, LAMBDA(                                         \
+        IF(SV, CONFIGURE                                                    \
+        ,   botvalue            =   100000                                  \
+        ,   itemflags           =   FL_POWERUP                              \
+        ,   respawntime         =         GET(g_pickup_respawntime_powerup) \
+        ,   respawntimejitter   =   GET(g_pickup_respawntimejitter_powerup) \
+        )                                                                   \
+        UNWORDS(__VA_ARGS__)                                          \
+    ))
+
+DEFINE(Strength
+    ,APPLY(CONFIGURE
+    ,   model               =   "models/items/g_strength.md3"
+    ,   sound               =   "misc/powerup.wav"
+    ,   name                =   "Strength Powerup"
+    )
+    ,IF(SV, CONFIGURE
+    ,   itemid              =   IT_STRENGTH
+    )
+)
+DEFINE(Shield
+    ,APPLY(CONFIGURE
+    ,   model               =   "models/items/g_invincible.md3"
+    ,   sound               =   "misc/powerup_shield.wav"
+    ,   name                =   "Shield"
+    )
+    ,IF(SV, CONFIGURE
+    ,   itemid              =   IT_INVINCIBLE
+    )
+)
+
+#undef WITH
+#undef CONFIGURE
+#undef DEFINE
diff --git a/qcsrc/common/items/item/powerup.qh b/qcsrc/common/items/item/powerup.qh
new file mode 100644 (file)
index 0000000..d27c1e6
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef POWERUP_H
+#define POWERUP_H
+#include "pickup.qh"
+CLASS(Powerup, Pickup)
+ENDCLASS(Powerup)
+
+#ifdef SVQC
+// For FL_POWERUP
+#include "../../../server/constants.qh"
+#endif
+
+#endif
index c3f15d1937e4963b06a1f6343c0d896c6ac44ce4..2e692d7268f9e7b55eefc8ea9c8c25d7c832825c 100644 (file)
@@ -3,7 +3,7 @@
     #include "../client/defs.qh"
     #include "util.qh"
     #include "buffs.qh"
-    #include "weapons/weapons.qh"
+    #include "weapons/all.qh"
     #include "mapinfo.qh"
 #elif defined(MENUQC)
 #elif defined(SVQC)
@@ -11,7 +11,7 @@
     #include "../dpdefs/dpextensions.qh"
     #include "util.qh"
     #include "buffs.qh"
-    #include "monsters/monsters.qh"
+    #include "monsters/all.qh"
     #include "mapinfo.qh"
 #endif
 
index 54255ec8d2aa153abfb6da7242d08b3635c40423..134103b89f3f9b49ea014916403ea772452ebf4b 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef MAPINFO_H
 #define MAPINFO_H
 
+#include "util.qh"
+
 int MAPINFO_TYPE_ALL;
 entity MapInfo_Type_first;
 entity MapInfo_Type_last;
@@ -10,7 +12,7 @@ entity MapInfo_Type_last;
 .string netname; // game type name as in cvar (with g_ prefix)
 .string mdl; // game type short name
 .string message; // human readable name
-.float team; // does this gametype support teamplay?
+.int team; // does this gametype support teamplay?
 .string model2; // game type defaults
 .string gametype_description; // game type description
 
diff --git a/qcsrc/common/monsters/all.inc b/qcsrc/common/monsters/all.inc
new file mode 100644 (file)
index 0000000..d30f298
--- /dev/null
@@ -0,0 +1,5 @@
+#include "monster/zombie.qc"
+#include "monster/spider.qc"
+#include "monster/mage.qc"
+#include "monster/wyvern.qc"
+#include "monster/shambler.qc"
diff --git a/qcsrc/common/monsters/all.qc b/qcsrc/common/monsters/all.qc
new file mode 100644 (file)
index 0000000..37dbcb3
--- /dev/null
@@ -0,0 +1,47 @@
+#include "all.qh"
+
+#include "all.inc"
+
+// MONSTER PLUGIN SYSTEM
+entity monster_info[MON_MAXCOUNT];
+entity dummy_monster_info;
+
+void register_monster(int id, float(float) func, int monsterflags, vector min_s, vector max_s, string modelname, string shortname, string mname)
+{
+       entity e;
+       monster_info[id - 1] = e = spawn();
+       e.classname = "monster_info";
+       e.monsterid = id;
+       e.netname = shortname;
+       e.monster_name = mname;
+       e.monster_func = func;
+       e.mdl = modelname;
+       e.spawnflags = monsterflags;
+       e.mins = min_s;
+       e.maxs = max_s;
+       e.model = strzone(strcat("models/monsters/", modelname));
+}
+float m_null(float dummy) { return 0; }
+void register_monsters_done()
+{
+       dummy_monster_info = spawn();
+       dummy_monster_info.classname = "monster_info";
+       dummy_monster_info.monsterid = 0; // you can recognize dummies by this
+       dummy_monster_info.netname = "";
+       dummy_monster_info.monster_name = "Monster";
+       dummy_monster_info.monster_func = m_null;
+       dummy_monster_info.mdl = "";
+       dummy_monster_info.mins = '-0 -0 -0';
+       dummy_monster_info.maxs = '0 0 0';
+       dummy_monster_info.model = "";
+}
+entity get_monsterinfo(int id)
+{
+       entity m;
+       if(id < MON_FIRST || id > MON_LAST)
+               return dummy_monster_info;
+       m = monster_info[id - 1];
+       if(m)
+               return m;
+       return dummy_monster_info;
+}
index c79a4e656c4033131542558bd4b49ec9a5a56869..ce02312f1d4a414a11014c618b32cf5816df0320 100644 (file)
@@ -1,11 +1,73 @@
-// TODO: include once
-//#ifndef MONSTERS_ALL_H
-//#define MONSTERS_ALL_H
+#ifndef MONSTERS_ALL_H
+#define MONSTERS_ALL_H
 
-#include "monster/zombie.qc"
-#include "monster/spider.qc"
-#include "monster/mage.qc"
-#include "monster/wyvern.qc"
-#include "monster/shambler.qc"
+#include "../util.qh"
 
-//#endif
+// monster requests
+const int MR_SETUP = 1; // (SERVER) setup monster data
+const int MR_THINK = 2; // (SERVER) logic to run every frame
+const int MR_DEATH = 3; // (SERVER) called when monster dies
+const int MR_PRECACHE = 4; // (BOTH) precaches models/sounds used by this monster
+
+// functions:
+entity get_monsterinfo(float id);
+
+// special spawn flags
+const int MONSTER_RESPAWN_DEATHPOINT = 16; // re-spawn where we died
+const int MONSTER_TYPE_FLY = 32;
+const int MONSTER_TYPE_SWIM = 64;
+const int MONSTER_SIZE_BROKEN = 128; // TODO: remove when bad models are replaced
+const int MON_FLAG_SUPERMONSTER = 256; // incredibly powerful monster
+const int MON_FLAG_RANGED = 512; // monster shoots projectiles
+const int MON_FLAG_MELEE = 1024;
+
+// entity properties of monsterinfo:
+.float monsterid; // MON_...
+.string netname; // short name
+.string monster_name; // human readable name
+.float(float) monster_func; // m_...
+.string mdl; // currently a copy of the model
+.string model; // full name of model
+.int spawnflags;
+.vector mins, maxs; // monster hitbox size
+
+// other useful macros
+#define MON_ACTION(monstertype,mrequest) (get_monsterinfo(monstertype)).monster_func(mrequest)
+#define M_NAME(monstertype) (get_monsterinfo(monstertype)).monster_name
+
+// =====================
+//     Monster Registration
+// =====================
+
+float m_null(float dummy);
+void register_monster(float id, float(float) func, float monsterflags, vector min_s, vector max_s, string modelname, string shortname, string mname);
+void register_monsters_done();
+
+const int MON_MAXCOUNT = 24;
+const int MON_FIRST = 1;
+int MON_COUNT;
+int MON_LAST;
+
+#define REGISTER_MONSTER_2(id,func,monsterflags,min_s,max_s,modelname,shortname,mname) \
+       int id; \
+       float func(float); \
+       void RegisterMonsters_##id() \
+       { \
+               MON_LAST = (id = MON_FIRST + MON_COUNT); \
+               ++MON_COUNT; \
+               register_monster(id,func,monsterflags,min_s,max_s,modelname,shortname,mname); \
+       } \
+       ACCUMULATE_FUNCTION(RegisterMonsters, RegisterMonsters_##id)
+#ifdef MENUQC
+#define REGISTER_MONSTER(id,func,monsterflags,min_s,max_s,modelname,shortname,mname) \
+       REGISTER_MONSTER_2(MON_##id,m_null,monsterflags,min_s,max_s,modelname,shortname,mname)
+#else
+#define REGISTER_MONSTER(id,func,monsterflags,min_s,max_s,modelname,shortname,mname) \
+       REGISTER_MONSTER_2(MON_##id,func,monsterflags,min_s,max_s,modelname,shortname,mname)
+#endif
+
+#include "all.inc"
+
+#undef REGISTER_MONSTER
+ACCUMULATE_FUNCTION(RegisterMonsters, register_monsters_done);
+#endif
index 12ff5dc891de1be28de7d0e1e083bca4f4cd5337..1858b9bd114669237f96c03e0bd355d679ae772e 100644 (file)
@@ -86,7 +86,7 @@ void shambler_lightning_explode()
        self.nextthink = time + 0.2;
 }
 
-void shambler_lightning_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
+void shambler_lightning_damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
 {
        if (self.health <= 0)
                return;
diff --git a/qcsrc/common/monsters/monsters.qc b/qcsrc/common/monsters/monsters.qc
deleted file mode 100644 (file)
index 096c2e5..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-#include "monsters.qh"
-
-#include "all.qh"
-
-// MONSTER PLUGIN SYSTEM
-entity monster_info[MON_MAXCOUNT];
-entity dummy_monster_info;
-
-void register_monster(int id, float(float) func, int monsterflags, vector min_s, vector max_s, string modelname, string shortname, string mname)
-{
-       entity e;
-       monster_info[id - 1] = e = spawn();
-       e.classname = "monster_info";
-       e.monsterid = id;
-       e.netname = shortname;
-       e.monster_name = mname;
-       e.monster_func = func;
-       e.mdl = modelname;
-       e.spawnflags = monsterflags;
-       e.mins = min_s;
-       e.maxs = max_s;
-       e.model = strzone(strcat("models/monsters/", modelname));
-}
-float m_null(float dummy) { return 0; }
-void register_monsters_done()
-{
-       dummy_monster_info = spawn();
-       dummy_monster_info.classname = "monster_info";
-       dummy_monster_info.monsterid = 0; // you can recognize dummies by this
-       dummy_monster_info.netname = "";
-       dummy_monster_info.monster_name = "Monster";
-       dummy_monster_info.monster_func = m_null;
-       dummy_monster_info.mdl = "";
-       dummy_monster_info.mins = '-0 -0 -0';
-       dummy_monster_info.maxs = '0 0 0';
-       dummy_monster_info.model = "";
-}
-entity get_monsterinfo(int id)
-{
-       entity m;
-       if(id < MON_FIRST || id > MON_LAST)
-               return dummy_monster_info;
-       m = monster_info[id - 1];
-       if(m)
-               return m;
-       return dummy_monster_info;
-}
diff --git a/qcsrc/common/monsters/monsters.qh b/qcsrc/common/monsters/monsters.qh
deleted file mode 100644 (file)
index 6fa9dfa..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-#ifndef MONSTERS_H
-#define MONSTERS_H
-
-// monster requests
-const int MR_SETUP = 1; // (SERVER) setup monster data
-const int MR_THINK = 2; // (SERVER) logic to run every frame
-const int MR_DEATH = 3; // (SERVER) called when monster dies
-const int MR_PRECACHE = 4; // (BOTH) precaches models/sounds used by this monster
-
-// functions:
-entity get_monsterinfo(float id);
-
-// special spawn flags
-const int MONSTER_RESPAWN_DEATHPOINT = 16; // re-spawn where we died
-const int MONSTER_TYPE_FLY = 32;
-const int MONSTER_TYPE_SWIM = 64;
-const int MONSTER_SIZE_BROKEN = 128; // TODO: remove when bad models are replaced
-const int MON_FLAG_SUPERMONSTER = 256; // incredibly powerful monster
-const int MON_FLAG_RANGED = 512; // monster shoots projectiles
-const int MON_FLAG_MELEE = 1024;
-
-// entity properties of monsterinfo:
-.float monsterid; // MON_...
-.string netname; // short name
-.string monster_name; // human readable name
-.float(float) monster_func; // m_...
-.string mdl; // currently a copy of the model
-.string model; // full name of model
-.int spawnflags;
-.vector mins, maxs; // monster hitbox size
-
-// other useful macros
-#define MON_ACTION(monstertype,mrequest) (get_monsterinfo(monstertype)).monster_func(mrequest)
-#define M_NAME(monstertype) (get_monsterinfo(monstertype)).monster_name
-
-// =====================
-//     Monster Registration
-// =====================
-
-float m_null(float dummy);
-void register_monster(float id, float(float) func, float monsterflags, vector min_s, vector max_s, string modelname, string shortname, string mname);
-void register_monsters_done();
-
-const int MON_MAXCOUNT = 24;
-const int MON_FIRST = 1;
-int MON_COUNT;
-int MON_LAST;
-
-#define REGISTER_MONSTER_2(id,func,monsterflags,min_s,max_s,modelname,shortname,mname) \
-       int id; \
-       float func(float); \
-       void RegisterMonsters_##id() \
-       { \
-               MON_LAST = (id = MON_FIRST + MON_COUNT); \
-               ++MON_COUNT; \
-               register_monster(id,func,monsterflags,min_s,max_s,modelname,shortname,mname); \
-       } \
-       ACCUMULATE_FUNCTION(RegisterMonsters, RegisterMonsters_##id)
-#ifdef MENUQC
-#define REGISTER_MONSTER(id,func,monsterflags,min_s,max_s,modelname,shortname,mname) \
-       REGISTER_MONSTER_2(MON_##id,m_null,monsterflags,min_s,max_s,modelname,shortname,mname)
-#else
-#define REGISTER_MONSTER(id,func,monsterflags,min_s,max_s,modelname,shortname,mname) \
-       REGISTER_MONSTER_2(MON_##id,func,monsterflags,min_s,max_s,modelname,shortname,mname)
-#endif
-
-#include "all.qh"
-
-#undef REGISTER_MONSTER
-ACCUMULATE_FUNCTION(RegisterMonsters, register_monsters_done);
-#endif
index 8aee54b98084fe36279553eb5ab761f7de4046af..5bfef1b8f574ab407250f1ba0433df9346488658 100644 (file)
@@ -3,7 +3,7 @@
 #elif defined(SVQC)
        #include "../../dpdefs/progsdefs.qh"
     #include "../util.qh"
-    #include "monsters.qh"
+    #include "all.qh"
     #include "sv_monsters.qh"
     #include "spawn.qh"
     #include "../../server/autocvars.qh"
index 28430e9617e8a9a6666519a444d39df47303a103..239f8fe9a7f57bf06f2f861f0544683e0774bda7 100644 (file)
@@ -7,18 +7,19 @@
     #include "../constants.qh"
     #include "../teams.qh"
     #include "../util.qh"
-    #include "monsters.qh"
+    #include "all.qh"
     #include "sv_monsters.qh"
-    #include "../weapons/weapons.qh"
+    #include "../weapons/all.qh"
     #include "../../server/autocvars.qh"
     #include "../../server/defs.qh"
     #include "../deathtypes.qh"
     #include "../../server/mutators/mutators_include.qh"
     #include "../../server/tturrets/include/turrets_early.qh"
-    #include "../../server/vehicles/vehicles_def.qh"
+    #include "../../server/vehicles/vehicle.qh"
     #include "../../server/campaign.qh"
     #include "../../server/command/common.qh"
     #include "../../server/command/cmd.qh"
+       #include "../triggers/triggers.qh"
     #include "../../csqcmodellib/sv_model.qh"
     #include "../../server/round_handler.qh"
     #include "../../server/tturrets/include/turrets.qh"
@@ -275,9 +276,9 @@ float LoadMonsterSounds(string f, float first)
                field = GetMonsterSoundSampleField(argv(0));
                if(GetMonsterSoundSampleField_notFound)
                        continue;
-               if(self.field)
-                       strunzone(self.field);
-               self.field = strzone(strcat(argv(1), " ", argv(2)));
+               if (self.(field))
+                       strunzone(self.(field));
+               self.(field) = strzone(strcat(argv(1), " ", argv(2)));
        }
        fclose(fh);
        return 1;
@@ -305,7 +306,7 @@ void MonsterSound(.string samplefield, float sound_delay, float delaytoo, float
        if(delaytoo)
        if(time < self.msound_delay)
                return; // too early
-       GlobalSound(self.samplefield, chan, VOICETYPE_PLAYERSOUND);
+       GlobalSound(self.(samplefield), chan, VOICETYPE_PLAYERSOUND);
 
        self.msound_delay = time + sound_delay;
 }
@@ -321,7 +322,7 @@ void monster_makevectors(entity e)
        makevectors(self.v_angle);
 }
 
-float monster_melee(entity targ, float damg, float anim, float er, float anim_finished, float deathtype, float dostop)
+float monster_melee(entity targ, float damg, float anim, float er, float anim_finished, int deathtype, float dostop)
 {
        if (self.health <= 0)
                return false; // attacking while dead?!
@@ -910,7 +911,7 @@ void monsters_reset()
        self.moveto = self.origin;
 }
 
-void monsters_corpse_damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
+void monsters_corpse_damage (entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
 {
        self.health -= damage;
 
@@ -979,7 +980,7 @@ void monster_die(entity attacker, float gibbed)
        MON_ACTION(self.monsterid, MR_DEATH);
 }
 
-void monsters_damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
+void monsters_damage (entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
 {
        if(self.frozen && deathtype != DEATH_KILL && deathtype != DEATH_NADE_ICE_FREEZE)
                return;
index f6b149816e27725278d9f781e9bf8aff956034cb..697c07b72ea02197831154a4f9e560d1869c1b0e 100644 (file)
@@ -93,7 +93,7 @@ const int MONSTER_STATE_ATTACK_MELEE = 2;
 float monster_initialize(float mon_id);
 float monster_leap (float anm, void() touchfunc, vector vel, float anim_finished);
 void monster_makevectors(entity e);
-float monster_melee(entity targ, float damg, float anim, float er, float anim_finished, float deathtype, float dostop);
+float monster_melee(entity targ, float damg, float anim, float er, float anim_finished, int deathtype, float dostop);
 void monster_move(float runspeed, float walkspeed, float stopspeed, float manim_run, float manim_walk, float manim_idle);
 void monster_setupcolors(entity mon);
 float Monster_SkillModifier();
diff --git a/qcsrc/common/movetypes/follow.qc b/qcsrc/common/movetypes/follow.qc
new file mode 100644 (file)
index 0000000..6cf28d6
--- /dev/null
@@ -0,0 +1,31 @@
+void _Movetype_Physics_Follow() // SV_Physics_Follow
+{
+       entity e = self.move_aiment; // TODO: networking?
+
+       // LordHavoc: implemented rotation on MOVETYPE_FOLLOW objects
+       if(self.move_angles == self.move_punchangle)
+       {
+               self.move_origin = e.move_origin + self.view_ofs;
+       }
+       else
+       {
+               vector ang, v;
+               ang_x = -self.move_punchangle_x;
+               ang_y = self.move_punchangle_y;
+               ang_z = self.move_punchangle_z;
+               makevectors(ang);
+               v_x = self.view_ofs_x * v_forward_x + self.view_ofs_y * v_right_x + self.view_ofs_z * v_up_x;
+               v_y = self.view_ofs_x * v_forward_y + self.view_ofs_y * v_right_y + self.view_ofs_z * v_up_y;
+               v_z = self.view_ofs_x * v_forward_z + self.view_ofs_y * v_right_z + self.view_ofs_z * v_up_z;
+               ang_x = -e.move_angles_x;
+               ang_y = e.move_angles_y;
+               ang_z = e.move_angles_z;
+               makevectors(ang);
+               self.move_origin_x = v_x * v_forward_x + v_y * v_forward_y + v_z * v_forward_z + e.move_origin_x;
+               self.move_origin_x = v_x * v_right_x + v_y * v_right_y + v_z * v_right_z + e.move_origin_y;
+               self.move_origin_x = v_x * v_up_x + v_y * v_up_y + v_z * v_up_z + e.move_origin_z;
+       }
+
+       self.move_angles = e.move_angles + self.v_angle;
+       _Movetype_LinkEdict(false);
+}
diff --git a/qcsrc/common/movetypes/include.qc b/qcsrc/common/movetypes/include.qc
new file mode 100644 (file)
index 0000000..322b3c4
--- /dev/null
@@ -0,0 +1,7 @@
+#include "push.qc"
+#include "toss.qc"
+#include "walk.qc"
+#include "step.qc"
+#include "follow.qc"
+
+#include "movetypes.qc"
diff --git a/qcsrc/common/movetypes/include.qh b/qcsrc/common/movetypes/include.qh
new file mode 100644 (file)
index 0000000..a96e595
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef MOVETYPES_INCLUDE_H
+#define MOVETYPES_INCLUDE_H
+
+#include "push.qh"
+#include "toss.qh"
+#include "walk.qh"
+
+#endif
diff --git a/qcsrc/common/movetypes/movetypes.qc b/qcsrc/common/movetypes/movetypes.qc
new file mode 100644 (file)
index 0000000..3dd286e
--- /dev/null
@@ -0,0 +1,683 @@
+#include "include.qh"
+#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 "../../server/t_items.qh"
+#elif defined(MENUQC)
+#elif defined(SVQC)
+       #include "../../server/autocvars.qh"
+#endif
+
+void _Movetype_WallFriction(vector stepnormal)  // SV_WallFriction
+{
+       /*float d, i;
+       vector into, side;
+       makevectors(self.v_angle);
+       d = (stepnormal * v_forward) + 0.5;
+
+       if(d < 0)
+       {
+           i = (stepnormal * self.move_velocity);
+           into = i * stepnormal;
+           side = self.move_velocity - into;
+           self.move_velocity_x = side.x * (1 * d);
+           self.move_velocity_y = side.y * (1 * d);
+       }*/
+}
+
+vector planes[MAX_CLIP_PLANES];
+int _Movetype_FlyMove(float dt, bool applygravity, vector stepnormal, float stepheight) // SV_FlyMove
+{
+       int blocked = 0, bumpcount;
+       int i, j, numplanes = 0;
+       float time_left = dt, grav = 0;
+       vector push;
+       vector primal_velocity, original_velocity, new_velocity = '0 0 0', restore_velocity;
+
+       for(i = 0; i <= MAX_CLIP_PLANES; ++i)
+               planes[i] = '0 0 0';
+       
+       grav = 0;
+
+       restore_velocity = self.move_velocity;
+
+       if(applygravity)
+       {
+               self.move_didgravity = 1;
+               grav = dt * (PHYS_ENTGRAVITY(self) ? PHYS_ENTGRAVITY(self) : 1) * PHYS_GRAVITY;
+
+               if(!GAMEPLAYFIX_NOGRAVITYONGROUND || !(self.move_flags & FL_ONGROUND))
+               {
+                       if(GRAVITY_UNAFFECTED_BY_TICRATE)
+                               self.move_velocity_z -= grav * 0.5;
+                       else
+                               self.move_velocity_z -= grav;
+               }
+       }
+
+       original_velocity = primal_velocity = self.move_velocity;
+
+       for(bumpcount = 0;bumpcount < MAX_CLIP_PLANES;bumpcount++)
+       {
+               if(!self.move_velocity_x && !self.move_velocity_y && !self.move_velocity_z)
+                       break;
+
+               push = self.move_velocity * time_left;
+               if(!_Movetype_PushEntity(push, false))
+               {
+                       // we got teleported by a touch function
+                       // let's abort the move
+                       blocked |= 8;
+                       break;
+               }
+
+               // this code is used by MOVETYPE_WALK and MOVETYPE_STEP and SV_UnstickEntity
+               // abort move if we're stuck in the world (and didn't make it out)
+               if(trace_startsolid && trace_allsolid)
+               {
+                       self.move_velocity = restore_velocity;
+                       return 3;
+               }
+
+               if(trace_fraction == 1)
+                       break;
+               if(trace_plane_normal_z)
+               {
+                       if(trace_plane_normal_z > 0.7)
+                       {
+                               // floor
+                               blocked |= 1;
+
+                               if(!trace_ent)
+                               {
+                                       //dprint("_Movetype_FlyMove: !trace_ent\n");
+                                       trace_ent = world;
+                               }
+
+                               self.move_flags |= FL_ONGROUND;
+                               self.move_groundentity = trace_ent;
+                       }
+               }
+               else if(stepheight)
+               {
+                       // step - handle it immediately
+                       vector org;
+                       vector steppush;
+                       //Con_Printf("step %f %f %f : ", self.move_origin_x, PRVM_serveredictvector(ent, origin)[1], PRVM_serveredictvector(ent, origin)[2]);
+                       steppush = '0 0 1' * stepheight;
+                       org = self.move_origin;
+                       if(!_Movetype_PushEntity(steppush, false))
+                       {
+                               blocked |= 8;
+                               break;
+                       }
+                       //Con_Printf("%f %f %f : ", self.move_origin_x, PRVM_serveredictvector(ent, origin)[1], PRVM_serveredictvector(ent, origin)[2]);
+                       if(!_Movetype_PushEntity(push, false))
+                       {
+                               blocked |= 8;
+                               break;
+                       }
+                       float trace2_fraction = trace_fraction;
+                       //Con_Printf("%f %f %f : ", self.move_origin_x, PRVM_serveredictvector(ent, origin)[1], PRVM_serveredictvector(ent, origin)[2]);
+                       steppush = '0 0 1' * (org_z - self.move_origin_z);
+                       if(!_Movetype_PushEntity(steppush, false))
+                       {
+                               blocked |= 8;
+                               break;
+                       }
+                       //Con_Printf("%f %f %f : ", self.move_origin_x, PRVM_serveredictvector(ent, origin)[1], PRVM_serveredictvector(ent, origin)[2]);
+                       // accept the new position if it made some progress...
+                       if(fabs(self.move_origin_x - org_x) >= 0.03125 || fabs(self.move_origin_y - org_y) >= 0.03125)
+                       {
+                               //Con_Printf("accepted (delta %f %f %f)\n", self.move_origin_x - org_x, PRVM_serveredictvector(ent, origin)[1] - org[1], PRVM_serveredictvector(ent, origin)[2] - org[2]);
+                               trace_endpos = self.move_origin;
+                               time_left *= 1 - trace2_fraction;
+                               numplanes = 0;
+                               continue;
+                       }
+                       else
+                       {
+                               //Con_Printf("REJECTED (delta %f %f %f)\n", self.move_origin_x - org_x, PRVM_serveredictvector(ent, origin)[1] - org[1], PRVM_serveredictvector(ent, origin)[2] - org[2]);
+                               self.move_origin = org;
+                       }
+               }
+               else
+               {
+                       // step - return it to caller
+                       blocked |= 2;
+                       // save the trace for player extrafriction
+                       if(stepnormal)
+                               stepnormal = trace_plane_normal;
+               }
+               if(trace_fraction >= 0.001)
+               {
+                       // actually covered some distance
+                       original_velocity = self.move_velocity;
+                       numplanes = 0;
+               }
+
+               time_left *= 1 - trace_fraction;
+
+               // clipped to another plane
+               if(numplanes >= MAX_CLIP_PLANES)
+               {
+                       // this shouldn't really happen
+                       self.move_velocity = '0 0 0';
+                       blocked = 3;
+                       break;
+               }
+
+               planes[numplanes] = trace_plane_normal;
+               numplanes++;
+
+               // modify original_velocity so it parallels all of the clip planes
+               for (i = 0;i < numplanes;i++)
+               {
+                       new_velocity = _Movetype_ClipVelocity(original_velocity, planes[i], 1);
+                       for (j = 0;j < numplanes;j++)
+                       {
+                               if(j != i)
+                               {
+                                       // not ok
+                                       if((new_velocity * planes[j]) < 0)
+                                               break;
+                               }
+                       }
+                       if(j == numplanes)
+                               break;
+               }
+
+               if(i != numplanes)
+               {
+                       // go along this plane
+                       self.move_velocity = new_velocity;
+               }
+               else
+               {
+                       // go along the crease
+                       if(numplanes != 2)
+                       {
+                               self.move_velocity = '0 0 0';
+                               blocked = 7;
+                               break;
+                       }
+                       vector dir;
+                       dir.x = planes[0].y * planes[1].z - planes[0].z * planes[1].y;
+                       dir.y = planes[0].z * planes[1].x - planes[0].x * planes[1].z;
+                       dir.z = planes[0].x * planes[1].y - planes[0].y * planes[1].x;
+                       // LordHavoc: thanks to taniwha of QuakeForge for pointing out this fix for slowed falling in corners
+                       float ilength = sqrt((dir * dir));
+                       if(ilength)
+                               ilength = 1.0 / ilength;
+                       dir.x *= ilength;
+                       dir.y *= ilength;
+                       dir.z *= ilength;
+                       float d = (dir * self.move_velocity);
+                       self.move_velocity = dir * d;
+               }
+
+               // if current velocity is against the original velocity,
+               // stop dead to avoid tiny occilations in sloping corners
+               if((self.move_velocity * primal_velocity) <= 0)
+               {
+                       self.move_velocity = '0 0 0';
+                       break;
+               }
+       }
+
+       // LordHavoc: this came from QW and allows you to get out of water more easily
+       if(GAMEPLAYFIX_EASIERWATERJUMP && (self.move_flags & FL_WATERJUMP) && !(blocked & 8))
+               self.move_velocity = primal_velocity;
+
+       if(applygravity)
+       {
+               if(!GAMEPLAYFIX_NOGRAVITYONGROUND || !(self.move_flags & FL_ONGROUND))
+               {
+                       if(GRAVITY_UNAFFECTED_BY_TICRATE)
+                               self.move_velocity_z -= grav * 0.5f;
+               }
+       }
+
+       return blocked;
+}
+
+void _Movetype_CheckVelocity()  // SV_CheckVelocity
+{
+       // if(vlen(self.move_velocity) < 0.0001)
+       // self.move_velocity = '0 0 0';
+}
+
+bool _Movetype_CheckWater(entity ent)  // SV_CheckWater
+{
+       vector point = ent.move_origin;
+       point.z += (ent.mins.z + 1);
+
+       int nativecontents = pointcontents(point);
+       if(ent.move_watertype && ent.move_watertype != nativecontents)
+       {
+               // dprintf("_Movetype_CheckWater(): Original: '%d', New: '%d'\n", ent.move_watertype, nativecontents);
+               if(ent.contentstransition)
+                       ent.contentstransition(ent.move_watertype, nativecontents);
+       }
+
+       ent.move_waterlevel = 0;
+       ent.move_watertype = CONTENT_EMPTY;
+
+       int supercontents = Mod_Q1BSP_SuperContentsFromNativeContents(nativecontents);
+       if(supercontents & DPCONTENTS_LIQUIDSMASK)
+       {
+               ent.move_watertype = nativecontents;
+               ent.move_waterlevel = 1;
+               point.y = (ent.origin.y + ((ent.mins.z + ent.maxs.y) * 0.5));
+               if(Mod_Q1BSP_SuperContentsFromNativeContents(pointcontents(point)) & DPCONTENTS_LIQUIDSMASK)
+               {
+                       ent.move_waterlevel = 2;
+                       point.y = ent.origin.y + ent.view_ofs.y;
+                       if(Mod_Q1BSP_SuperContentsFromNativeContents(pointcontents(point)) & DPCONTENTS_LIQUIDSMASK)
+                               ent.move_waterlevel = 3;
+               }
+       }
+
+       return ent.move_waterlevel > 1;
+}
+
+void _Movetype_CheckWaterTransition(entity ent)  // SV_CheckWaterTransition
+{
+       int contents = pointcontents(ent.move_origin);
+
+       if(!ent.move_watertype)
+       {
+               // just spawned here
+               if(!autocvar_cl_gameplayfix_fixedcheckwatertransition)
+               {
+                       ent.move_watertype = contents;
+                       ent.move_waterlevel = 1;
+                       return;
+               }
+       }
+       else if(ent.move_watertype != contents)
+       {
+               // dprintf("_Movetype_CheckWaterTransition(): Origin: %s, Direct: '%d', Original: '%d', New: '%d'\n", vtos(ent.move_origin), pointcontents(ent.move_origin), ent.move_watertype, contents);
+               if(ent.contentstransition)
+                       ent.contentstransition(ent.move_watertype, contents);
+       }
+
+       if(contents <= CONTENT_WATER)
+       {
+               ent.move_watertype = contents;
+               ent.move_waterlevel = 1;
+       }
+       else
+       {
+               ent.move_watertype = CONTENT_EMPTY;
+               ent.move_waterlevel = (autocvar_cl_gameplayfix_fixedcheckwatertransition ? 0 : contents);
+       }
+}
+
+void _Movetype_Impact(entity oth)  // SV_Impact
+{
+       entity oldself = self;
+       entity oldother = other;
+
+       if(self.move_touch)
+       {
+               other = oth;
+
+               self.move_touch();
+
+               other = oldother;
+       }
+
+       if(oth.move_touch)
+       {
+               other = self;
+               self = oth;
+
+               self.move_touch();
+
+               self = oldself;
+               other = oldother;
+       }
+}
+
+void _Movetype_LinkEdict_TouchAreaGrid()  // SV_LinkEdict_TouchAreaGrid
+{
+       entity oldself = self;
+       entity oldother = other;
+
+       for (entity e = findradius(0.5 * (self.absmin + self.absmax), 0.5 * vlen(self.absmax - self.absmin)); e; e = e.chain)
+       {
+               if(e.move_touch && boxesoverlap(e.absmin, e.absmax, oldself.absmin, oldself.absmax))
+               {
+                       self = e;
+                       other = oldself;
+
+                       trace_allsolid = false;
+                       trace_startsolid = false;
+                       trace_fraction = 1;
+                       trace_inwater = false;
+                       trace_inopen = true;
+                       trace_endpos = e.origin;
+                       trace_plane_normal = '0 0 1';
+                       trace_plane_dist = 0;
+                       trace_ent = oldself;
+
+                       e.move_touch();
+               }
+       }
+
+       other = oldother;
+       self = oldself;
+}
+
+void _Movetype_LinkEdict(bool touch_triggers)  // SV_LinkEdict
+{
+       vector mi, ma;
+       if(self.solid == SOLID_BSP)
+       {
+               // TODO set the absolute bbox
+               mi = self.mins;
+               ma = self.maxs;
+       }
+       else
+       {
+               mi = self.mins;
+               ma = self.maxs;
+       }
+       mi += self.move_origin;
+       ma += self.move_origin;
+
+       if(self.move_flags & FL_ITEM)
+       {
+               mi.x -= 15;
+               mi.y -= 15;
+               mi.z -= 1;
+               ma.x += 15;
+               ma.y += 15;
+               ma.z += 1;
+       }
+       else
+       {
+               mi.x -= 1;
+               mi.y -= 1;
+               mi.z -= 1;
+               ma.x += 1;
+               ma.y += 1;
+               ma.z += 1;
+       }
+
+       self.absmin = mi;
+       self.absmax = ma;
+
+       if(touch_triggers)
+               _Movetype_LinkEdict_TouchAreaGrid();
+}
+
+bool _Movetype_TestEntityPosition(vector ofs)  // SV_TestEntityPosition
+{
+//     vector org = self.move_origin + ofs;
+
+       int cont = self.dphitcontentsmask;
+       self.dphitcontentsmask = DPCONTENTS_SOLID;
+       tracebox(self.move_origin, self.mins, self.maxs, self.move_origin, MOVE_NOMONSTERS, self);
+       self.dphitcontentsmask = cont;
+
+       if(trace_startsolid)
+               return true;
+
+       if(vlen(trace_endpos - self.move_origin) > 0.0001)
+               self.move_origin = trace_endpos;
+       return false;
+}
+
+bool _Movetype_UnstickEntity()  // SV_UnstickEntity
+{
+       if(!_Movetype_TestEntityPosition('0 0 0')) return true;
+       if(!_Movetype_TestEntityPosition('-1 0 0')) goto success;
+       if(!_Movetype_TestEntityPosition('1 0 0')) goto success;
+       if(!_Movetype_TestEntityPosition('0 -1 0')) goto success;
+       if(!_Movetype_TestEntityPosition('0 1 0')) goto success;
+       if(!_Movetype_TestEntityPosition('-1 -1 0')) goto success;
+       if(!_Movetype_TestEntityPosition('1 -1 0')) goto success;
+       if(!_Movetype_TestEntityPosition('-1 1 0')) goto success;
+       if(!_Movetype_TestEntityPosition('1 1 0')) goto success;
+       for (int i = 1; i <= 17; ++i)
+       {
+               if(!_Movetype_TestEntityPosition('0 0 -1' * i)) goto success;
+               if(!_Movetype_TestEntityPosition('0 0 1' * i)) goto success;
+       }
+       dprintf("Can't unstick an entity (edict: %d, classname: %s, origin: %s)\n",
+               num_for_edict(self), self.classname, vtos(self.move_origin));
+       return false;
+       : success;
+       dprintf("Sucessfully unstuck an entity (edict: %d, classname: %s, origin: %s)\n",
+               num_for_edict(self), self.classname, vtos(self.move_origin));
+       _Movetype_LinkEdict(true);
+       return true;
+}
+
+vector _Movetype_ClipVelocity(vector vel, vector norm, float f)  // SV_ClipVelocity
+{
+       vel -= ((vel * norm) * norm) * f;
+
+       if(vel.x > -0.1 && vel.x < 0.1) vel.x = 0;
+       if(vel.y > -0.1 && vel.y < 0.1) vel.y = 0;
+       if(vel.z > -0.1 && vel.z < 0.1) vel.z = 0;
+
+       return vel;
+}
+
+void _Movetype_PushEntityTrace(vector push)
+{
+       vector end = self.move_origin + push;
+       int type;
+       if(self.move_nomonsters)
+               type = max(0, self.move_nomonsters);
+       else if(self.move_movetype == MOVETYPE_FLYMISSILE)
+               type = MOVE_MISSILE;
+       else if(self.solid == SOLID_TRIGGER || self.solid == SOLID_NOT)
+               type = MOVE_NOMONSTERS;
+       else
+               type = MOVE_NORMAL;
+
+       tracebox(self.move_origin, self.mins, self.maxs, end, type, self);
+}
+
+float _Movetype_PushEntity(vector push, bool failonstartsolid)  // SV_PushEntity
+{
+       _Movetype_PushEntityTrace(push);
+
+       if(trace_startsolid && failonstartsolid)
+               return trace_fraction;
+
+       self.move_origin = trace_endpos;
+
+       if(trace_fraction < 1)
+               if(self.solid >= SOLID_TRIGGER && (!(self.move_flags & FL_ONGROUND) || (self.move_groundentity != trace_ent)))
+                       _Movetype_Impact(trace_ent);
+
+       return trace_fraction;
+}
+
+
+.float ltime;
+.void() blocked;
+// matrix version of makevectors, sets v_forward, v_right and v_up
+void makevectors_matrix(vector myangles)  // AngleVectorsFLU
+{
+       v_forward = v_right = v_up = '0 0 0';
+
+       float y = myangles.y * (M_PI * 2 / 360);
+       float sy = sin(y);
+       float cy = cos(y);
+       float p = myangles.x * (M_PI * 2 / 360);
+       float sp = sin(p);
+       float cp = cos(p);
+       if(v_forward)
+       {
+               v_forward.x = cp * cy;
+               v_forward.y = cp * sy;
+               v_forward.z = -sp;
+       }
+       if(v_right || v_up)
+       {
+               if(myangles.z)
+               {
+                       float r = myangles.z * (M_PI * 2 / 360);
+                       float sr = sin(r);
+                       float cr = cos(r);
+                       if(v_right)
+                       {
+                               v_right.x = sr * sp * cy + cr * -sy;
+                               v_right.y = sr * sp * sy + cr * cy;
+                               v_right.z = sr * cp;
+                       }
+                       if(v_up)
+                       {
+                               v_up.x = cr * sp * cy + -sr * -sy;
+                               v_up.y = cr * sp * sy + -sr * cy;
+                               v_up.z = cr * cp;
+                       }
+               }
+               else
+               {
+                       if(v_right)
+                       {
+                               v_right.x = -sy;
+                               v_right.y = cy;
+                               v_right.z = 0;
+                       }
+                       if(v_up)
+                       {
+                               v_up.x = sp * cy;
+                               v_up.y = sp * sy;
+                               v_up.z = cp;
+                       }
+               }
+       }
+}
+
+void _Movetype_Physics_Frame(float movedt)
+{
+       self.move_didgravity = -1;
+       switch (self.move_movetype)
+       {
+               case MOVETYPE_PUSH:
+               case MOVETYPE_FAKEPUSH:
+                       _Movetype_Physics_Pusher(movedt);
+                       break;
+               case MOVETYPE_NONE:
+                       break;
+               case MOVETYPE_FOLLOW:
+                       _Movetype_Physics_Follow();
+                       break;
+               case MOVETYPE_NOCLIP:
+                       _Movetype_CheckWater(self);
+                       self.move_origin = self.move_origin + TICRATE * self.move_velocity;
+                       self.move_angles = self.move_angles + TICRATE * self.move_avelocity;
+                       _Movetype_LinkEdict(false);
+                       break;
+               case MOVETYPE_STEP:
+                       _Movetype_Physics_Step(movedt);
+                       break;
+               case MOVETYPE_WALK:
+                       _Movetype_Physics_Walk(movedt);
+                       break;
+               case MOVETYPE_TOSS:
+               case MOVETYPE_BOUNCE:
+               case MOVETYPE_BOUNCEMISSILE:
+               case MOVETYPE_FLYMISSILE:
+               case MOVETYPE_FLY:
+                       _Movetype_Physics_Toss(movedt);
+                       break;
+       }
+}
+
+void Movetype_Physics_NoMatchServer()  // optimized
+{
+       float movedt = time - self.move_time;
+       self.move_time = time;
+
+       _Movetype_Physics_Frame(movedt);
+       if(wasfreed(self))
+               return;
+
+       self.avelocity = self.move_avelocity;
+       self.velocity = self.move_velocity;
+       self.angles = self.move_angles;
+       setorigin(self, self.move_origin);
+}
+
+void Movetype_Physics_MatchServer(bool sloppy)
+{
+       Movetype_Physics_MatchTicrate(TICRATE, sloppy);
+}
+
+void Movetype_Physics_MatchTicrate(float tr, bool sloppy)  // SV_Physics_Entity
+{
+       if(tr <= 0)
+       {
+               Movetype_Physics_NoMatchServer();
+               return;
+       }
+
+       float dt = time - self.move_time;
+
+       int n = max(0, floor(dt / tr));
+       dt -= n * tr;
+       self.move_time += n * tr;
+
+       if(!self.move_didgravity)
+               self.move_didgravity = ((self.move_movetype == MOVETYPE_BOUNCE || self.move_movetype == MOVETYPE_TOSS) && !(self.move_flags & FL_ONGROUND));
+
+       for (int i = 0; i < n; ++i)
+       {
+               _Movetype_Physics_Frame(tr);
+               if(wasfreed(self))
+                       return;
+       }
+
+       self.avelocity = self.move_avelocity;
+
+       if(dt > 0 && self.move_movetype != MOVETYPE_NONE && !(self.move_flags & FL_ONGROUND))
+       {
+               // now continue the move from move_time to time
+               self.velocity = self.move_velocity;
+
+               if(self.move_didgravity > 0)
+               {
+                       self.velocity_z -= (GRAVITY_UNAFFECTED_BY_TICRATE ? 0.5 : 1)
+                           * dt
+                           * (self.gravity ? self.gravity : 1)
+                           * PHYS_GRAVITY;
+               }
+
+               self.angles = self.move_angles + dt * self.avelocity;
+
+               if(sloppy || self.move_movetype == MOVETYPE_NOCLIP)
+               {
+                       setorigin(self, self.move_origin + dt * self.velocity);
+               }
+               else
+               {
+                       _Movetype_PushEntityTrace(dt * self.velocity);
+                       if(!trace_startsolid)
+                               setorigin(self, trace_endpos);
+               }
+
+               if(self.move_didgravity > 0 && GRAVITY_UNAFFECTED_BY_TICRATE)
+                       self.velocity_z -= 0.5 * dt * (self.gravity ? self.gravity : 1) * PHYS_GRAVITY;
+       }
+       else
+       {
+               self.velocity = self.move_velocity;
+               self.angles = self.move_angles;
+               setorigin(self, self.move_origin);
+       }
+}
diff --git a/qcsrc/common/movetypes/movetypes.qh b/qcsrc/common/movetypes/movetypes.qh
new file mode 100644 (file)
index 0000000..67cd51e
--- /dev/null
@@ -0,0 +1,103 @@
+#ifndef MOVETYPES_H
+#define MOVETYPES_H
+
+.float move_ltime;
+.void(void)move_think;
+.float move_nextthink;
+.void(void)move_blocked;
+
+.float move_movetype;
+.float move_time;
+.vector move_origin;
+.vector move_angles;
+.vector move_velocity;
+.vector move_avelocity;
+.int move_flags;
+.int move_watertype;
+.int move_waterlevel;
+.void(void)move_touch;
+.void(float, float)contentstransition;
+.float move_bounce_factor;
+.float move_bounce_stopspeed;
+.float move_nomonsters;  // -1 for MOVE_NORMAL, otherwise a MOVE_ constant
+
+.entity move_aiment;
+.vector move_punchangle;
+
+// should match sv_gameplayfix_fixedcheckwatertransition
+float autocvar_cl_gameplayfix_fixedcheckwatertransition = 1;
+
+#ifdef SVQC
+.int stat_gameplayfix_upvelocityclearsonground;
+
+#define GRAVITY_UNAFFECTED_BY_TICRATE autocvar_sv_gameplayfix_gravityunaffectedbyticrate
+#define UPWARD_VELOCITY_CLEARS_ONGROUND autocvar_sv_gameplayfix_upwardvelocityclearsongroundflag
+
+#define TICRATE sys_frametime
+#elif defined(CSQC)
+#define GRAVITY_UNAFFECTED_BY_TICRATE (getstati(STAT_MOVEFLAGS) & MOVEFLAG_GRAVITYUNAFFECTEDBYTICRATE)
+#define UPWARD_VELOCITY_CLEARS_ONGROUND getstati(STAT_GAMEPLAYFIX_UPVELOCITYCLEARSONGROUND)
+
+#define TICRATE ticrate
+#endif
+
+.entity move_groundentity;  // FIXME add move_groundnetworkentity?
+.float move_suspendedinair;
+.float move_didgravity;
+
+void _Movetype_WallFriction(vector stepnormal);
+int _Movetype_FlyMove(float dt, bool applygravity, vector stepnormal, float stepheight);
+void _Movetype_CheckVelocity();
+void _Movetype_CheckWaterTransition(entity ent);
+float _Movetype_CheckWater(entity ent);
+void _Movetype_LinkEdict_TouchAreaGrid();
+void _Movetype_LinkEdict(float touch_triggers);
+float _Movetype_TestEntityPosition(vector ofs);
+float _Movetype_UnstickEntity();
+vector _Movetype_ClipVelocity(vector vel, vector norm, float f);
+void _Movetype_PushEntityTrace(vector push);
+float _Movetype_PushEntity(vector push, float failonstartsolid);
+void makevectors_matrix(vector myangles);
+
+void Movetype_Physics_MatchTicrate(float tr, bool sloppy);
+void Movetype_Physics_MatchServer(bool sloppy);
+void Movetype_Physics_NoMatchServer();
+void _Movetype_LinkEdict(float touch_triggers);
+void _Movetype_LinkEdict_TouchAreaGrid();
+
+float _Movetype_UnstickEntity();
+
+const int MAX_CLIP_PLANES = 5;
+
+#ifdef CSQC
+const int MOVETYPE_NONE             = 0;
+const int MOVETYPE_ANGLENOCLIP      = 1;
+const int MOVETYPE_ANGLECLIP        = 2;
+const int MOVETYPE_WALK             = 3;
+const int MOVETYPE_STEP             = 4;
+const int MOVETYPE_FLY              = 5;
+const int MOVETYPE_TOSS             = 6;
+const int MOVETYPE_PUSH             = 7;
+const int MOVETYPE_NOCLIP           = 8;
+const int MOVETYPE_FLYMISSILE       = 9;
+const int MOVETYPE_BOUNCE           = 10;
+const int MOVETYPE_BOUNCEMISSILE    = 11;  // Like bounce but doesn't lose speed on bouncing
+const int MOVETYPE_FOLLOW           = 12;
+const int MOVETYPE_FLY_WORLDONLY    = 33;
+
+const int FL_ITEM                   = 256;
+const int FL_ONGROUND                          = 512;
+#endif
+
+const int MOVETYPE_FAKEPUSH         = 13;
+
+const float MOVEFLAG_Q2AIRACCELERATE            = 1;
+const float MOVEFLAG_NOGRAVITYONGROUND          = 2;
+const float MOVEFLAG_GRAVITYUNAFFECTEDBYTICRATE = 4;
+
+#ifdef CSQC
+// TODO: figure out server's version of this
+#define moveflags (getstati(STAT_MOVEFLAGS))
+#endif
+
+#endif
diff --git a/qcsrc/common/movetypes/push.qc b/qcsrc/common/movetypes/push.qc
new file mode 100644 (file)
index 0000000..1f563f5
--- /dev/null
@@ -0,0 +1,161 @@
+void _Movetype_PushMove(float dt)  // SV_PushMove
+{
+       if (self.move_velocity == '0 0 0' && self.move_avelocity == '0 0 0')
+       {
+               self.move_ltime += dt;
+               return;
+       }
+
+       switch (self.solid)
+       {
+               // LordHavoc: valid pusher types
+               case SOLID_BSP:
+               case SOLID_BBOX:
+               case SOLID_SLIDEBOX:
+               case SOLID_CORPSE:  // LordHavoc: this would be weird...
+                       break;
+               // LordHavoc: no collisions
+               case SOLID_NOT:
+               case SOLID_TRIGGER:
+                       self.move_origin = self.move_origin + dt * self.move_velocity;
+                       self.move_angles = self.move_angles + dt * self.move_avelocity;
+                       self.move_angles_x -= 360.0 * floor(self.move_angles.x * (1.0 / 360.0));
+                       self.move_angles_y -= 360.0 * floor(self.move_angles.y * (1.0 / 360.0));
+                       self.move_angles_z -= 360.0 * floor(self.move_angles.z * (1.0 / 360.0));
+                       self.move_ltime += dt;
+                       _Movetype_LinkEdict(true);
+                       return;
+               default:
+                       dprintf("_Movetype_PushMove: entity %e, unrecognized solid type %d\n", self, self.solid);
+                       return;
+       }
+
+       bool rotated = (self.move_angles * self.move_angles) + (self.move_avelocity * self.move_avelocity) > 0;
+
+       vector move1 = self.move_velocity * dt;
+       vector moveangle = self.move_avelocity * dt;
+
+       makevectors_matrix(-moveangle);
+
+//     vector pushorig = self.move_origin;
+//     vector pushang = self.move_angles;
+//     float pushltime = self.move_ltime;
+
+// move the pusher to its final position
+
+       self.move_origin = self.move_origin + dt * self.move_velocity;
+       self.move_angles = self.move_angles + dt * self.move_avelocity;
+
+       self.move_ltime += dt;
+       _Movetype_LinkEdict(true);
+
+       int savesolid = self.solid;
+
+       if (self.move_movetype != MOVETYPE_FAKEPUSH)
+       {
+               for (entity check = findradius(0.5 * (self.absmin + self.absmax), 0.5 * vlen(self.absmax - self.absmin)); check; check = check.chain)
+               {
+                       switch (check.move_movetype)
+                       {
+                               case MOVETYPE_NONE:
+                               case MOVETYPE_PUSH:
+                               case MOVETYPE_FOLLOW:
+                               case MOVETYPE_NOCLIP:
+                               case MOVETYPE_FLY_WORLDONLY:
+                                       continue;
+                               default:
+                                       break;
+                       }
+
+                       if (check.owner == self)
+                               continue;
+
+                       if (self.owner == check)
+                               continue;
+
+                       vector pivot = check.mins + 0.5 * (check.maxs - check.mins);
+                       vector move;
+                       if (rotated)
+                       {
+                               vector org = (check.move_origin - self.move_origin) + pivot;
+                               vector org2;
+                               org2.x = org * v_forward;
+                               org2.y = org * v_right;
+                               org2.z = org * v_up;
+                               move = (org2 - org) + move1;
+                       }
+                       else
+                       {
+                               move = move1;
+                       }
+
+                       // physics objects need better collisions than this code can do
+                       if (check.move_movetype == 32)  // MOVETYPE_PHYSICS
+                       {
+                               check.move_origin = check.move_origin + move;
+                               entity oldself = self;
+                               self = check;
+                               _Movetype_LinkEdict(true);
+                               self = oldself;
+                               continue;
+                       }
+
+                       // try moving the contacted entity
+                       self.solid = SOLID_NOT;
+                       entity oldself = self;
+                       self = check;
+                       if (!_Movetype_PushEntity(move, true))
+                       {
+                               self = oldself;
+                               // entity "check" got teleported
+                               check.move_angles_y += trace_fraction * moveangle.y;
+                               self.solid = savesolid;
+                               continue;  // pushed enough
+                       }
+                       self = oldself;
+                       // FIXME: turn players specially
+                       check.move_angles_y += trace_fraction * moveangle.y;
+                       self.solid = savesolid;
+
+                       // this trace.fraction < 1 check causes items to fall off of pushers
+                       // if they pass under or through a wall
+                       // the groundentity check causes items to fall off of ledges
+                       if (check.move_movetype != MOVETYPE_WALK && (trace_fraction < 1 || check.move_groundentity != self))
+                               check.move_flags &= ~FL_ONGROUND;
+               }
+       }
+
+       self.move_angles_x -= 360.0 * floor(self.move_angles.x * (1.0 / 360.0));
+       self.move_angles_y -= 360.0 * floor(self.move_angles.y * (1.0 / 360.0));
+       self.move_angles_z -= 360.0 * floor(self.move_angles.z * (1.0 / 360.0));
+}
+
+void _Movetype_Physics_Pusher(float dt)  // SV_Physics_Pusher
+{
+       float oldltime = self.move_ltime;
+       float thinktime = self.move_nextthink;
+       float movetime;
+       if (thinktime < self.move_ltime + dt)
+       {
+               movetime = thinktime - self.move_ltime;
+               if (movetime < 0)
+                       movetime = 0;
+       }
+       else
+       {
+               movetime = dt;
+       }
+
+       if (movetime)
+               // advances self.move_ltime if not blocked
+               _Movetype_PushMove(movetime);
+
+       if (thinktime > oldltime && thinktime <= self.move_ltime)
+       {
+               self.move_nextthink = 0;
+               self.move_time = time;
+               other = world;
+               if (self.move_think)
+                       self.move_think();
+       }
+}
diff --git a/qcsrc/common/movetypes/push.qh b/qcsrc/common/movetypes/push.qh
new file mode 100644 (file)
index 0000000..44d5442
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef MOVETYPE_PUSH_H
+#define MOVETYPE_PUSH_H
+
+void _Movetype_Physics_Pusher(float dt);
+
+#endif
\ No newline at end of file
diff --git a/qcsrc/common/movetypes/step.qc b/qcsrc/common/movetypes/step.qc
new file mode 100644 (file)
index 0000000..822bf09
--- /dev/null
@@ -0,0 +1,23 @@
+void _Movetype_Physics_Step(float dt) // SV_Physics_Step
+{
+       if(self.move_flags & FL_ONGROUND)
+       {
+               if(self.velocity_z >= (1.0 / 32.0) && UPWARD_VELOCITY_CLEARS_ONGROUND)
+               {
+                       self.move_flags &= ~FL_ONGROUND;
+                       _Movetype_CheckVelocity();
+                       _Movetype_FlyMove(dt, true, '0 0 0', 0);
+                       _Movetype_LinkEdict(true);
+               }
+       }
+       else
+       {
+               _Movetype_CheckVelocity();
+               _Movetype_FlyMove(dt, true, '0 0 0', 0);
+               _Movetype_LinkEdict(true);
+
+               // TODO? movetypesteplandevent
+       }
+
+       _Movetype_CheckWaterTransition(self);
+}
diff --git a/qcsrc/common/movetypes/toss.qc b/qcsrc/common/movetypes/toss.qc
new file mode 100644 (file)
index 0000000..6ed0407
--- /dev/null
@@ -0,0 +1,115 @@
+#include "../physics.qh"
+
+void _Movetype_Physics_Toss(float dt)  // SV_Physics_Toss
+{
+       if (self.move_flags & FL_ONGROUND)
+       {
+               if (self.move_velocity.z >= 1 / 32)
+               {
+                       self.move_flags &= ~FL_ONGROUND;
+               }
+               else if (!self.move_groundentity)
+               {
+                       return;
+               }
+               else if (self.move_suspendedinair && wasfreed(self.move_groundentity))
+               {
+                       self.move_groundentity = world;
+                       return;
+               }
+       }
+
+       self.move_suspendedinair = false;
+
+       _Movetype_CheckVelocity();
+
+       if (self.move_movetype == MOVETYPE_BOUNCE || self.move_movetype == MOVETYPE_TOSS)
+       {
+               self.move_didgravity = 1;
+               self.move_velocity_z -= (GRAVITY_UNAFFECTED_BY_TICRATE ? 0.5 : 1)
+                   * dt
+                   * (self.gravity ? self.gravity : 1)
+                   * PHYS_GRAVITY;
+       }
+
+       self.move_angles = self.move_angles + self.move_avelocity * dt;
+
+       float movetime = dt;
+       for (int bump = 0; bump < MAX_CLIP_PLANES && movetime > 0; ++bump)
+       {
+               vector move = self.move_velocity * movetime;
+               _Movetype_PushEntity(move, true);
+               if (wasfreed(self))
+                       return;
+
+               if (trace_startsolid)
+               {
+                       _Movetype_UnstickEntity();
+                       _Movetype_PushEntity(move, false);
+                       if (wasfreed(self))
+                               return;
+               }
+
+               if (trace_fraction == 1)
+                       break;
+
+               movetime *= 1 - min(1, trace_fraction);
+
+               if (self.move_movetype == MOVETYPE_BOUNCEMISSILE)
+               {
+                       self.move_velocity = _Movetype_ClipVelocity(self.move_velocity, trace_plane_normal, 2.0);
+                       self.move_flags &= ~FL_ONGROUND;
+               }
+               else if (self.move_movetype == MOVETYPE_BOUNCE)
+               {
+                       float bouncefac = self.move_bounce_factor;     if (!bouncefac)  bouncefac = 0.5;
+                       float bouncestop = self.move_bounce_stopspeed; if (!bouncestop) bouncestop = 60 / 800;
+                       bouncestop *= (self.gravity ? self.gravity : 1) * PHYS_GRAVITY;
+
+                       self.move_velocity = _Movetype_ClipVelocity(self.move_velocity, trace_plane_normal, 1 + bouncefac);
+
+                       float d = trace_plane_normal * self.move_velocity;
+                       if (trace_plane_normal.z > 0.7 && d < bouncestop && d > -bouncestop)
+                       {
+                               self.move_flags |= FL_ONGROUND;
+                               self.move_groundentity = trace_ent;
+                               self.move_velocity = '0 0 0';
+                               self.move_avelocity = '0 0 0';
+                       }
+                       else
+                       {
+                               self.move_flags &= ~FL_ONGROUND;
+                       }
+               }
+               else
+               {
+                       self.move_velocity = _Movetype_ClipVelocity(self.move_velocity, trace_plane_normal, 1.0);
+                       if (trace_plane_normal.z > 0.7)
+                       {
+                               self.move_flags |= FL_ONGROUND;
+                               self.move_groundentity = trace_ent;
+                               if (trace_ent.solid == SOLID_BSP)
+                                       self.move_suspendedinair = true;
+                               self.move_velocity = '0 0 0';
+                               self.move_avelocity = '0 0 0';
+                       }
+                       else
+                       {
+                               self.move_flags &= ~FL_ONGROUND;
+                       }
+               }
+
+               // DP revision 8905 (just, WHY...)
+               if (self.move_movetype == MOVETYPE_BOUNCEMISSILE)
+                       break;
+
+               // DP revision 8918 (WHY...)
+               if (self.move_flags & FL_ONGROUND)
+                       break;
+       }
+
+       if (GRAVITY_UNAFFECTED_BY_TICRATE && self.move_didgravity > 0 && !(self.move_flags & FL_ONGROUND))
+               self.move_velocity_z -= 0.5 * dt * (self.gravity ? self.gravity : 1) * PHYS_GRAVITY;
+
+       _Movetype_CheckWaterTransition(self);
+}
diff --git a/qcsrc/common/movetypes/toss.qh b/qcsrc/common/movetypes/toss.qh
new file mode 100644 (file)
index 0000000..9e11595
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef MOVETYPE_TOSS_H
+#define MOVETYPE_TOSS_H
+
+void _Movetype_Physics_Toss(float dt);
+
+#endif
\ No newline at end of file
diff --git a/qcsrc/common/movetypes/walk.qc b/qcsrc/common/movetypes/walk.qc
new file mode 100644 (file)
index 0000000..180dfcc
--- /dev/null
@@ -0,0 +1,169 @@
+void _Movetype_Physics_Walk(float dt)  // SV_WalkMove
+{
+       vector stepnormal = '0 0 0';
+
+       // if frametime is 0 (due to client sending the same timestamp twice), don't move
+       if (dt <= 0)
+               return;
+
+       if (GAMEPLAYFIX_UNSTICKPLAYERS)
+               _Movetype_UnstickEntity();
+
+       bool applygravity = (!_Movetype_CheckWater(self) && self.move_movetype == MOVETYPE_WALK && !(self.move_flags & FL_WATERJUMP));
+
+       _Movetype_CheckVelocity();
+
+       // do a regular slide move unless it looks like you ran into a step
+       bool oldonground = (self.move_flags & FL_ONGROUND);
+
+       vector start_origin = self.move_origin;
+       vector start_velocity = self.move_velocity;
+
+       int clip = _Movetype_FlyMove(dt, applygravity, stepnormal, GAMEPLAYFIX_STEPMULTIPLETIMES ? PHYS_STEPHEIGHT : 0);
+
+       if (GAMEPLAYFIX_DOWNTRACEONGROUND && !(clip & 1))
+       {
+               // only try this if there was no floor in the way in the trace (no,
+               // this check seems to be not REALLY necessary, because if clip & 1,
+               // our trace will hit that thing too)
+               vector upmove = self.move_origin + '0 0 1';
+               vector downmove = self.move_origin - '0 0 1';
+               int type;
+               if (self.move_movetype == MOVETYPE_FLYMISSILE)
+                       type = MOVE_MISSILE;
+               else if (self.move_movetype == MOVETYPE_FLY_WORLDONLY)
+                       type = MOVE_WORLDONLY;
+               else if (self.solid == SOLID_TRIGGER || self.solid == SOLID_NOT)
+                       type = MOVE_NOMONSTERS;
+               else type = MOVE_NORMAL;
+               tracebox(upmove, self.mins, self.maxs, downmove, type, self);
+               if (trace_fraction < 1 && trace_plane_normal.z > 0.7)
+                       clip |= 1;  // but we HAVE found a floor
+       }
+
+       // if the move did not hit the ground at any point, we're not on ground
+       if (!(clip & 1))
+               self.move_flags &= ~FL_ONGROUND;
+
+       _Movetype_CheckVelocity();
+       _Movetype_LinkEdict(true);
+
+       if (clip & 8)  // teleport
+               return;
+
+       if (self.move_flags & FL_WATERJUMP)
+               return;
+
+       if (PHYS_NOSTEP)
+               return;
+
+       vector originalmove_origin = self.move_origin;
+       vector originalmove_velocity = self.move_velocity;
+       // originalmove_clip = clip;
+       int originalmove_flags = self.move_flags;
+       entity originalmove_groundentity = self.move_groundentity;
+
+       // if move didn't block on a step, return
+       if (clip & 2)
+       {
+               // if move was not trying to move into the step, return
+               if (fabs(start_velocity.x) < 0.03125 && fabs(start_velocity.y) < 0.03125)
+                       return;
+
+               if (self.move_movetype != MOVETYPE_FLY)
+               {
+                       // return if gibbed by a trigger
+                       if (self.move_movetype != MOVETYPE_WALK)
+                               return;
+
+                       // return if attempting to jump while airborn (unless sv_jumpstep)
+                       if (!PHYS_JUMPSTEP)
+                               if (!oldonground && self.move_waterlevel == 0)
+                                       return;
+               }
+
+               // try moving up and forward to go up a step
+               // back to start pos
+               self.move_origin = start_origin;
+               self.move_velocity = start_velocity;
+
+               // move up
+               vector upmove = '0 0 1' * PHYS_STEPHEIGHT;
+               if (!_Movetype_PushEntity(upmove, true))
+               {
+                       // we got teleported when upstepping... must abort the move
+                       return;
+               }
+
+               // move forward
+               self.move_velocity_z = 0;
+               clip = _Movetype_FlyMove(dt, applygravity, stepnormal, 0);
+               self.move_velocity_z += start_velocity.z;
+               if (clip & 8)
+               {
+                       // we got teleported when upstepping... must abort the move
+                       // note that z velocity handling may not be what QC expects here, but we cannot help it
+                       return;
+               }
+
+               _Movetype_CheckVelocity();
+               _Movetype_LinkEdict(true);
+
+               // check for stuckness, possibly due to the limited precision of floats
+               // in the clipping hulls
+               if (clip
+                   && fabs(originalmove_origin.y - self.move_origin.y) < 0.03125
+                   && fabs(originalmove_origin.x - self.move_origin.x) < 0.03125)
+               {
+                       // Con_Printf("wall\n");
+                       // stepping up didn't make any progress, revert to original move
+                       self.move_origin = originalmove_origin;
+                       self.move_velocity = originalmove_velocity;
+                       // clip = originalmove_clip;
+                       self.move_flags = originalmove_flags;
+                       self.move_groundentity = originalmove_groundentity;
+                       // now try to unstick if needed
+                       // clip = SV_TryUnstick (ent, oldvel);
+                       return;
+               }
+
+               // Con_Printf("step - ");
+
+               // extra friction based on view angle
+               if (clip & 2 && PHYS_WALLFRICTION)
+                       _Movetype_WallFriction(stepnormal);
+       }
+       // don't do the down move if stepdown is disabled, moving upward, not in water, or the move started offground or ended onground
+       else if (!GAMEPLAYFIX_STEPDOWN || self.move_waterlevel >= 3 || start_velocity.z >= (1.0 / 32.0) || !oldonground || (self.move_flags & FL_ONGROUND))
+       {
+               return;
+       }
+
+       // move down
+       vector downmove = '0 0 1' * (-PHYS_STEPHEIGHT + start_velocity.z * dt);
+       if (!_Movetype_PushEntity(downmove, true))
+       {
+               // we got teleported when downstepping... must abort the move
+               return;
+       }
+
+       if (trace_fraction < 1 && trace_plane_normal.z > 0.7)
+       {
+               // this has been disabled so that you can't jump when you are stepping
+               // up while already jumping (also known as the Quake2 double jump bug)
+       }
+       else
+       {
+               // Con_Printf("slope\n");
+               // if the push down didn't end up on good ground, use the move without
+               // the step up.  This happens near wall / slope combinations, and can
+               // cause the player to hop up higher on a slope too steep to climb
+               self.move_origin = originalmove_origin;
+               self.move_velocity = originalmove_velocity;
+               self.move_flags = originalmove_flags;
+               self.move_groundentity = originalmove_groundentity;
+       }
+
+       _Movetype_CheckVelocity();
+       _Movetype_LinkEdict(true);
+}
diff --git a/qcsrc/common/movetypes/walk.qh b/qcsrc/common/movetypes/walk.qh
new file mode 100644 (file)
index 0000000..10493c9
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef MOVETYPE_WALK_H
+#define MOVETYPE_WALK_H
+
+void _Movetype_Physics_Walk(float dt);
+
+#endif
index 4225a19f03cb76e98b5afa198312d94f2c575cfc..fcdc5533e4c1be7b9f94902074c62761b119c4d1 100644 (file)
@@ -3,7 +3,7 @@
        #include "../client/defs.qh"
        #include "nades.qh"
        #include "buffs.qh"
-       #include "../client/movetypes.qh"
+       #include "../common/movetypes/movetypes.qh"
        #include "../server/tturrets/include/turrets_early.qh"
        #include "../client/main.qh"
        #include "../csqcmodellib/cl_model.qh"
index d11e4eabfb83d75157210ac8c3e3f145b4d6304f..2b2aa857b806e9b7cd9efecb8da9b7017dcfb61e 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef NADES_H
 #define NADES_H
 
+#include "teams.qh"
+
 .float healer_lifetime;
 .float healer_radius;
 
@@ -104,7 +106,7 @@ string Nade_TrailEffect(float proj, float nade_team)
 }
 
 #ifdef SVQC
-float healer_send(entity to, float sf);
+float healer_send(entity to, int sf);
 #endif
 
 #ifdef CSQC
index bc520e59d57005b7547d8ddbeba0a3cd6a5b9584..fb9958b08fcbd186fd151b65afb89462d442a357 100644 (file)
@@ -47,9 +47,6 @@ void sv_notice_toall(string _notice, float _howlong, float _modal)
 #endif // SVQC
 
 #ifdef CSQC
-void SUB_Remove()
-{ remove(self); }
-
 void cl_notice_read()
 {
     entity _notice;
index b48daec7bcec244b831d8a74129eee9bfae826a8..a406df52419dc71d1bdf985e7aa963e83b988fa1 100644 (file)
@@ -946,8 +946,7 @@ void Create_Notification_Entity(
 #ifdef SVQC
 void Notification_GetCvars(void)
 {
-       float i;
-       for(i = 0; i <= NOTIF_CHOICE_COUNT; ++i)
+       for(int i = 0; i <= NOTIF_CHOICE_COUNT; ++i)
        {
                GetCvars_handleFloat(
                        get_cvars_s,
@@ -1633,7 +1632,7 @@ void Local_Notification(int net_type, int net_name, ...count)
 
                        if(notif.nent_challow_var && (warmup_stage || (notif.nent_challow_var == 2)))
                        {
-                               switch(cvar_string(sprintf("notification_%s", notif.nent_name)))
+                               switch(cvar(sprintf("notification_%s", notif.nent_name)))
                                {
                                        case 1: found_choice = notif.nent_optiona; break;
                                        case 2: found_choice = notif.nent_optionb; break;
@@ -1763,21 +1762,19 @@ void Net_Notification_Remove()
        ));
        #endif
 
-       float i;
-       for(i = 0; i < 4; ++i) { if(self.nent_strings[i]) { strunzone(self.nent_strings[i]); } }
+       for(int i = 0; i < 4; ++i) { if(self.nent_strings[i]) { strunzone(self.nent_strings[i]); } }
        remove(self);
 }
 
-float Net_Write_Notification(entity client, float sf)
+float Net_Write_Notification(entity client, int sf)
 {
        if(Notification_ShouldSend(self.nent_broadcast, client, self.nent_client))
        {
-               float i;
                WriteByte(MSG_ENTITY, ENT_CLIENT_NOTIFICATION);
                WriteByte(MSG_ENTITY, self.nent_net_type);
                WriteShort(MSG_ENTITY, self.nent_net_name);
-               for(i = 0; i < self.nent_stringcount; ++i) { WriteString(MSG_ENTITY, self.nent_strings[i]); }
-               for(i = 0; i < self.nent_floatcount; ++i) { WriteLong(MSG_ENTITY, self.nent_floats[i]); }
+               for(int i = 0; i < self.nent_stringcount; ++i) { WriteString(MSG_ENTITY, self.nent_strings[i]); }
+               for(int i = 0; i < self.nent_floatcount; ++i) { WriteLong(MSG_ENTITY, self.nent_floats[i]); }
                return true;
        }
        else { return false; }
@@ -2098,10 +2095,9 @@ void Send_Notification(
                net_notif.nent_stringcount = notif.nent_stringcount;
                net_notif.nent_floatcount = notif.nent_floatcount;
 
-               float i;
-               for(i = 0; i < net_notif.nent_stringcount; ++i)
+               for(int i = 0; i < net_notif.nent_stringcount; ++i)
                        { net_notif.nent_strings[i] = strzone(...(i, string)); }
-               for(i = 0; i < net_notif.nent_floatcount; ++i)
+               for(int i = 0; i < net_notif.nent_floatcount; ++i)
                        { net_notif.nent_floats[i] = ...((net_notif.nent_stringcount + i), float); }
 
                net_notif.think = Net_Notification_Remove;
index 97a1099a9923d47a955520d9707a23c62f9070a7..13487ad830001d6a4ca1e09c574a612c67f0e06a 100644 (file)
@@ -3,6 +3,7 @@
 
 #include "constants.qh"
 #include "teams.qh"
+#include "util.qh"
 
 // ================================================
 //  Unified notification system, written by Samual
diff --git a/qcsrc/common/oo.qh b/qcsrc/common/oo.qh
new file mode 100644 (file)
index 0000000..63b1708
--- /dev/null
@@ -0,0 +1,71 @@
+#ifndef OO_H
+#define OO_H
+
+#ifdef MENUQC
+       #define NULL (null_entity)
+#else
+       #define NULL (world)
+#endif
+
+.string classname;
+.string vtblname;
+.entity vtblbase;
+entity spawnVtbl(entity this, entity base)
+{
+       entity vtbl = spawn();
+       copyentity(this, vtbl);
+       vtbl.vtblname = vtbl.classname;
+       vtbl.classname = "vtbl";
+       vtbl.vtblbase = base ? base : vtbl; // Top level objects use vtbl as base
+       return vtbl;
+}
+
+entity Object_vtbl;
+entity spawnObject(entity this, entity)
+{
+       this = spawn();
+       this.classname = "Object";
+       if (!Object_vtbl) Object_vtbl = spawnVtbl(this, NULL);
+       return this;
+}
+
+// Classes have a `spawn##cname(entity, entity)` constructor
+// The parameters are used as locals for [[accumulate]]
+
+// Macro to hide this implementation detail
+#define NEW(cname) (spawn##cname(NULL, NULL))
+
+#define CLASS(cname, base)                                                     \
+entity spawn##cname(entity this, entity basevtbl) {                            \
+    this = NEW(base); basevtbl = base##_vtbl;                                  \
+}
+
+#define METHOD(cname, name, prototype)                                         \
+prototype cname##_##name;                                                      \
+.prototype name;                                                               \
+[[accumulate]] entity spawn##cname(entity this, entity basevtbl) {             \
+    this.name = cname##_##name;                                                \
+}
+
+#define ATTRIB(cname, name, type, val)                                         \
+.type name;                                                                    \
+[[accumulate]] entity spawn##cname(entity this, entity basevtbl) {             \
+    this.name = val;                                                           \
+}
+
+#define ATTRIBARRAY(cname, name, type, cnt)                                    \
+.type name[cnt];
+
+#define ENDCLASS(cname)                                                        \
+.bool instanceOf##cname;                                                       \
+entity cname##_vtbl;                                                           \
+[[accumulate]] [[last]] entity spawn##cname(entity this, entity basevtbl) {    \
+    this.instanceOf##cname = true;                                             \
+    this.classname = #cname;                                                   \
+    if (!cname##_vtbl) cname##_vtbl = spawnVtbl(this, basevtbl);               \
+    return this;                                                               \
+}
+
+#define SUPER(cname) (cname##_vtbl.vtblbase)
+
+#endif
diff --git a/qcsrc/common/physics.qc b/qcsrc/common/physics.qc
new file mode 100644 (file)
index 0000000..60ca3b1
--- /dev/null
@@ -0,0 +1,1933 @@
+#include "physics.qh"
+#include "triggers/trigger/swamp.qh"
+#include "triggers/trigger/jumppads.qh"
+
+#ifdef SVQC
+
+#include "../server/miscfunctions.qh"
+
+// 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;
+}
+
+float Physics_ClientOption(entity pl, string option)
+{
+       if(Physics_Valid(pl.cvar_cl_physics))
+       {
+               string var = sprintf("g_physics_%s_%s", pl.cvar_cl_physics, option);
+               if(cvar_type(var) & CVAR_TYPEFLAG_EXISTS)
+                       return cvar(var);
+       }
+       if(autocvar_g_physics_clientselect && autocvar_g_physics_clientselect_default)
+       {
+               string var = sprintf("g_physics_%s_%s", autocvar_g_physics_clientselect_default, option);
+               if(cvar_type(var) & CVAR_TYPEFLAG_EXISTS)
+                       return cvar(var);
+       }
+       return cvar(strcat("sv_", option));
+}
+
+void Physics_AddStats()
+{
+       // static view offset and hitbox vectors
+       // networked for all you bandwidth pigs out there
+       addstat(STAT_PL_VIEW_OFS1, AS_FLOAT, stat_pl_view_ofs_x);
+       addstat(STAT_PL_VIEW_OFS2, AS_FLOAT, stat_pl_view_ofs_y);
+       addstat(STAT_PL_VIEW_OFS3, AS_FLOAT, stat_pl_view_ofs_z);
+       addstat(STAT_PL_CROUCH_VIEW_OFS1, AS_FLOAT, stat_pl_crouch_view_ofs_x);
+       addstat(STAT_PL_CROUCH_VIEW_OFS2, AS_FLOAT, stat_pl_crouch_view_ofs_y);
+       addstat(STAT_PL_CROUCH_VIEW_OFS3, AS_FLOAT, stat_pl_crouch_view_ofs_z);
+
+       addstat(STAT_PL_MIN1, AS_FLOAT, stat_pl_min_x);
+       addstat(STAT_PL_MIN2, AS_FLOAT, stat_pl_min_y);
+       addstat(STAT_PL_MIN3, AS_FLOAT, stat_pl_min_z);
+       addstat(STAT_PL_MAX1, AS_FLOAT, stat_pl_max_x);
+       addstat(STAT_PL_MAX2, AS_FLOAT, stat_pl_max_y);
+       addstat(STAT_PL_MAX3, AS_FLOAT, stat_pl_max_z);
+       addstat(STAT_PL_CROUCH_MIN1, AS_FLOAT, stat_pl_crouch_min_x);
+       addstat(STAT_PL_CROUCH_MIN2, AS_FLOAT, stat_pl_crouch_min_y);
+       addstat(STAT_PL_CROUCH_MIN3, AS_FLOAT, stat_pl_crouch_min_z);
+       addstat(STAT_PL_CROUCH_MAX1, AS_FLOAT, stat_pl_crouch_max_x);
+       addstat(STAT_PL_CROUCH_MAX2, AS_FLOAT, stat_pl_crouch_max_y);
+       addstat(STAT_PL_CROUCH_MAX3, AS_FLOAT, stat_pl_crouch_max_z);
+
+       // g_movementspeed hack
+       addstat(STAT_MOVEVARS_AIRSPEEDLIMIT_NONQW, AS_FLOAT, stat_sv_airspeedlimit_nonqw);
+       addstat(STAT_MOVEVARS_MAXSPEED, AS_FLOAT, stat_sv_maxspeed);
+       addstat(STAT_MOVEVARS_AIRACCEL_QW, AS_FLOAT, stat_sv_airaccel_qw);
+       addstat(STAT_MOVEVARS_AIRSTRAFEACCEL_QW, AS_FLOAT, stat_sv_airstrafeaccel_qw);
+       addstat(STAT_MOVEVARS_HIGHSPEED, AS_FLOAT, stat_movement_highspeed);
+
+       // jet pack
+       addstat(STAT_JETPACK_ACCEL_SIDE, AS_FLOAT, stat_jetpack_accel_side);
+       addstat(STAT_JETPACK_ACCEL_UP, AS_FLOAT, stat_jetpack_accel_up);
+       addstat(STAT_JETPACK_ANTIGRAVITY, AS_FLOAT, stat_jetpack_antigravity);
+       addstat(STAT_JETPACK_FUEL, AS_FLOAT, stat_jetpack_fuel);
+       addstat(STAT_JETPACK_MAXSPEED_UP, AS_FLOAT, stat_jetpack_maxspeed_up);
+       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);
+
+       // double jump
+       addstat(STAT_DOUBLEJUMP, AS_INT, stat_doublejump);
+
+       // jump speed caps
+       addstat(STAT_MOVEVARS_JUMPSPEEDCAP_MIN, AS_FLOAT, stat_jumpspeedcap_min);
+       addstat(STAT_MOVEVARS_JUMPSPEEDCAP_MIN, AS_FLOAT, stat_jumpspeedcap_min);
+       addstat(STAT_MOVEVARS_JUMPSPEEDCAP_DISABLE_ONRAMPS, AS_INT, stat_jumpspeedcap_disable_onramps);
+
+       // hacks
+       addstat(STAT_MOVEVARS_FRICTION_ONLAND, AS_FLOAT, stat_sv_friction_on_land);
+       addstat(STAT_MOVEVARS_FRICTION_SLICK, AS_FLOAT, stat_sv_friction_slick);
+       addstat(STAT_GAMEPLAYFIX_EASIERWATERJUMP, AS_INT, stat_gameplayfix_easierwaterjump);
+
+       // new properties
+       addstat(STAT_MOVEVARS_JUMPVELOCITY, AS_FLOAT, stat_sv_jumpvelocity);
+       addstat(STAT_MOVEVARS_AIRACCEL_QW_STRETCHFACTOR, AS_FLOAT, stat_sv_airaccel_qw_stretchfactor);
+       addstat(STAT_MOVEVARS_MAXAIRSTRAFESPEED, AS_FLOAT, stat_sv_maxairstrafespeed);
+       addstat(STAT_MOVEVARS_MAXAIRSPEED, AS_FLOAT, stat_sv_maxairspeed);
+       addstat(STAT_MOVEVARS_AIRSTRAFEACCELERATE, AS_FLOAT, stat_sv_airstrafeaccelerate);
+       addstat(STAT_MOVEVARS_WARSOWBUNNY_TURNACCEL, AS_FLOAT, stat_sv_warsowbunny_turnaccel);
+       addstat(STAT_MOVEVARS_AIRACCEL_SIDEWAYS_FRICTION, AS_FLOAT, stat_sv_airaccel_sideways_friction);
+       addstat(STAT_MOVEVARS_AIRCONTROL, AS_FLOAT, stat_sv_aircontrol);
+       addstat(STAT_MOVEVARS_AIRCONTROL_POWER, AS_FLOAT, stat_sv_aircontrol_power);
+       addstat(STAT_MOVEVARS_AIRCONTROL_PENALTY, AS_FLOAT, stat_sv_aircontrol_penalty);
+       addstat(STAT_MOVEVARS_WARSOWBUNNY_AIRFORWARDACCEL, AS_FLOAT, stat_sv_warsowbunny_airforwardaccel);
+       addstat(STAT_MOVEVARS_WARSOWBUNNY_TOPSPEED, AS_FLOAT, stat_sv_warsowbunny_topspeed);
+       addstat(STAT_MOVEVARS_WARSOWBUNNY_ACCEL, AS_FLOAT, stat_sv_warsowbunny_accel);
+       addstat(STAT_MOVEVARS_WARSOWBUNNY_BACKTOSIDERATIO, AS_FLOAT, stat_sv_warsowbunny_backtosideratio);
+       addstat(STAT_MOVEVARS_FRICTION, AS_FLOAT, stat_sv_friction);
+       addstat(STAT_MOVEVARS_ACCELERATE, AS_FLOAT, stat_sv_accelerate);
+       addstat(STAT_MOVEVARS_STOPSPEED, AS_FLOAT, stat_sv_stopspeed);
+       addstat(STAT_MOVEVARS_AIRACCELERATE, AS_FLOAT, stat_sv_airaccelerate);
+       addstat(STAT_MOVEVARS_AIRSTOPACCELERATE, AS_FLOAT, stat_sv_airstopaccelerate);
+
+       addstat(STAT_GAMEPLAYFIX_UPVELOCITYCLEARSONGROUND, AS_INT, stat_gameplayfix_upvelocityclearsonground);
+}
+
+void Physics_UpdateStats(float maxspd_mod)
+{
+       // blah
+       self.stat_pl_view_ofs = PL_VIEW_OFS;
+       self.stat_pl_crouch_view_ofs = PL_CROUCH_VIEW_OFS;
+
+       self.stat_pl_min = PL_MIN;
+       self.stat_pl_max = PL_MAX;
+       self.stat_pl_crouch_min = PL_CROUCH_MIN;
+       self.stat_pl_crouch_max = PL_CROUCH_MAX;
+
+
+       self.stat_sv_airaccel_qw = AdjustAirAccelQW(Physics_ClientOption(self, "airaccel_qw"), maxspd_mod);
+       if(Physics_ClientOption(self, "airstrafeaccel_qw"))
+               self.stat_sv_airstrafeaccel_qw = AdjustAirAccelQW(Physics_ClientOption(self, "airstrafeaccel_qw"), maxspd_mod);
+       else
+               self.stat_sv_airstrafeaccel_qw = 0;
+       self.stat_sv_airspeedlimit_nonqw = Physics_ClientOption(self, "airspeedlimit_nonqw") * maxspd_mod;
+       self.stat_sv_maxspeed = Physics_ClientOption(self, "maxspeed") * maxspd_mod; // also slow walking
+       self.stat_movement_highspeed = PHYS_HIGHSPEED; // TODO: remove this!
+
+       self.stat_doublejump = PHYS_DOUBLEJUMP;
+
+       self.stat_jetpack_antigravity = PHYS_JETPACK_ANTIGRAVITY;
+       self.stat_jetpack_accel_up = PHYS_JETPACK_ACCEL_UP;
+       self.stat_jetpack_accel_side = PHYS_JETPACK_ACCEL_SIDE;
+       self.stat_jetpack_maxspeed_side = PHYS_JETPACK_MAXSPEED_SIDE;
+       self.stat_jetpack_maxspeed_up = PHYS_JETPACK_MAXSPEED_UP;
+       self.stat_jetpack_fuel = PHYS_JETPACK_FUEL;
+
+       self.stat_jumpspeedcap_min = PHYS_JUMPSPEEDCAP_MIN;
+       self.stat_jumpspeedcap_max = PHYS_JUMPSPEEDCAP_MAX;
+       self.stat_jumpspeedcap_disable_onramps = PHYS_JUMPSPEEDCAP_DISABLE_ONRAMPS;
+
+       self.stat_sv_friction_on_land = PHYS_FRICTION_ONLAND;
+       self.stat_sv_friction_slick = PHYS_FRICTION_SLICK;
+
+       self.stat_gameplayfix_easierwaterjump = GAMEPLAYFIX_EASIERWATERJUMP;
+
+
+       // old stats
+       // fix some new settings
+       self.stat_sv_airaccel_qw_stretchfactor = Physics_ClientOption(self, "airaccel_qw_stretchfactor");
+       self.stat_sv_maxairstrafespeed = Physics_ClientOption(self, "maxairstrafespeed");
+       self.stat_sv_maxairspeed = Physics_ClientOption(self, "maxairspeed");
+       self.stat_sv_airstrafeaccelerate = Physics_ClientOption(self, "airstrafeaccelerate");
+       self.stat_sv_warsowbunny_turnaccel = Physics_ClientOption(self, "warsowbunny_turnaccel");
+       self.stat_sv_airaccel_sideways_friction = Physics_ClientOption(self, "airaccel_sideways_friction");
+       self.stat_sv_aircontrol = Physics_ClientOption(self, "aircontrol");
+       self.stat_sv_aircontrol_power = Physics_ClientOption(self, "aircontrol_power");
+       self.stat_sv_aircontrol_penalty = Physics_ClientOption(self, "aircontrol_penalty");
+       self.stat_sv_warsowbunny_airforwardaccel = Physics_ClientOption(self, "warsowbunny_airforwardaccel");
+       self.stat_sv_warsowbunny_topspeed = Physics_ClientOption(self, "warsowbunny_topspeed");
+       self.stat_sv_warsowbunny_accel = Physics_ClientOption(self, "warsowbunny_accel");
+       self.stat_sv_warsowbunny_backtosideratio = Physics_ClientOption(self, "warsowbunny_backtosideratio");
+       self.stat_sv_friction = Physics_ClientOption(self, "friction");
+       self.stat_sv_accelerate = Physics_ClientOption(self, "accelerate");
+       self.stat_sv_stopspeed = Physics_ClientOption(self, "stopspeed");
+       self.stat_sv_airaccelerate = Physics_ClientOption(self, "airaccelerate");
+       self.stat_sv_airstopaccelerate = Physics_ClientOption(self, "airstopaccelerate");
+       self.stat_sv_jumpvelocity = Physics_ClientOption(self, "jumpvelocity");
+
+       self.stat_gameplayfix_upvelocityclearsonground = UPWARD_VELOCITY_CLEARS_ONGROUND;
+}
+#endif
+
+float IsMoveInDirection(vector mv, float ang) // key mix factor
+{
+       if (mv_x == 0 && mv_y == 0)
+               return 0; // avoid division by zero
+       ang -= RAD2DEG * atan2(mv_y, mv_x);
+       ang = remainder(ang, 360) / 45;
+       return ang > 1 ? 0 : ang < -1 ? 0 : 1 - fabs(ang);
+}
+
+float GeomLerp(float a, float lerp, float b)
+{
+       return a == 0 ? (lerp < 1 ? 0 : b)
+               : b == 0 ? (lerp > 0 ? 0 : a)
+               : a * pow(fabs(b / a), lerp);
+}
+
+noref float pmove_waterjumptime;
+
+const float unstick_count = 27;
+vector unstick_offsets[unstick_count] =
+{
+// 1 no nudge (just return the original if this test passes)
+       '0.000   0.000  0.000',
+// 6 simple nudges
+       ' 0.000  0.000  0.125', '0.000  0.000 -0.125',
+       '-0.125  0.000  0.000', '0.125  0.000  0.000',
+       ' 0.000 -0.125  0.000', '0.000  0.125  0.000',
+// 4 diagonal flat nudges
+       '-0.125 -0.125  0.000', '0.125 -0.125  0.000',
+       '-0.125  0.125  0.000', '0.125  0.125  0.000',
+// 8 diagonal upward nudges
+       '-0.125  0.000  0.125', '0.125  0.000  0.125',
+       ' 0.000 -0.125  0.125', '0.000  0.125  0.125',
+       '-0.125 -0.125  0.125', '0.125 -0.125  0.125',
+       '-0.125  0.125  0.125', '0.125  0.125  0.125',
+// 8 diagonal downward nudges
+       '-0.125  0.000 -0.125', '0.125  0.000 -0.125',
+       ' 0.000 -0.125 -0.125', '0.000  0.125 -0.125',
+       '-0.125 -0.125 -0.125', '0.125 -0.125 -0.125',
+       '-0.125  0.125 -0.125', '0.125  0.125 -0.125',
+};
+
+void PM_ClientMovement_Unstick()
+{
+       float i;
+       for (i = 0; i < unstick_count; i++)
+       {
+               vector neworigin = unstick_offsets[i] + self.origin;
+               tracebox(neworigin, PL_CROUCH_MIN, PL_CROUCH_MAX, neworigin, MOVE_NORMAL, self);
+               if (!trace_startsolid)
+               {
+                       setorigin(self, neworigin);
+                       return;// true;
+               }
+       }
+}
+
+void PM_ClientMovement_UpdateStatus(bool ground)
+{
+       // make sure player is not stuck
+       PM_ClientMovement_Unstick();
+
+       // set crouched
+       if (PHYS_INPUT_BUTTON_CROUCH(self))
+       {
+               // wants to crouch, this always works..
+               if (!IS_DUCKED(self))
+                       SET_DUCKED(self);
+       }
+       else
+       {
+               // wants to stand, if currently crouching we need to check for a
+               // low ceiling first
+               if (IS_DUCKED(self))
+               {
+                       tracebox(self.origin, PL_MIN, PL_MAX, self.origin, MOVE_NORMAL, self);
+                       if (!trace_startsolid)
+                               UNSET_DUCKED(self);
+               }
+       }
+
+       // set onground
+       vector origin1 = self.origin + '0 0 1';
+       vector origin2 = self.origin - '0 0 1';
+
+       if(ground)
+       {
+               tracebox(origin1, self.mins, self.maxs, origin2, MOVE_NORMAL, self);
+               if (trace_fraction < 1.0 && trace_plane_normal_z > 0.7)
+               {
+                       SET_ONGROUND(self);
+
+                       // this code actually "predicts" an impact; so let's clip velocity first
+                       float f = self.velocity * trace_plane_normal;
+                       self.velocity -= f * trace_plane_normal;
+               }
+               else
+                       UNSET_ONGROUND(self);
+       }
+
+       // set watertype/waterlevel
+       origin1 = self.origin;
+       origin1_z += self.mins_z + 1;
+       self.waterlevel = WATERLEVEL_NONE;
+
+       int thepoint = pointcontents(origin1);
+
+       self.watertype = (thepoint == CONTENT_WATER || thepoint == CONTENT_LAVA || thepoint == CONTENT_SLIME);
+
+       if(self.watertype)
+       {
+               self.waterlevel = WATERLEVEL_WETFEET;
+               origin1_z = self.origin_z + (self.mins_z + self.maxs_z) * 0.5;
+               thepoint = pointcontents(origin1);
+               if(thepoint == CONTENT_WATER || thepoint == CONTENT_LAVA || thepoint == CONTENT_SLIME)
+               {
+                       self.waterlevel = WATERLEVEL_SWIMMING;
+                       origin1_z = self.origin_z + 22;
+                       thepoint = pointcontents(origin1);
+                       if(thepoint == CONTENT_WATER || thepoint == CONTENT_LAVA || thepoint == CONTENT_SLIME)
+                               self.waterlevel = WATERLEVEL_SUBMERGED;
+               }
+       }
+
+       if(IS_ONGROUND(self) || self.velocity_z <= 0 || pmove_waterjumptime <= 0)
+               pmove_waterjumptime = 0;
+}
+
+void PM_ClientMovement_Move()
+{
+#ifdef CSQC
+       int bump;
+       float t;
+       float f;
+       vector neworigin;
+       vector currentorigin2;
+       vector neworigin2;
+       vector primalvelocity;
+
+       vector trace1_endpos = '0 0 0';
+       vector trace2_endpos = '0 0 0';
+       vector trace3_endpos = '0 0 0';
+       float trace1_fraction = 0;
+       float trace2_fraction = 0;
+       float trace3_fraction = 0;
+       vector trace1_plane_normal = '0 0 0';
+       vector trace2_plane_normal = '0 0 0';
+       vector trace3_plane_normal = '0 0 0';
+       
+
+       PM_ClientMovement_UpdateStatus(false);
+       primalvelocity = self.velocity;
+       for(bump = 0, t = PHYS_INPUT_TIMELENGTH; bump < 8 && (self.velocity * self.velocity) > 0; bump++)
+       {
+               neworigin = self.origin + t * self.velocity;
+               tracebox(self.origin, self.mins, self.maxs, neworigin, MOVE_NORMAL, self);
+               trace1_endpos = trace_endpos;
+               trace1_fraction = trace_fraction;
+               trace1_plane_normal = trace_plane_normal;
+               if(trace1_fraction < 1 && trace1_plane_normal_z == 0)
+               {
+                       // may be a step or wall, try stepping up
+                       // first move forward at a higher level
+                       currentorigin2 = self.origin;
+                       currentorigin2_z += PHYS_STEPHEIGHT;
+                       neworigin2 = neworigin;
+                       neworigin2_z += PHYS_STEPHEIGHT;
+                       tracebox(currentorigin2, self.mins, self.maxs, neworigin2, MOVE_NORMAL, self);
+                       trace2_endpos = trace_endpos;
+                       trace2_fraction = trace_fraction;
+                       trace2_plane_normal = trace_plane_normal;
+                       if(!trace_startsolid)
+                       {
+                               // then move down from there
+                               currentorigin2 = trace2_endpos;
+                               neworigin2 = trace2_endpos;
+                               neworigin2_z = self.origin_z;
+                               tracebox(currentorigin2, self.mins, self.maxs, neworigin2, MOVE_NORMAL, self);
+                               trace3_endpos = trace_endpos;
+                               trace3_fraction = trace_fraction;
+                               trace3_plane_normal = trace_plane_normal;
+                               // accept the new trace if it made some progress
+                               if(fabs(trace3_endpos_x - trace1_endpos_x) >= 0.03125 || fabs(trace3_endpos_y - trace1_endpos_y) >= 0.03125)
+                               {
+                                       trace1_endpos = trace2_endpos;
+                                       trace1_fraction = trace2_fraction;
+                                       trace1_plane_normal = trace2_plane_normal;
+                                       trace1_endpos = trace3_endpos;
+                               }
+                       }
+               }
+
+               // check if it moved at all
+               if(trace1_fraction >= 0.001)
+                       setorigin(self, trace1_endpos);
+
+               // check if it moved all the way
+               if(trace1_fraction == 1)
+                       break;
+
+               // this is only really needed for nogravityonground combined with gravityunaffectedbyticrate
+               // <LordHavoc> I'm pretty sure I commented it out solely because it seemed redundant
+               // this got commented out in a change that supposedly makes the code match QW better
+               // so if this is broken, maybe put it in an if(cls.protocol != PROTOCOL_QUAKEWORLD) block
+               if(trace1_plane_normal_z > 0.7)
+                       SET_ONGROUND(self);
+
+               t -= t * trace1_fraction;
+
+               f = (self.velocity * trace1_plane_normal);
+               self.velocity = self.velocity + -f * trace1_plane_normal;
+       }
+       if(pmove_waterjumptime > 0)
+               self.velocity = primalvelocity;
+#endif
+}
+
+void CPM_PM_Aircontrol(vector wishdir, float wishspeed)
+{
+       float k = 32 * (2 * IsMoveInDirection(self.movement, 0) - 1);
+       if (k <= 0)
+               return;
+
+       k *= bound(0, wishspeed / PHYS_MAXAIRSPEED(self), 1);
+
+       float zspeed = self.velocity_z;
+       self.velocity_z = 0;
+       float xyspeed = vlen(self.velocity);
+       self.velocity = normalize(self.velocity);
+
+       float dot = self.velocity * wishdir;
+
+       if (dot > 0) // we can't change direction while slowing down
+       {
+               k *= pow(dot, PHYS_AIRCONTROL_POWER) * PHYS_INPUT_TIMELENGTH;
+               xyspeed = max(0, xyspeed - PHYS_AIRCONTROL_PENALTY * sqrt(max(0, 1 - dot*dot)) * k/32);
+               k *= PHYS_AIRCONTROL;
+               self.velocity = normalize(self.velocity * xyspeed + wishdir * k);
+       }
+
+       self.velocity = self.velocity * xyspeed;
+       self.velocity_z = zspeed;
+}
+
+float AdjustAirAccelQW(float accelqw, float factor)
+{
+       return copysign(bound(0.000001, 1 - (1 - fabs(accelqw)) * factor, 1), accelqw);
+}
+
+// example config for alternate speed clamping:
+//   sv_airaccel_qw 0.8
+//   sv_airaccel_sideways_friction 0
+//   prvm_globalset server speedclamp_mode 1
+//     (or 2)
+void PM_Accelerate(vector wishdir, float wishspeed, float wishspeed0, float accel, float accelqw, float stretchfactor, float sidefric, float speedlimit)
+{
+       float speedclamp = stretchfactor > 0 ? stretchfactor
+       : accelqw < 0 ? 1 // full clamping, no stretch
+       : -1; // no clamping
+
+       accelqw = fabs(accelqw);
+
+       if (GAMEPLAYFIX_Q2AIRACCELERATE)
+               wishspeed0 = wishspeed; // don't need to emulate this Q1 bug
+
+       float vel_straight = self.velocity * wishdir;
+       float vel_z = self.velocity_z;
+       vector vel_xy = vec2(self.velocity);
+       vector vel_perpend = vel_xy - vel_straight * wishdir;
+
+       float step = accel * PHYS_INPUT_TIMELENGTH * wishspeed0;
+
+       float vel_xy_current  = vlen(vel_xy);
+       if (speedlimit)
+               accelqw = AdjustAirAccelQW(accelqw, (speedlimit - bound(wishspeed, vel_xy_current, speedlimit)) / max(1, speedlimit - wishspeed));
+       float vel_xy_forward =  vel_xy_current  + bound(0, wishspeed - vel_xy_current, step) * accelqw + step * (1 - accelqw);
+       float vel_xy_backward = vel_xy_current  - bound(0, wishspeed + vel_xy_current, step) * accelqw - step * (1 - accelqw);
+       vel_xy_backward = max(0, vel_xy_backward); // not that it REALLY occurs that this would cause wrong behaviour afterwards
+       vel_straight =          vel_straight    + bound(0, wishspeed - vel_straight,   step) * accelqw + step * (1 - accelqw);
+
+       if (sidefric < 0 && (vel_perpend*vel_perpend))
+               // negative: only apply so much sideways friction to stay below the speed you could get by "braking"
+       {
+               float f = max(0, 1 + PHYS_INPUT_TIMELENGTH * wishspeed * sidefric);
+               float fmin = (vel_xy_backward * vel_xy_backward - vel_straight * vel_straight) / (vel_perpend * vel_perpend);
+               // assume: fmin > 1
+               // vel_xy_backward*vel_xy_backward - vel_straight*vel_straight > vel_perpend*vel_perpend
+               // vel_xy_backward*vel_xy_backward > vel_straight*vel_straight + vel_perpend*vel_perpend
+               // vel_xy_backward*vel_xy_backward > vel_xy * vel_xy
+               // obviously, this cannot be
+               if (fmin <= 0)
+                       vel_perpend *= f;
+               else
+               {
+                       fmin = sqrt(fmin);
+                       vel_perpend *= max(fmin, f);
+               }
+       }
+       else
+               vel_perpend *= max(0, 1 - PHYS_INPUT_TIMELENGTH * wishspeed * sidefric);
+
+       vel_xy = vel_straight * wishdir + vel_perpend;
+
+       if (speedclamp >= 0)
+       {
+               float vel_xy_preclamp;
+               vel_xy_preclamp = vlen(vel_xy);
+               if (vel_xy_preclamp > 0) // prevent division by zero
+               {
+                       vel_xy_current += (vel_xy_forward - vel_xy_current) * speedclamp;
+                       if (vel_xy_current < vel_xy_preclamp)
+                               vel_xy *= (vel_xy_current / vel_xy_preclamp);
+               }
+       }
+
+       self.velocity = vel_xy + vel_z * '0 0 1';
+}
+
+void PM_AirAccelerate(vector wishdir, float wishspeed)
+{
+       if (wishspeed == 0)
+               return;
+
+       vector curvel = self.velocity;
+       curvel_z = 0;
+       float curspeed = vlen(curvel);
+
+       if (wishspeed > curspeed * 1.01)
+               wishspeed = min(wishspeed, curspeed + PHYS_WARSOWBUNNY_AIRFORWARDACCEL * PHYS_MAXSPEED(self) * PHYS_INPUT_TIMELENGTH);
+       else
+       {
+               float f = max(0, (PHYS_WARSOWBUNNY_TOPSPEED - curspeed) / (PHYS_WARSOWBUNNY_TOPSPEED - PHYS_MAXSPEED(self)));
+               wishspeed = max(curspeed, PHYS_MAXSPEED(self)) + PHYS_WARSOWBUNNY_ACCEL * f * PHYS_MAXSPEED(self) * PHYS_INPUT_TIMELENGTH;
+       }
+       vector wishvel = wishdir * wishspeed;
+       vector acceldir = wishvel - curvel;
+       float addspeed = vlen(acceldir);
+       acceldir = normalize(acceldir);
+
+       float accelspeed = min(addspeed, PHYS_WARSOWBUNNY_TURNACCEL * PHYS_MAXSPEED(self) * PHYS_INPUT_TIMELENGTH);
+
+       if (PHYS_WARSOWBUNNY_BACKTOSIDERATIO < 1)
+       {
+               vector curdir = normalize(curvel);
+               float dot = acceldir * curdir;
+               if (dot < 0)
+                       acceldir -= (1 - PHYS_WARSOWBUNNY_BACKTOSIDERATIO) * dot * curdir;
+       }
+
+       self.velocity += accelspeed * acceldir;
+}
+
+
+/*
+=============
+PlayerJump
+
+When you press the jump key
+returns true if handled
+=============
+*/
+bool PlayerJump (void)
+{
+       if (PHYS_FROZEN(self))
+               return true; // no jumping in freezetag when frozen
+
+#ifdef SVQC
+       if (self.player_blocked)
+               return true; // no jumping while blocked
+#endif
+
+       bool doublejump = false;
+       float mjumpheight = PHYS_JUMPVELOCITY;
+
+       player_multijump = doublejump;
+       player_jumpheight = mjumpheight;
+#ifdef SVQC
+       if (MUTATOR_CALLHOOK(PlayerJump))
+#elif defined(CSQC)
+       if(PM_multijump_checkjump())
+#endif
+               return true;
+
+       doublejump = player_multijump;
+       mjumpheight = player_jumpheight;
+
+       if (PHYS_DOUBLEJUMP)
+       {
+               tracebox(self.origin + '0 0 0.01', self.mins, self.maxs, self.origin - '0 0 0.01', MOVE_NORMAL, self);
+               if (trace_fraction < 1 && trace_plane_normal_z > 0.7)
+               {
+                       doublejump = true;
+
+                       // we MUST clip velocity here!
+                       float f;
+                       f = self.velocity * trace_plane_normal;
+                       if (f < 0)
+                               self.velocity -= f * trace_plane_normal;
+               }
+       }
+
+       if (self.waterlevel >= WATERLEVEL_SWIMMING)
+       {
+               self.velocity_z = PHYS_MAXSPEED(self) * 0.7;
+               return true;
+       }
+
+       if (!doublejump)
+               if (!IS_ONGROUND(self))
+                       return IS_JUMP_HELD(self);
+
+       if (PHYS_TRACK_CANJUMP(self))
+               if (IS_JUMP_HELD(self))
+                       return true;
+
+       // sv_jumpspeedcap_min/sv_jumpspeedcap_max act as baseline
+       // velocity bounds.  Final velocity is bound between (jumpheight *
+       // min + jumpheight) and (jumpheight * max + jumpheight);
+
+       if(PHYS_JUMPSPEEDCAP_MIN)
+       {
+               float minjumpspeed = mjumpheight * PHYS_JUMPSPEEDCAP_MIN;
+
+               if (self.velocity_z < minjumpspeed)
+                       mjumpheight += minjumpspeed - self.velocity_z;
+       }
+
+       if(PHYS_JUMPSPEEDCAP_MAX)
+       {
+               // don't do jump speedcaps on ramps to preserve old xonotic ramjump style
+               tracebox(self.origin + '0 0 0.01', self.mins, self.maxs, self.origin - '0 0 0.01', MOVE_NORMAL, self);
+
+               if (!(trace_fraction < 1 && trace_plane_normal_z < 0.98 && PHYS_JUMPSPEEDCAP_DISABLE_ONRAMPS))
+               {
+                       float maxjumpspeed = mjumpheight * PHYS_JUMPSPEEDCAP_MAX;
+
+                       if (self.velocity_z > maxjumpspeed)
+                               mjumpheight -= self.velocity_z - maxjumpspeed;
+               }
+       }
+
+       if (!WAS_ONGROUND(self))
+       {
+#ifdef SVQC
+               if(autocvar_speedmeter)
+                       dprint(strcat("landing velocity: ", vtos(self.velocity), " (abs: ", ftos(vlen(self.velocity)), ")\n"));
+#endif
+               if(self.lastground < time - 0.3)
+               {
+                       self.velocity_x *= (1 - PHYS_FRICTION_ONLAND);
+                       self.velocity_y *= (1 - PHYS_FRICTION_ONLAND);
+               }
+#ifdef SVQC
+               if(self.jumppadcount > 1)
+                       dprint(strcat(ftos(self.jumppadcount), "x jumppad combo\n"));
+               self.jumppadcount = 0;
+#endif
+       }
+
+       self.velocity_z += mjumpheight;
+
+       UNSET_ONGROUND(self);
+       SET_JUMP_HELD(self);
+
+#ifdef SVQC
+
+       self.oldvelocity_z = self.velocity_z;
+
+       animdecide_setaction(self, ANIMACTION_JUMP, true);
+
+       if (autocvar_g_jump_grunt)
+               PlayerSound(playersound_jump, CH_PLAYER, VOICETYPE_PLAYERSOUND);
+#endif
+       return true;
+}
+
+void CheckWaterJump()
+{
+// check for a jump-out-of-water
+       makevectors(self.v_angle);
+       vector start = self.origin;
+       start_z += 8;
+       v_forward_z = 0;
+       normalize(v_forward);
+       vector end = start + v_forward*24;
+       traceline (start, end, true, self);
+       if (trace_fraction < 1)
+       {       // solid at waist
+               start_z = start_z + self.maxs_z - 8;
+               end = start + v_forward*24;
+               self.movedir = trace_plane_normal * -50;
+               traceline(start, end, true, self);
+               if (trace_fraction == 1)
+               {       // open at eye level
+                       self.velocity_z = 225;
+                       self.flags |= FL_WATERJUMP;
+                       SET_JUMP_HELD(self);
+#ifdef SVQC
+                       self.teleport_time = time + 2;  // safety net
+#elif defined(CSQC)
+                       pmove_waterjumptime = time + 2;
+#endif
+               }
+       }
+}
+
+
+#ifdef SVQC
+       #define JETPACK_JUMP(s) s.cvar_cl_jetpack_jump
+#elif defined(CSQC)
+       float autocvar_cl_jetpack_jump;
+       #define JETPACK_JUMP(s) autocvar_cl_jetpack_jump
+#endif
+.float jetpack_stopped;
+// Hack: shouldn't need to know about this
+.float multijump_count;
+void CheckPlayerJump()
+{
+#ifdef SVQC
+       float was_flying = ITEMS_STAT(self) & IT_USING_JETPACK;
+#endif
+       if (JETPACK_JUMP(self) < 2)
+               ITEMS_STAT(self) &= ~IT_USING_JETPACK;
+
+       if(PHYS_INPUT_BUTTON_JUMP(self) || PHYS_INPUT_BUTTON_JETPACK(self))
+       {
+               float air_jump = !PlayerJump() || self.multijump_count > 0; // PlayerJump() has important side effects
+               float activate = JETPACK_JUMP(self) && air_jump && PHYS_INPUT_BUTTON_JUMP(self) || PHYS_INPUT_BUTTON_JETPACK(self);
+               float has_fuel = !PHYS_JETPACK_FUEL || PHYS_AMMO_FUEL(self) || ITEMS_STAT(self) & IT_UNLIMITED_WEAPON_AMMO;
+
+               if (!(ITEMS_STAT(self) & IT_JETPACK)) { }
+               else if (self.jetpack_stopped) { }
+               else if (!has_fuel)
+               {
+#ifdef SVQC
+                       if (was_flying) // TODO: ran out of fuel message
+                               Send_Notification(NOTIF_ONE, self, MSG_INFO, INFO_JETPACK_NOFUEL);
+                       else if (activate)
+                               Send_Notification(NOTIF_ONE, self, MSG_INFO, INFO_JETPACK_NOFUEL);
+#endif
+                       self.jetpack_stopped = true;
+                       ITEMS_STAT(self) &= ~IT_USING_JETPACK;
+               }
+               else if (activate && !PHYS_FROZEN(self))
+                       ITEMS_STAT(self) |= IT_USING_JETPACK;
+       }
+       else
+       {
+               self.jetpack_stopped = false;
+               ITEMS_STAT(self) &= ~IT_USING_JETPACK;
+       }
+       if (!PHYS_INPUT_BUTTON_JUMP(self))
+               UNSET_JUMP_HELD(self);
+
+       if (self.waterlevel == WATERLEVEL_SWIMMING)
+               CheckWaterJump();
+}
+
+float racecar_angle(float forward, float down)
+{
+       if (forward < 0)
+       {
+               forward = -forward;
+               down = -down;
+       }
+
+       float ret = vectoyaw('0 1 0' * down + '1 0 0' * forward);
+
+       float angle_mult = forward / (800 + forward);
+
+       if (ret > 180)
+               return ret * angle_mult + 360 * (1 - angle_mult);
+       else
+               return ret * angle_mult;
+}
+
+void RaceCarPhysics()
+{
+#ifdef SVQC
+       // using this move type for "big rigs"
+       // the engine does not push the entity!
+
+       vector rigvel;
+
+       vector angles_save = self.angles;
+       float accel = bound(-1, self.movement.x / PHYS_MAXSPEED(self), 1);
+       float steer = bound(-1, self.movement.y / PHYS_MAXSPEED(self), 1);
+
+       if (g_bugrigs_reverse_speeding)
+       {
+               if (accel < 0)
+               {
+                       // back accel is DIGITAL
+                       // to prevent speedhack
+                       if (accel < -0.5)
+                               accel = -1;
+                       else
+                               accel = 0;
+               }
+       }
+
+       self.angles_x = 0;
+       self.angles_z = 0;
+       makevectors(self.angles); // new forward direction!
+
+       if (IS_ONGROUND(self) || g_bugrigs_air_steering)
+       {
+               float myspeed = self.velocity * v_forward;
+               float upspeed = self.velocity * v_up;
+
+               // responsiveness factor for steering and acceleration
+               float f = 1 / (1 + pow(max(-myspeed, myspeed) / g_bugrigs_speed_ref, g_bugrigs_speed_pow));
+               //MAXIMA: f(v) := 1 / (1 + (v / g_bugrigs_speed_ref) ^ g_bugrigs_speed_pow);
+
+               float steerfactor;
+               if (myspeed < 0 && g_bugrigs_reverse_spinning)
+                       steerfactor = -myspeed * g_bugrigs_steer;
+               else
+                       steerfactor = -myspeed * f * g_bugrigs_steer;
+
+               float accelfactor;
+               if (myspeed < 0 && g_bugrigs_reverse_speeding)
+                       accelfactor = g_bugrigs_accel;
+               else
+                       accelfactor = f * g_bugrigs_accel;
+               //MAXIMA: accel(v) := f(v) * g_bugrigs_accel;
+
+               if (accel < 0)
+               {
+                       if (myspeed > 0)
+                       {
+                               myspeed = max(0, myspeed - PHYS_INPUT_TIMELENGTH * (g_bugrigs_friction_floor - g_bugrigs_friction_brake * accel));
+                       }
+                       else
+                       {
+                               if (!g_bugrigs_reverse_speeding)
+                                       myspeed = min(0, myspeed + PHYS_INPUT_TIMELENGTH * g_bugrigs_friction_floor);
+                       }
+               }
+               else
+               {
+                       if (myspeed >= 0)
+                       {
+                               myspeed = max(0, myspeed - PHYS_INPUT_TIMELENGTH * g_bugrigs_friction_floor);
+                       }
+                       else
+                       {
+                               if (g_bugrigs_reverse_stopping)
+                                       myspeed = 0;
+                               else
+                                       myspeed = min(0, myspeed + PHYS_INPUT_TIMELENGTH * (g_bugrigs_friction_floor + g_bugrigs_friction_brake * accel));
+                       }
+               }
+               // terminal velocity = velocity at which 50 == accelfactor, that is, 1549 units/sec
+               //MAXIMA: friction(v) := g_bugrigs_friction_floor;
+
+               self.angles_y += steer * PHYS_INPUT_TIMELENGTH * steerfactor; // apply steering
+               makevectors(self.angles); // new forward direction!
+
+               myspeed += accel * accelfactor * PHYS_INPUT_TIMELENGTH;
+
+               rigvel = myspeed * v_forward + '0 0 1' * upspeed;
+       }
+       else
+       {
+               float myspeed = vlen(self.velocity);
+
+               // responsiveness factor for steering and acceleration
+               float f = 1 / (1 + pow(max(0, myspeed / g_bugrigs_speed_ref), g_bugrigs_speed_pow));
+               float steerfactor = -myspeed * f;
+               self.angles_y += steer * PHYS_INPUT_TIMELENGTH * steerfactor; // apply steering
+
+               rigvel = self.velocity;
+               makevectors(self.angles); // new forward direction!
+       }
+
+       rigvel *= max(0, 1 - vlen(rigvel) * g_bugrigs_friction_air * PHYS_INPUT_TIMELENGTH);
+       //MAXIMA: airfriction(v) := v * v * g_bugrigs_friction_air;
+       //MAXIMA: total_acceleration(v) := accel(v) - friction(v) - airfriction(v);
+       //MAXIMA: solve(total_acceleration(v) = 0, v);
+
+       if (g_bugrigs_planar_movement)
+       {
+               vector rigvel_xy, neworigin, up;
+               float mt;
+
+               rigvel_z -= PHYS_INPUT_TIMELENGTH * PHYS_GRAVITY; // 4x gravity plays better
+               rigvel_xy = vec2(rigvel);
+
+               if (g_bugrigs_planar_movement_car_jumping)
+                       mt = MOVE_NORMAL;
+               else
+                       mt = MOVE_NOMONSTERS;
+
+               tracebox(self.origin, self.mins, self.maxs, self.origin + '0 0 1024', mt, self);
+               up = trace_endpos - self.origin;
+
+               // BUG RIGS: align the move to the surface instead of doing collision testing
+               // can we move?
+               tracebox(trace_endpos, self.mins, self.maxs, trace_endpos + rigvel_xy * PHYS_INPUT_TIMELENGTH, mt, self);
+
+               // align to surface
+               tracebox(trace_endpos, self.mins, self.maxs, trace_endpos - up + '0 0 1' * rigvel_z * PHYS_INPUT_TIMELENGTH, mt, self);
+
+               if (trace_fraction < 0.5)
+               {
+                       trace_fraction = 1;
+                       neworigin = self.origin;
+               }
+               else
+                       neworigin = trace_endpos;
+
+               if (trace_fraction < 1)
+               {
+                       // now set angles_x so that the car points parallel to the surface
+                       self.angles = vectoangles(
+                                       '1 0 0' * v_forward_x * trace_plane_normal_z
+                                       +
+                                       '0 1 0' * v_forward_y * trace_plane_normal_z
+                                       +
+                                       '0 0 1' * -(v_forward_x * trace_plane_normal_x + v_forward_y * trace_plane_normal_y)
+                                       );
+                       SET_ONGROUND(self);
+               }
+               else
+               {
+                       // now set angles_x so that the car points forward, but is tilted in velocity direction
+                       UNSET_ONGROUND(self);
+               }
+
+               self.velocity = (neworigin - self.origin) * (1.0 / PHYS_INPUT_TIMELENGTH);
+               self.movetype = MOVETYPE_NOCLIP;
+       }
+       else
+       {
+               rigvel_z -= PHYS_INPUT_TIMELENGTH * PHYS_GRAVITY; // 4x gravity plays better
+               self.velocity = rigvel;
+               self.movetype = MOVETYPE_FLY;
+       }
+
+       trace_fraction = 1;
+       tracebox(self.origin, self.mins, self.maxs, self.origin - '0 0 4', MOVE_NORMAL, self);
+       if (trace_fraction != 1)
+       {
+               self.angles = vectoangles2(
+                               '1 0 0' * v_forward_x * trace_plane_normal_z
+                               +
+                               '0 1 0' * v_forward_y * trace_plane_normal_z
+                               +
+                               '0 0 1' * -(v_forward_x * trace_plane_normal_x + v_forward_y * trace_plane_normal_y),
+                               trace_plane_normal
+                               );
+       }
+       else
+       {
+               vector vel_local;
+
+               vel_local_x = v_forward * self.velocity;
+               vel_local_y = v_right * self.velocity;
+               vel_local_z = v_up * self.velocity;
+
+               self.angles_x = racecar_angle(vel_local_x, vel_local_z);
+               self.angles_z = racecar_angle(-vel_local_y, vel_local_z);
+       }
+
+       // smooth the angles
+       vector vf1, vu1, smoothangles;
+       makevectors(self.angles);
+       float f = bound(0, PHYS_INPUT_TIMELENGTH * g_bugrigs_angle_smoothing, 1);
+       if (f == 0)
+               f = 1;
+       vf1 = v_forward * f;
+       vu1 = v_up * f;
+       makevectors(angles_save);
+       vf1 = vf1 + v_forward * (1 - f);
+       vu1 = vu1 + v_up * (1 - f);
+       smoothangles = vectoangles2(vf1, vu1);
+       self.angles_x = -smoothangles_x;
+       self.angles_z =  smoothangles_z;
+#endif
+}
+
+string specialcommand = "xwxwxsxsxaxdxaxdx1x ";
+.float specialcommand_pos;
+void SpecialCommand()
+{
+#ifdef SVQC
+#ifdef TETRIS
+       TetrisImpulse();
+#else
+       if (!CheatImpulse(99))
+               print("A hollow voice says \"Plugh\".\n");
+#endif
+#endif
+}
+
+float PM_check_keepaway(void)
+{
+#ifdef SVQC
+       return (self.ballcarried && g_keepaway) ? autocvar_g_keepaway_ballcarrier_highspeed : 1;
+#else
+       return 1;
+#endif
+}
+
+void PM_check_race_movetime(void)
+{
+#ifdef SVQC
+       self.race_movetime_frac += PHYS_INPUT_TIMELENGTH;
+       float f = floor(self.race_movetime_frac);
+       self.race_movetime_frac -= f;
+       self.race_movetime_count += f;
+       self.race_movetime = self.race_movetime_frac + self.race_movetime_count;
+#endif
+}
+
+float PM_check_specialcommand(float buttons)
+{
+#ifdef SVQC
+       string c;
+       if (!buttons)
+               c = "x";
+       else if (buttons == 1)
+               c = "1";
+       else if (buttons == 2)
+               c = " ";
+       else if (buttons == 128)
+               c = "s";
+       else if (buttons == 256)
+               c = "w";
+       else if (buttons == 512)
+               c = "a";
+       else if (buttons == 1024)
+               c = "d";
+       else
+               c = "?";
+
+       if (c == substring(specialcommand, self.specialcommand_pos, 1))
+       {
+               self.specialcommand_pos += 1;
+               if (self.specialcommand_pos >= strlen(specialcommand))
+               {
+                       self.specialcommand_pos = 0;
+                       SpecialCommand();
+                       return true;
+               }
+       }
+       else if (self.specialcommand_pos && (c != substring(specialcommand, self.specialcommand_pos - 1, 1)))
+               self.specialcommand_pos = 0;
+#endif
+       return false;
+}
+
+void PM_check_nickspam(void)
+{
+#ifdef SVQC
+       if (time >= self.nickspamtime)
+               return;
+       if (self.nickspamcount >= autocvar_g_nick_flood_penalty_yellow)
+       {
+               // slight annoyance for nick change scripts
+               self.movement = -1 * self.movement;
+               self.BUTTON_ATCK = self.BUTTON_JUMP = self.BUTTON_ATCK2 = self.BUTTON_ZOOM = self.BUTTON_CROUCH = self.BUTTON_HOOK = self.BUTTON_USE = 0;
+
+               if (self.nickspamcount >= autocvar_g_nick_flood_penalty_red) // if you are persistent and the slight annoyance above does not stop you, I'll show you!
+               {
+                       self.v_angle_x = random() * 360;
+                       self.v_angle_y = random() * 360;
+                       // at least I'm not forcing retardedview by also assigning to angles_z
+                       self.fixangle = true;
+               }
+       }
+#endif
+}
+
+void PM_check_punch()
+{
+#ifdef SVQC
+       if (self.punchangle != '0 0 0')
+       {
+               float f = vlen(self.punchangle) - 10 * PHYS_INPUT_TIMELENGTH;
+               if (f > 0)
+                       self.punchangle = normalize(self.punchangle) * f;
+               else
+                       self.punchangle = '0 0 0';
+       }
+
+       if (self.punchvector != '0 0 0')
+       {
+               float f = vlen(self.punchvector) - 30 * PHYS_INPUT_TIMELENGTH;
+               if (f > 0)
+                       self.punchvector = normalize(self.punchvector) * f;
+               else
+                       self.punchvector = '0 0 0';
+       }
+#endif
+}
+
+void PM_check_spider(void)
+{
+#ifdef SVQC
+       if (time >= self.spider_slowness)
+               return;
+       PHYS_MAXSPEED(self) *= 0.5; // half speed while slow from spider
+       PHYS_MAXAIRSPEED(self) *= 0.5;
+       PHYS_AIRSPEEDLIMIT_NONQW(self) *= 0.5;
+       PHYS_AIRSTRAFEACCELERATE(self) *= 0.5;
+#endif
+}
+
+// predict frozen movement, as frozen players CAN move in some cases
+void PM_check_frozen(void)
+{
+       if (!PHYS_FROZEN(self))
+               return;
+       if (PHYS_DODGING_FROZEN
+#ifdef SVQC
+       && IS_REAL_CLIENT(self)
+#endif
+       )
+       {
+               self.movement_x = bound(-5, self.movement.x, 5);
+               self.movement_y = bound(-5, self.movement.y, 5);
+               self.movement_z = bound(-5, self.movement.z, 5);
+       }
+       else
+               self.movement = '0 0 0';
+
+       vector midpoint = ((self.absmin + self.absmax) * 0.5);
+       if (pointcontents(midpoint) == CONTENT_WATER)
+       {
+               self.velocity = self.velocity * 0.5;
+
+               if (pointcontents(midpoint + '0 0 16') == CONTENT_WATER)
+                       self.velocity_z = 200;
+       }
+}
+
+void PM_check_hitground()
+{
+#ifdef SVQC
+       if (IS_ONGROUND(self))
+       if (IS_PLAYER(self)) // no fall sounds for observers thank you very much
+       if (self.wasFlying)
+       {
+               self.wasFlying = 0;
+               if (self.waterlevel < WATERLEVEL_SWIMMING)
+               if (time >= self.ladder_time)
+               if (!self.hook)
+               {
+                       self.nextstep = time + 0.3 + random() * 0.1;
+                       trace_dphitq3surfaceflags = 0;
+                       tracebox(self.origin, self.mins, self.maxs, self.origin - '0 0 1', MOVE_NOMONSTERS, self);
+                       if (!(trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOSTEPS))
+                       {
+                               if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_METALSTEPS)
+                                       GlobalSound(globalsound_metalfall, CH_PLAYER, VOICETYPE_PLAYERSOUND);
+                               else
+                                       GlobalSound(globalsound_fall, CH_PLAYER, VOICETYPE_PLAYERSOUND);
+                       }
+               }
+       }
+#endif
+}
+
+void PM_check_blocked(void)
+{
+#ifdef SVQC
+       if (!self.player_blocked)
+               return;
+       self.movement = '0 0 0';
+       self.disableclientprediction = 1;
+#endif
+}
+
+#ifdef SVQC
+float speedaward_lastsent;
+float speedaward_lastupdate;
+#endif
+void PM_check_race(void)
+{
+#ifdef SVQC
+       if(!(g_cts || g_race))
+               return;
+       if (vlen(self.velocity - self.velocity_z * '0 0 1') > speedaward_speed)
+       {
+               speedaward_speed = vlen(self.velocity - self.velocity_z * '0 0 1');
+               speedaward_holder = self.netname;
+               speedaward_uid = self.crypto_idfp;
+               speedaward_lastupdate = time;
+       }
+       if (speedaward_speed > speedaward_lastsent && time - speedaward_lastupdate > 1)
+       {
+               string rr = (g_cts) ? CTS_RECORD : RACE_RECORD;
+               race_send_speedaward(MSG_ALL);
+               speedaward_lastsent = speedaward_speed;
+               if (speedaward_speed > speedaward_alltimebest && speedaward_uid != "")
+               {
+                       speedaward_alltimebest = speedaward_speed;
+                       speedaward_alltimebest_holder = speedaward_holder;
+                       speedaward_alltimebest_uid = speedaward_uid;
+                       db_put(ServerProgsDB, strcat(GetMapname(), rr, "speed/speed"), ftos(speedaward_alltimebest));
+                       db_put(ServerProgsDB, strcat(GetMapname(), rr, "speed/crypto_idfp"), speedaward_alltimebest_uid);
+                       race_send_speedaward_alltimebest(MSG_ALL);
+               }
+       }
+#endif
+}
+
+void PM_check_vortex(void)
+{
+#ifdef SVQC
+       // WEAPONTODO
+       float xyspeed = vlen(vec2(self.velocity));
+       if (self.weapon == WEP_VORTEX && WEP_CVAR(vortex, charge) && WEP_CVAR(vortex, charge_velocity_rate) && xyspeed > WEP_CVAR(vortex, charge_minspeed))
+       {
+               // add a maximum of charge_velocity_rate when going fast (f = 1), gradually increasing from minspeed (f = 0) to maxspeed
+               xyspeed = min(xyspeed, WEP_CVAR(vortex, charge_maxspeed));
+               float f = (xyspeed - WEP_CVAR(vortex, charge_minspeed)) / (WEP_CVAR(vortex, charge_maxspeed) - WEP_CVAR(vortex, charge_minspeed));
+               // add the extra charge
+               self.vortex_charge = min(1, self.vortex_charge + WEP_CVAR(vortex, charge_velocity_rate) * f * PHYS_INPUT_TIMELENGTH);
+       }
+#endif
+}
+
+void PM_fly(float maxspd_mod)
+{
+       // noclipping or flying
+       UNSET_ONGROUND(self);
+
+       self.velocity = self.velocity * (1 - PHYS_INPUT_TIMELENGTH * PHYS_FRICTION);
+       makevectors(self.v_angle);
+       //wishvel = v_forward * self.movement.x + v_right * self.movement.y + v_up * self.movement.z;
+       vector wishvel = v_forward * self.movement.x
+                                       + v_right * self.movement.y
+                                       + '0 0 1' * self.movement.z;
+       // acceleration
+       vector wishdir = normalize(wishvel);
+       float wishspeed = min(vlen(wishvel), PHYS_MAXSPEED(self) * maxspd_mod);
+#ifdef SVQC
+       if (time >= self.teleport_time)
+#endif
+               PM_Accelerate(wishdir, wishspeed, wishspeed, PHYS_ACCELERATE * maxspd_mod, 1, 0, 0, 0);
+       PM_ClientMovement_Move();
+}
+
+void PM_swim(float maxspd_mod)
+{
+       // swimming
+       UNSET_ONGROUND(self);
+
+       float jump = PHYS_INPUT_BUTTON_JUMP(self);
+       // water jump only in certain situations
+       // this mimics quakeworld code
+       if (jump && self.waterlevel == WATERLEVEL_SWIMMING && self.velocity_z >= -180)
+       {
+               vector yawangles = '0 1 0' * self.v_angle.y;
+               makevectors(yawangles);
+               vector forward = v_forward;
+               vector spot = self.origin + 24 * forward;
+               spot_z += 8;
+               traceline(spot, spot, MOVE_NOMONSTERS, self);
+               if (trace_startsolid)
+               {
+                       spot_z += 24;
+                       traceline(spot, spot, MOVE_NOMONSTERS, self);
+                       if (!trace_startsolid)
+                       {
+                               self.velocity = forward * 50;
+                               self.velocity_z = 310;
+                               pmove_waterjumptime = 2;
+                               UNSET_ONGROUND(self);
+                               SET_JUMP_HELD(self);
+                       }
+               }
+       }
+       makevectors(self.v_angle);
+       //wishvel = v_forward * self.movement.x + v_right * self.movement.y + v_up * self.movement.z;
+       vector wishvel = v_forward * self.movement.x
+                                       + v_right * self.movement.y
+                                       + '0 0 1' * self.movement.z;
+       if (wishvel == '0 0 0')
+               wishvel = '0 0 -60'; // drift towards bottom
+
+       vector wishdir = normalize(wishvel);
+       float wishspeed = min(vlen(wishvel), PHYS_MAXSPEED(self) * maxspd_mod) * 0.7;
+
+       if (IS_DUCKED(self))
+       wishspeed *= 0.5;
+
+//     if (pmove_waterjumptime <= 0) // TODO: use
+    {
+               // water friction
+               float f = 1 - PHYS_INPUT_TIMELENGTH * PHYS_FRICTION;
+               f = min(max(0, f), 1);
+               self.velocity *= f;
+
+               f = wishspeed - self.velocity * wishdir;
+               if (f > 0)
+               {
+                       float accelspeed = min(PHYS_ACCELERATE * PHYS_INPUT_TIMELENGTH * wishspeed, f);
+                       self.velocity += accelspeed * wishdir;
+               }
+
+               // holding jump button swims upward slowly
+               if (jump)
+               {
+#if 0
+                       if (self.watertype & CONTENT_LAVA)
+                               self.velocity_z =  50;
+                       else if (self.watertype & CONTENT_SLIME)
+                               self.velocity_z =  80;
+                       else
+                       {
+                               if (IS_NEXUIZ_DERIVED(gamemode))
+#endif
+                                       self.velocity_z = 200;
+#if 0
+                               else
+                                       self.velocity_z = 100;
+                       }
+#endif
+               }
+       }
+       // water acceleration
+       PM_Accelerate(wishdir, wishspeed, wishspeed, PHYS_ACCELERATE * maxspd_mod, 1, 0, 0, 0);
+       PM_ClientMovement_Move();
+}
+
+void PM_ladder(float maxspd_mod)
+{
+       // on a spawnfunc_func_ladder or swimming in spawnfunc_func_water
+       UNSET_ONGROUND(self);
+
+       float g;
+       g = PHYS_GRAVITY * PHYS_INPUT_TIMELENGTH;
+       if (PHYS_ENTGRAVITY(self))
+               g *= PHYS_ENTGRAVITY(self);
+       if (GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE)
+       {
+               g *= 0.5;
+               self.velocity_z += g;
+       }
+
+       self.velocity = self.velocity * (1 - PHYS_INPUT_TIMELENGTH * PHYS_FRICTION);
+       makevectors(self.v_angle);
+       //wishvel = v_forward * self.movement.x + v_right * self.movement.y + v_up * self.movement.z;
+       vector wishvel = v_forward * self.movement_x
+                                       + v_right * self.movement_y
+                                       + '0 0 1' * self.movement_z;
+       self.velocity_z += g;
+       if (self.ladder_entity.classname == "func_water")
+       {
+               float f = vlen(wishvel);
+               if (f > self.ladder_entity.speed)
+                       wishvel *= (self.ladder_entity.speed / f);
+
+               self.watertype = self.ladder_entity.skin;
+               f = self.ladder_entity.origin_z + self.ladder_entity.maxs_z;
+               if ((self.origin_z + self.view_ofs_z) < f)
+                       self.waterlevel = WATERLEVEL_SUBMERGED;
+               else if ((self.origin_z + (self.mins_z + self.maxs_z) * 0.5) < f)
+                       self.waterlevel = WATERLEVEL_SWIMMING;
+               else if ((self.origin_z + self.mins_z + 1) < f)
+                       self.waterlevel = WATERLEVEL_WETFEET;
+               else
+               {
+                       self.waterlevel = WATERLEVEL_NONE;
+                       self.watertype = CONTENT_EMPTY;
+               }
+       }
+       // acceleration
+       vector wishdir = normalize(wishvel);
+       float wishspeed = min(vlen(wishvel), PHYS_MAXSPEED(self) * maxspd_mod);
+#ifdef SVQC
+       if (time >= self.teleport_time)
+#endif
+               // water acceleration
+               PM_Accelerate(wishdir, wishspeed, wishspeed, PHYS_ACCELERATE*maxspd_mod, 1, 0, 0, 0);
+       PM_ClientMovement_Move();
+}
+
+void PM_jetpack(float maxspd_mod)
+{
+       //makevectors(self.v_angle.y * '0 1 0');
+       makevectors(self.v_angle);
+       vector wishvel = v_forward * self.movement_x
+                                       + v_right * self.movement_y;
+       // add remaining speed as Z component
+       float maxairspd = PHYS_MAXAIRSPEED(self) * max(1, maxspd_mod);
+       // fix speedhacks :P
+       wishvel = normalize(wishvel) * min(1, vlen(wishvel) / maxairspd);
+       // add the unused velocity as up component
+       wishvel_z = 0;
+
+       // if (self.BUTTON_JUMP)
+               wishvel_z = sqrt(max(0, 1 - wishvel * wishvel));
+
+       // it is now normalized, so...
+       float a_side = PHYS_JETPACK_ACCEL_SIDE;
+       float a_up = PHYS_JETPACK_ACCEL_UP;
+       float a_add = PHYS_JETPACK_ANTIGRAVITY * PHYS_GRAVITY;
+
+       wishvel_x *= a_side;
+       wishvel_y *= a_side;
+       wishvel_z *= a_up;
+       wishvel_z += a_add;
+
+       float best = 0;
+       //////////////////////////////////////////////////////////////////////////////////////
+       // finding the maximum over all vectors of above form
+       // with wishvel having an absolute value of 1
+       //////////////////////////////////////////////////////////////////////////////////////
+       // we're finding the maximum over
+       //   f(a_side, a_up, a_add, z) := a_side * (1 - z^2) + (a_add + a_up * z)^2;
+       // for z in the range from -1 to 1
+       //////////////////////////////////////////////////////////////////////////////////////
+       // maximum is EITHER attained at the single extreme point:
+       float a_diff = a_side * a_side - a_up * a_up;
+       float f;
+       if (a_diff != 0)
+       {
+               f = a_add * a_up / a_diff; // this is the zero of diff(f(a_side, a_up, a_add, z), z)
+               if (f > -1 && f < 1) // can it be attained?
+               {
+                       best = (a_diff + a_add * a_add) * (a_diff + a_up * a_up) / a_diff;
+                       //print("middle\n");
+               }
+       }
+       // OR attained at z = 1:
+       f = (a_up + a_add) * (a_up + a_add);
+       if (f > best)
+       {
+               best = f;
+               //print("top\n");
+       }
+       // OR attained at z = -1:
+       f = (a_up - a_add) * (a_up - a_add);
+       if (f > best)
+       {
+               best = f;
+               //print("bottom\n");
+       }
+       best = sqrt(best);
+       //////////////////////////////////////////////////////////////////////////////////////
+
+       //print("best possible acceleration: ", ftos(best), "\n");
+
+       float fxy, fz;
+       fxy = bound(0, 1 - (self.velocity * normalize(wishvel_x * '1 0 0' + wishvel_y * '0 1 0')) / PHYS_JETPACK_MAXSPEED_SIDE, 1);
+       if (wishvel_z - PHYS_GRAVITY > 0)
+               fz = bound(0, 1 - self.velocity_z / PHYS_JETPACK_MAXSPEED_UP, 1);
+       else
+               fz = bound(0, 1 + self.velocity_z / PHYS_JETPACK_MAXSPEED_UP, 1);
+
+       float fvel;
+       fvel = vlen(wishvel);
+       wishvel_x *= fxy;
+       wishvel_y *= fxy;
+       wishvel_z = (wishvel_z - PHYS_GRAVITY) * fz + PHYS_GRAVITY;
+
+       fvel = min(1, vlen(wishvel) / best);
+       if (PHYS_JETPACK_FUEL && !(ITEMS_STAT(self) & IT_UNLIMITED_WEAPON_AMMO))
+               f = min(1, PHYS_AMMO_FUEL(self) / (PHYS_JETPACK_FUEL * PHYS_INPUT_TIMELENGTH * fvel));
+       else
+               f = 1;
+
+       //print("this acceleration: ", ftos(vlen(wishvel) * f), "\n");
+
+       if (f > 0 && wishvel != '0 0 0')
+       {
+               self.velocity = self.velocity + wishvel * f * PHYS_INPUT_TIMELENGTH;
+               UNSET_ONGROUND(self);
+
+#ifdef SVQC
+               if (!(ITEMS_STAT(self) & IT_UNLIMITED_WEAPON_AMMO))
+                       self.ammo_fuel -= PHYS_JETPACK_FUEL * PHYS_INPUT_TIMELENGTH * fvel * f;
+
+               ITEMS_STAT(self) |= IT_USING_JETPACK;
+
+               // jetpack also inhibits health regeneration, but only for 1 second
+               self.pauseregen_finished = max(self.pauseregen_finished, time + autocvar_g_balance_pause_fuel_regen);
+#endif
+       }
+
+#ifdef CSQC
+       float g = PHYS_GRAVITY * PHYS_ENTGRAVITY(self) * PHYS_INPUT_TIMELENGTH;
+       if (GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE)
+               self.velocity_z -= g * 0.5;
+       else
+               self.velocity_z -= g;
+       PM_ClientMovement_Move();
+       if (!IS_ONGROUND(self) || !(GAMEPLAYFIX_NOGRAVITYONGROUND))
+               if (GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE)
+                       self.velocity_z -= g * 0.5;
+#endif
+}
+
+void PM_walk(float buttons_prev, float maxspd_mod)
+{
+       if (!WAS_ONGROUND(self))
+       {
+#ifdef SVQC
+               if (autocvar_speedmeter)
+                       dprint(strcat("landing velocity: ", vtos(self.velocity), " (abs: ", ftos(vlen(self.velocity)), ")\n"));
+#endif
+               if (self.lastground < time - 0.3)
+                       self.velocity *= (1 - PHYS_FRICTION_ONLAND);
+#ifdef SVQC
+               if (self.jumppadcount > 1)
+                       dprint(strcat(ftos(self.jumppadcount), "x jumppad combo\n"));
+               self.jumppadcount = 0;
+#endif
+       }
+
+       // walking
+       makevectors(self.v_angle.y * '0 1 0');
+       vector wishvel = v_forward * self.movement.x
+                                       + v_right * self.movement.y;
+       // acceleration
+       vector wishdir = normalize(wishvel);
+       float wishspeed = vlen(wishvel);
+
+       wishspeed = min(wishspeed, PHYS_MAXSPEED(self) * maxspd_mod);
+       if (IS_DUCKED(self))
+               wishspeed *= 0.5;
+
+       // apply edge friction
+       float f = vlen(vec2(self.velocity));
+       if (f > 0)
+       {
+               float realfriction;
+               trace_dphitq3surfaceflags = 0;
+               tracebox(self.origin, self.mins, self.maxs, self.origin - '0 0 1', MOVE_NOMONSTERS, self);
+               // TODO: apply edge friction
+               // apply ground friction
+               if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_SLICK)
+                       realfriction = PHYS_FRICTION_SLICK;
+               else
+                       realfriction = PHYS_FRICTION;
+
+               f = 1 - PHYS_INPUT_TIMELENGTH * realfriction * ((f < PHYS_STOPSPEED) ? (PHYS_STOPSPEED / f) : 1);
+               f = max(0, f);
+               self.velocity *= f;
+               /*
+                  Mathematical analysis time!
+
+                  Our goal is to invert this mess.
+
+                  For the two cases we get:
+                       v = v0 * (1 - PHYS_INPUT_TIMELENGTH * (PHYS_STOPSPEED / v0) * PHYS_FRICTION)
+                         = v0 - PHYS_INPUT_TIMELENGTH * PHYS_STOPSPEED * PHYS_FRICTION
+                       v0 = v + PHYS_INPUT_TIMELENGTH * PHYS_STOPSPEED * PHYS_FRICTION
+                  and
+                       v = v0 * (1 - PHYS_INPUT_TIMELENGTH * PHYS_FRICTION)
+                       v0 = v / (1 - PHYS_INPUT_TIMELENGTH * PHYS_FRICTION)
+
+                  These cases would be chosen ONLY if:
+                       v0 < PHYS_STOPSPEED
+                       v + PHYS_INPUT_TIMELENGTH * PHYS_STOPSPEED * PHYS_FRICTION < PHYS_STOPSPEED
+                       v < PHYS_STOPSPEED * (1 - PHYS_INPUT_TIMELENGTH * PHYS_FRICTION)
+                  and, respectively:
+                       v0 >= PHYS_STOPSPEED
+                       v / (1 - PHYS_INPUT_TIMELENGTH * PHYS_FRICTION) >= PHYS_STOPSPEED
+                       v >= PHYS_STOPSPEED * (1 - PHYS_INPUT_TIMELENGTH * PHYS_FRICTION)
+                */
+       }
+       float addspeed = wishspeed - self.velocity * wishdir;
+       if (addspeed > 0)
+       {
+               float accelspeed = min(PHYS_ACCELERATE * PHYS_INPUT_TIMELENGTH * wishspeed, addspeed);
+               self.velocity += accelspeed * wishdir;
+       }
+       float g = PHYS_GRAVITY * PHYS_ENTGRAVITY(self) * PHYS_INPUT_TIMELENGTH;
+       if (!(GAMEPLAYFIX_NOGRAVITYONGROUND))
+               self.velocity_z -= g * (GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE ? 0.5 : 1);
+       if (self.velocity * self.velocity)
+               PM_ClientMovement_Move();
+       if (GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE)
+               if (!IS_ONGROUND(self) || !GAMEPLAYFIX_NOGRAVITYONGROUND)
+                       self.velocity_z -= g * 0.5;
+}
+
+void PM_air(float buttons_prev, float maxspd_mod)
+{
+       makevectors(self.v_angle.y * '0 1 0');
+       vector wishvel = v_forward * self.movement.x
+                                       + v_right * self.movement.y;
+       // acceleration
+       vector wishdir = normalize(wishvel);
+       float wishspeed = vlen(wishvel);
+
+#ifdef SVQC
+       if (time >= self.teleport_time)
+#else
+       if (pmove_waterjumptime <= 0)
+#endif
+       {
+               float maxairspd = PHYS_MAXAIRSPEED(self) * min(maxspd_mod, 1);
+
+               // apply air speed limit
+               float airaccelqw = PHYS_AIRACCEL_QW(self);
+               float wishspeed0 = wishspeed;
+               wishspeed = min(wishspeed, maxairspd);
+               if (IS_DUCKED(self))
+                       wishspeed *= 0.5;
+               float airaccel = PHYS_AIRACCELERATE * min(maxspd_mod, 1);
+
+               float accelerating = (self.velocity * wishdir > 0);
+               float wishspeed2 = wishspeed;
+
+               // CPM: air control
+               if (PHYS_AIRSTOPACCELERATE)
+               {
+                       vector curdir = normalize(vec2(self.velocity));
+                       airaccel += (PHYS_AIRSTOPACCELERATE*maxspd_mod - airaccel) * max(0, -(curdir * wishdir));
+               }
+               // note that for straight forward jumping:
+               // step = accel * PHYS_INPUT_TIMELENGTH * wishspeed0;
+               // accel  = bound(0, wishspeed - vel_xy_current, step) * accelqw + step * (1 - accelqw);
+               // -->
+               // dv/dt = accel * maxspeed (when slow)
+               // dv/dt = accel * maxspeed * (1 - accelqw) (when fast)
+               // log dv/dt = logaccel + logmaxspeed (when slow)
+               // log dv/dt = logaccel + logmaxspeed + log(1 - accelqw) (when fast)
+               float strafity = IsMoveInDirection(self.movement, -90) + IsMoveInDirection(self.movement, +90); // if one is nonzero, other is always zero
+               if (PHYS_MAXAIRSTRAFESPEED)
+                       wishspeed = min(wishspeed, GeomLerp(PHYS_MAXAIRSPEED(self)*maxspd_mod, strafity, PHYS_MAXAIRSTRAFESPEED*maxspd_mod));
+               if (PHYS_AIRSTRAFEACCELERATE(self))
+                       airaccel = GeomLerp(airaccel, strafity, PHYS_AIRSTRAFEACCELERATE(self)*maxspd_mod);
+               if (PHYS_AIRSTRAFEACCEL_QW(self))
+                       airaccelqw =
+               (((strafity > 0.5 ? PHYS_AIRSTRAFEACCEL_QW(self) : PHYS_AIRACCEL_QW(self)) >= 0) ? +1 : -1)
+               *
+               (1 - GeomLerp(1 - fabs(PHYS_AIRACCEL_QW(self)), strafity, 1 - fabs(PHYS_AIRSTRAFEACCEL_QW(self))));
+               // !CPM
+
+               if (PHYS_WARSOWBUNNY_TURNACCEL && accelerating && self.movement.y == 0 && self.movement.x != 0)
+                       PM_AirAccelerate(wishdir, wishspeed2);
+               else
+                       PM_Accelerate(wishdir, wishspeed, wishspeed0, airaccel, airaccelqw, PHYS_AIRACCEL_QW_STRETCHFACTOR(self), PHYS_AIRACCEL_SIDEWAYS_FRICTION / maxairspd, PHYS_AIRSPEEDLIMIT_NONQW(self));
+
+               if (PHYS_AIRCONTROL)
+                       CPM_PM_Aircontrol(wishdir, wishspeed2);
+       }
+       float g = PHYS_GRAVITY * PHYS_ENTGRAVITY(self) * PHYS_INPUT_TIMELENGTH;
+       if (GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE)
+               self.velocity_z -= g * 0.5;
+       else
+               self.velocity_z -= g;
+       PM_ClientMovement_Move();
+       if (!IS_ONGROUND(self) || !(GAMEPLAYFIX_NOGRAVITYONGROUND))
+               if (GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE)
+                       self.velocity_z -= g * 0.5;
+}
+
+// used for calculating airshots
+bool IsFlying(entity a)
+{
+       if(IS_ONGROUND(a))
+               return false;
+       if(a.waterlevel >= WATERLEVEL_SWIMMING)
+               return false;
+       traceline(a.origin, a.origin - '0 0 48', MOVE_NORMAL, a);
+       if(trace_fraction < 1)
+               return false;
+       return true;
+}
+
+void PM_Main()
+{
+       int buttons = PHYS_INPUT_BUTTON_MASK(self);
+#ifdef CSQC
+       self.items = getstati(STAT_ITEMS, 0, 24);
+
+       self.movement = PHYS_INPUT_MOVEVALUES(self);
+
+       vector oldv_angle = self.v_angle;
+       vector oldangles = self.angles; // we need to save these, as they're abused by other code
+       self.v_angle = PHYS_INPUT_ANGLES(self);
+       self.angles = PHYS_WORLD_ANGLES(self);
+
+       self.team = myteam + 1; // is this correct?
+       if (!(PHYS_INPUT_BUTTON_JUMP(self))) // !jump
+               UNSET_JUMP_HELD(self); // canjump = true
+       pmove_waterjumptime -= PHYS_INPUT_TIMELENGTH;
+
+       PM_ClientMovement_UpdateStatus(true);
+#endif
+       
+
+#ifdef SVQC
+       WarpZone_PlayerPhysics_FixVAngle();
+#endif
+       float maxspeed_mod = 1;
+       maxspeed_mod *= PM_check_keepaway();
+       maxspeed_mod *= PHYS_HIGHSPEED;
+
+#ifdef SVQC
+       Physics_UpdateStats(maxspeed_mod);
+
+       if (self.PlayerPhysplug)
+               if (self.PlayerPhysplug())
+                       return;
+#endif
+
+       PM_check_race_movetime();
+#ifdef SVQC
+       anticheat_physics();
+#endif
+
+       if (PM_check_specialcommand(buttons))
+               return;
+#ifdef SVQC
+       if (sv_maxidle > 0)
+       {
+               if (buttons != self.buttons_old || self.movement != self.movement_old || self.v_angle != self.v_angle_old)
+                       self.parm_idlesince = time;
+       }
+#endif
+       int buttons_prev = self.buttons_old;
+       self.buttons_old = buttons;
+       self.movement_old = self.movement;
+       self.v_angle_old = self.v_angle;
+
+       PM_check_nickspam();
+
+       PM_check_punch();
+#ifdef SVQC
+       if (IS_BOT_CLIENT(self))
+       {
+               if (playerdemo_read())
+                       return;
+               bot_think();
+       }
+
+       if (IS_PLAYER(self))
+#endif
+       {
+#ifdef SVQC
+               if (self.race_penalty)
+                       if (time > self.race_penalty)
+                               self.race_penalty = 0;
+#endif
+
+               bool not_allowed_to_move = false;
+#ifdef SVQC
+               if (self.race_penalty)
+                       not_allowed_to_move = true;
+#endif
+#ifdef SVQC
+               if (time < game_starttime)
+                       not_allowed_to_move = true;
+#endif
+
+               if (not_allowed_to_move)
+               {
+                       self.velocity = '0 0 0';
+                       self.movetype = MOVETYPE_NONE;
+#ifdef SVQC
+                       self.disableclientprediction = 2;
+#endif
+               }
+#ifdef SVQC
+               else if (self.disableclientprediction == 2)
+               {
+                       if (self.movetype == MOVETYPE_NONE)
+                               self.movetype = MOVETYPE_WALK;
+                       self.disableclientprediction = 0;
+               }
+#endif
+       }
+
+#ifdef SVQC
+       if (self.movetype == MOVETYPE_NONE)
+               return;
+
+       // when we get here, disableclientprediction cannot be 2
+       self.disableclientprediction = 0;
+#endif
+
+       PM_check_spider();
+
+       PM_check_frozen();
+
+       PM_check_blocked();
+
+       maxspeed_mod = 1;
+
+       if (self.in_swamp)
+               maxspeed_mod *= self.swamp_slowdown; //cvar("g_balance_swamp_moverate");
+
+       // conveyors: first fix velocity
+       if (self.conveyor.state)
+               self.velocity -= self.conveyor.movedir;
+
+#ifdef SVQC
+       MUTATOR_CALLHOOK(PlayerPhysics);
+#endif
+#ifdef CSQC
+       PM_multijump();
+#endif
+
+//     float forcedodge = 1;
+//     if(forcedodge) {
+//#ifdef CSQC
+//             PM_dodging_checkpressedkeys();
+//#endif
+//             PM_dodging();
+//             PM_ClientMovement_Move();
+//             return;
+//     }
+
+#ifdef SVQC
+       if (!IS_PLAYER(self))
+       {
+               maxspeed_mod = autocvar_sv_spectator_speed_multiplier;
+               if (!self.spectatorspeed)
+                       self.spectatorspeed = maxspeed_mod;
+               if (self.impulse && self.impulse <= 19 || (self.impulse >= 200 && self.impulse <= 209) || (self.impulse >= 220 && self.impulse <= 229))
+               {
+                       if (self.lastclassname != "player")
+                       {
+                               if (self.impulse == 10 || self.impulse == 15 || self.impulse == 18 || (self.impulse >= 200 && self.impulse <= 209))
+                                       self.spectatorspeed = bound(1, self.spectatorspeed + 0.5, 5);
+                               else if (self.impulse == 11)
+                                       self.spectatorspeed = maxspeed_mod;
+                               else if (self.impulse == 12 || self.impulse == 16  || self.impulse == 19 || (self.impulse >= 220 && self.impulse <= 229))
+                                       self.spectatorspeed = bound(1, self.spectatorspeed - 0.5, 5);
+                               else if (self.impulse >= 1 && self.impulse <= 9)
+                                       self.spectatorspeed = 1 + 0.5 * (self.impulse - 1);
+                       } // otherwise just clear
+                       self.impulse = 0;
+               }
+               maxspeed_mod = self.spectatorspeed;
+       }
+
+       float spd = max(PHYS_MAXSPEED(self), PHYS_MAXAIRSPEED(self)) * maxspeed_mod;
+       if(self.speed != spd)
+       {
+               self.speed = spd;
+               string temps = ftos(spd);
+               stuffcmd(self, strcat("cl_forwardspeed ", temps, "\n"));
+               stuffcmd(self, strcat("cl_backspeed ", temps, "\n"));
+               stuffcmd(self, strcat("cl_sidespeed ", temps, "\n"));
+               stuffcmd(self, strcat("cl_upspeed ", temps, "\n"));
+       }
+#endif
+
+       if(PHYS_DEAD(self))
+       {
+               // handle water here
+               vector midpoint = ((self.absmin + self.absmax) * 0.5);
+               if(pointcontents(midpoint) == CONTENT_WATER)
+               {
+                       self.velocity = self.velocity * 0.5;
+
+                       // do we want this?
+                       //if(pointcontents(midpoint + '0 0 2') == CONTENT_WATER)
+                               //{ self.velocity_z = 70; }
+               }
+               goto end;
+       }
+
+#ifdef SVQC
+       if (!self.fixangle && !g_bugrigs)
+               self.angles = '0 1 0' * self.v_angle.y;
+#endif
+
+       PM_check_hitground();
+
+       if(IsFlying(self))
+               self.wasFlying = 1;
+
+       if (IS_PLAYER(self))
+               CheckPlayerJump();
+
+       if (self.flags & FL_WATERJUMP)
+       {
+               self.velocity_x = self.movedir_x;
+               self.velocity_y = self.movedir_y;
+               if (time > self.teleport_time || self.waterlevel == WATERLEVEL_NONE)
+               {
+                       self.flags &= ~FL_WATERJUMP;
+                       self.teleport_time = 0;
+               }
+       }
+
+#ifdef SVQC
+       else if (g_bugrigs && IS_PLAYER(self))
+               RaceCarPhysics();
+#endif
+
+       else if (self.movetype == MOVETYPE_NOCLIP || self.movetype == MOVETYPE_FLY || self.movetype == MOVETYPE_FLY_WORLDONLY || (BUFFS(self) & BUFF_FLIGHT))
+               PM_fly(maxspeed_mod);
+
+       else if (self.waterlevel >= WATERLEVEL_SWIMMING)
+               PM_swim(maxspeed_mod);
+
+       else if (time < self.ladder_time)
+               PM_ladder(maxspeed_mod);
+
+       else if (ITEMS_STAT(self) & IT_USING_JETPACK)
+               PM_jetpack(maxspeed_mod);
+
+       else if (IS_ONGROUND(self))
+               PM_walk(buttons_prev, maxspeed_mod);
+
+       else
+               PM_air(buttons_prev, maxspeed_mod);
+
+#ifdef SVQC
+       if (!IS_OBSERVER(self))
+               PM_check_race();
+#endif
+       PM_check_vortex();
+
+:end
+       if (IS_ONGROUND(self))
+               self.lastground = time;
+
+       // conveyors: then break velocity again
+       if(self.conveyor.state)
+               self.velocity += self.conveyor.movedir;
+
+       self.lastflags = self.flags;
+
+       self.lastclassname = self.classname;
+
+#ifdef CSQC
+       self.v_angle = oldv_angle;
+       self.angles = oldangles;
+#endif
+}
+
+#ifdef SVQC
+void SV_PlayerPhysics(void)
+#elif defined(CSQC)
+void CSQC_ClientMovement_PlayerMove_Frame(void)
+#endif
+{
+       PM_Main();
+
+#ifdef CSQC
+       self.pmove_flags = 
+                       ((self.flags & FL_DUCKED) ? PMF_DUCKED : 0) |
+                       (!(self.flags & FL_JUMPRELEASED) ? 0 : PMF_JUMP_HELD) |
+                       ((self.flags & FL_ONGROUND) ? PMF_ONGROUND : 0);
+#endif
+}
diff --git a/qcsrc/common/physics.qh b/qcsrc/common/physics.qh
new file mode 100644 (file)
index 0000000..17de7b2
--- /dev/null
@@ -0,0 +1,372 @@
+#ifndef COMMON_PHYSICS_H
+#define COMMON_PHYSICS_H
+
+// Client/server mappings
+
+.entity conveyor;
+
+.float race_penalty;
+
+.float gravity;
+.float swamp_slowdown;
+.float lastflags;
+.float lastground;
+.float wasFlying;
+.float spectatorspeed;
+
+.vector movement_old;
+.float buttons_old;
+.vector v_angle_old;
+.string lastclassname;
+
+.float() PlayerPhysplug;
+float AdjustAirAccelQW(float accelqw, float factor);
+
+bool IsFlying(entity a);
+
+#ifdef CSQC
+
+       const int FL_WATERJUMP = 2048;  // player jumping out of water
+       const int FL_JUMPRELEASED = 4096;       // for jump debouncing
+
+       float PM_multijump_checkjump();
+       void PM_multijump();
+
+       .float watertype;
+       .int items;
+
+       .vector movement;
+       .vector v_angle;
+
+// TODO
+       #define IS_CLIENT(s)                                            (s).isplayermodel
+       #define IS_PLAYER(s)                                            (s).isplayermodel
+       #define isPushable(s)                                           (s).isplayermodel
+
+       float player_multijump;
+       float player_jumpheight;
+
+       #define PHYS_INPUT_ANGLES(s)                            input_angles
+// TODO
+       #define PHYS_WORLD_ANGLES(s)                            input_angles
+
+       #define PHYS_INPUT_TIMELENGTH                           input_timelength
+       #define PHYS_INPUT_FRAMETIME                            serverdeltatime
+
+       #define PHYS_INPUT_MOVEVALUES(s)                        input_movevalues
+
+       #define PHYS_INPUT_BUTTON_MASK(s)               (input_buttons | 128 * (input_movevalues_x < 0) | 256 * (input_movevalues_x > 0) | 512 * (input_movevalues_y < 0) | 1024 * (input_movevalues_y > 0))
+       #define PHYS_INPUT_BUTTON_ATCK(s)                       !!(input_buttons & 1)
+       #define PHYS_INPUT_BUTTON_JUMP(s)                       !!(input_buttons & 2)
+       #define PHYS_INPUT_BUTTON_ATCK2(s)                      !!(input_buttons & 4)
+       #define PHYS_INPUT_BUTTON_ZOOM(s)                       !!(input_buttons & 8)
+       #define PHYS_INPUT_BUTTON_CROUCH(s)                     !!(input_buttons & 16)
+       #define PHYS_INPUT_BUTTON_HOOK(s)                       !!(input_buttons & 32)
+       #define PHYS_INPUT_BUTTON_USE(s)                        !!(input_buttons & 64)
+       #define PHYS_INPUT_BUTTON_BACKWARD(s)           !!(input_buttons & 128)
+       #define PHYS_INPUT_BUTTON_FORWARD(s)            !!(input_buttons & 256)
+       #define PHYS_INPUT_BUTTON_LEFT(s)                       !!(input_buttons & 512)
+       #define PHYS_INPUT_BUTTON_RIGHT(s)                      !!(input_buttons & 1024)
+       #define PHYS_INPUT_BUTTON_JETPACK(s)            !!(input_buttons & 4096)
+
+       #define PHYS_DEAD(s)                                            s.csqcmodel_isdead
+
+       #define GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE  !!(moveflags & MOVEFLAG_GRAVITYUNAFFECTEDBYTICRATE)
+       #define GAMEPLAYFIX_NOGRAVITYONGROUND                   cvar("sv_gameplayfix_nogravityonground")
+       #define GAMEPLAYFIX_Q2AIRACCELERATE                             cvar("sv_gameplayfix_q2airaccelerate")
+       #define GAMEPLAYFIX_EASIERWATERJUMP                     getstati(STAT_GAMEPLAYFIX_EASIERWATERJUMP)
+       #define GAMEPLAYFIX_DOWNTRACEONGROUND                   getstati(STAT_GAMEPLAYFIX_DOWNTRACEONGROUND)
+       #define GAMEPLAYFIX_STEPMULTIPLETIMES                   getstati(STAT_GAMEPLAYFIX_STEPMULTIPLETIMES)
+       #define GAMEPLAYFIX_UNSTICKPLAYERS                              getstati(STAT_GAMEPLAYFIX_UNSTICKPLAYERS)
+       #define GAMEPLAYFIX_STEPDOWN                                    getstati(STAT_GAMEPLAYFIX_STEPDOWN)
+
+       #define IS_DUCKED(s)                                            !!(s.flags & FL_DUCKED)
+       #define SET_DUCKED(s)                                           s.flags |= FL_DUCKED
+       #define UNSET_DUCKED(s)                                         s.flags &= ~FL_DUCKED
+
+       #define IS_JUMP_HELD(s)                                         !(s.flags & FL_JUMPRELEASED)
+       #define SET_JUMP_HELD(s)                                        s.flags &= ~FL_JUMPRELEASED
+       #define UNSET_JUMP_HELD(s)                                      s.flags |= FL_JUMPRELEASED
+
+       #define IS_ONGROUND(s)                                          !!(s.flags & FL_ONGROUND)
+       #define SET_ONGROUND(s)                                         s.flags |= FL_ONGROUND
+       #define UNSET_ONGROUND(s)                                       s.flags &= ~FL_ONGROUND
+
+       #define WAS_ONGROUND(s)                                         !!(s.lastflags & FL_ONGROUND)
+
+       #define ITEMS_STAT(s)                                           (s).items
+       #define BUFFS(s)                                                        getstati(STAT_BUFFS)
+
+       #define PHYS_AMMO_FUEL(s)                                       getstati(STAT_FUEL)
+
+       #define PHYS_FROZEN(s)                                          getstati(STAT_FROZEN)
+
+       #define PHYS_DOUBLEJUMP                                         getstati(STAT_DOUBLEJUMP)
+
+       #define PHYS_BUGRIGS                                            getstati(STAT_BUGRIGS)
+       #define PHYS_BUGRIGS_ANGLE_SMOOTHING            getstati(STAT_BUGRIGS_ANGLE_SMOOTHING)
+       #define PHYS_BUGRIGS_PLANAR_MOVEMENT            getstati(STAT_BUGRIGS_PLANAR_MOVEMENT)
+       #define PHYS_BUGRIGS_REVERSE_SPEEDING           getstati(STAT_BUGRIGS_REVERSE_SPEEDING)
+       #define PHYS_BUGRIGS_FRICTION_FLOOR             getstatf(STAT_BUGRIGS_FRICTION_FLOOR)
+       #define PHYS_BUGRIGS_AIR_STEERING                       getstati(STAT_BUGRIGS_AIR_STEERING)
+       #define PHYS_BUGRIGS_FRICTION_BRAKE             getstatf(STAT_BUGRIGS_FRICTION_BRAKE)
+       #define PHYS_BUGRIGS_ACCEL                                      getstatf(STAT_BUGRIGS_ACCEL)
+       #define PHYS_BUGRIGS_SPEED_REF                          getstatf(STAT_BUGRIGS_SPEED_REF)
+       #define PHYS_BUGRIGS_SPEED_POW                          getstatf(STAT_BUGRIGS_SPEED_POW)
+       #define PHYS_BUGRIGS_STEER                                      getstatf(STAT_BUGRIGS_STEER)
+       #define PHYS_BUGRIGS_FRICTION_AIR                       getstatf(STAT_BUGRIGS_FRICTION_AIR)
+       #define PHYS_BUGRIGS_CAR_JUMPING                        getstatf(STAT_BUGRIGS_CAR_JUMPING)
+       #define PHYS_BUGRIGS_REVERSE_SPINNING           getstatf(STAT_BUGRIGS_REVERSE_SPINNING)
+       #define PHYS_BUGRIGS_REVERSE_STOPPING           getstatf(STAT_BUGRIGS_REVERSE_STOPPING)
+
+       #define PHYS_JUMPSPEEDCAP_MIN                           getstatf(STAT_MOVEVARS_JUMPSPEEDCAP_MIN)
+       #define PHYS_JUMPSPEEDCAP_MAX                           getstatf(STAT_MOVEVARS_JUMPSPEEDCAP_MAX)
+       #define PHYS_JUMPSPEEDCAP_DISABLE_ONRAMPS       getstati(STAT_MOVEVARS_JUMPSPEEDCAP_DISABLE_ONRAMPS)
+
+       #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)
+       #define PHYS_AIRACCEL_QW_STRETCHFACTOR(s)       getstatf(STAT_MOVEVARS_AIRACCEL_QW_STRETCHFACTOR)
+       #define PHYS_AIRACCEL_SIDEWAYS_FRICTION         getstatf(STAT_MOVEVARS_AIRACCEL_SIDEWAYS_FRICTION)
+       #define PHYS_AIRACCELERATE                                      getstatf(STAT_MOVEVARS_AIRACCELERATE)
+       #define PHYS_AIRCONTROL                                         getstatf(STAT_MOVEVARS_AIRCONTROL)
+       #define PHYS_AIRCONTROL_PENALTY                         getstatf(STAT_MOVEVARS_AIRCONTROL_PENALTY)
+       #define PHYS_AIRCONTROL_POWER                           getstatf(STAT_MOVEVARS_AIRCONTROL_POWER)
+       #define PHYS_AIRSPEEDLIMIT_NONQW(s)                     getstatf(STAT_MOVEVARS_AIRSPEEDLIMIT_NONQW)
+       #define PHYS_AIRSTOPACCELERATE                          getstatf(STAT_MOVEVARS_AIRSTOPACCELERATE)
+       #define PHYS_AIRSTRAFEACCEL_QW(s)                       getstatf(STAT_MOVEVARS_AIRSTRAFEACCEL_QW)
+       #define PHYS_AIRSTRAFEACCELERATE(s)                     getstatf(STAT_MOVEVARS_AIRSTRAFEACCELERATE)
+       #define PHYS_ENTGRAVITY(s)                                      getstatf(STAT_MOVEVARS_ENTGRAVITY)
+       #define PHYS_FRICTION                                           getstatf(STAT_MOVEVARS_FRICTION)
+       #define PHYS_FRICTION_SLICK                                     getstatf(STAT_MOVEVARS_FRICTION_SLICK)
+       #define PHYS_FRICTION_ONLAND                            getstatf(STAT_MOVEVARS_FRICTION_ONLAND)
+       #define PHYS_GRAVITY                                            getstatf(STAT_MOVEVARS_GRAVITY)
+       #define PHYS_HIGHSPEED                                          getstatf(STAT_MOVEVARS_HIGHSPEED)
+       #define PHYS_JUMPVELOCITY                                       getstatf(STAT_MOVEVARS_JUMPVELOCITY)
+       #define PHYS_MAXAIRSPEED(s)                                     getstatf(STAT_MOVEVARS_MAXAIRSPEED)
+       #define PHYS_MAXAIRSTRAFESPEED                          getstatf(STAT_MOVEVARS_MAXAIRSTRAFESPEED)
+       #define PHYS_MAXSPEED(s)                                        getstatf(STAT_MOVEVARS_MAXSPEED)
+       #define PHYS_STEPHEIGHT                                         getstatf(STAT_MOVEVARS_STEPHEIGHT)
+       #define PHYS_STOPSPEED                                          getstatf(STAT_MOVEVARS_STOPSPEED)
+       #define PHYS_WARSOWBUNNY_ACCEL                          getstatf(STAT_MOVEVARS_WARSOWBUNNY_ACCEL)
+       #define PHYS_WARSOWBUNNY_BACKTOSIDERATIO        getstatf(STAT_MOVEVARS_WARSOWBUNNY_BACKTOSIDERATIO)
+       #define PHYS_WARSOWBUNNY_AIRFORWARDACCEL        getstatf(STAT_MOVEVARS_WARSOWBUNNY_AIRFORWARDACCEL)
+       #define PHYS_WARSOWBUNNY_TOPSPEED                       getstatf(STAT_MOVEVARS_WARSOWBUNNY_TOPSPEED)
+       #define PHYS_WARSOWBUNNY_TURNACCEL                      getstatf(STAT_MOVEVARS_WARSOWBUNNY_TURNACCEL)
+
+       #define PHYS_WALLFRICTION                                       getstati(STAT_MOVEVARS_WALLFRICTION)
+
+       #define PHYS_JETPACK_ACCEL_UP                           getstatf(STAT_JETPACK_ACCEL_UP)
+       #define PHYS_JETPACK_ACCEL_SIDE                         getstatf(STAT_JETPACK_ACCEL_SIDE)
+       #define PHYS_JETPACK_ANTIGRAVITY                        getstatf(STAT_JETPACK_ANTIGRAVITY)
+       #define PHYS_JETPACK_FUEL                                       getstatf(STAT_JETPACK_FUEL)
+       #define PHYS_JETPACK_MAXSPEED_UP                        getstatf(STAT_JETPACK_MAXSPEED_UP)
+       #define PHYS_JETPACK_MAXSPEED_SIDE                      getstatf(STAT_JETPACK_MAXSPEED_SIDE)
+
+       #define PHYS_DODGING_FROZEN                                     getstati(STAT_DODGING_FROZEN)
+
+       #define PHYS_NOSTEP                                                     getstati(STAT_NOSTEP)
+       #define PHYS_JUMPSTEP                                           getstati(STAT_MOVEVARS_JUMPSTEP)
+
+#elif defined(SVQC)
+
+       bool Physics_Valid(string thecvar);
+
+       .vector stat_pl_view_ofs;
+       .vector stat_pl_crouch_view_ofs;
+
+       .vector stat_pl_min;
+       .vector stat_pl_max;
+       .vector stat_pl_crouch_min;
+       .vector stat_pl_crouch_max;
+
+       .float stat_sv_airaccel_qw;
+       .float stat_sv_airstrafeaccel_qw;
+       .float stat_sv_airspeedlimit_nonqw;
+       .float stat_sv_maxspeed;
+       .float stat_movement_highspeed;
+
+       .float stat_sv_friction_on_land;
+       .float stat_sv_friction_slick;
+
+       .float stat_doublejump;
+
+       .float stat_jumpspeedcap_min;
+       .float stat_jumpspeedcap_max;
+       .float stat_jumpspeedcap_disable_onramps;
+
+       .float stat_jetpack_accel_side;
+       .float stat_jetpack_accel_up;
+       .float stat_jetpack_antigravity;
+       .float stat_jetpack_fuel;
+       .float stat_jetpack_maxspeed_up;
+       .float stat_jetpack_maxspeed_side;
+       .float stat_gameplayfix_easierwaterjump;
+       .float stat_gameplayfix_downtracesupportsongroundflag;
+       .float stat_gameplayfix_stepmultipletimes;
+       .float stat_gameplayfix_unstickplayers;
+       .float stat_gameplayfix_stepdown;
+
+       .float stat_bugrigs;
+       .float stat_bugrigs_angle_smoothing;
+       .float stat_bugrigs_planar_movement;
+       .float stat_bugrigs_reverse_speeding;
+       .float stat_bugrigs_friction_floor;
+       .float stat_bugrigs_air_steering;
+       .float stat_bugrigs_friction_brake;
+       .float stat_bugrigs_accel;
+       .float stat_bugrigs_speed_ref;
+       .float stat_bugrigs_speed_pow;
+       .float stat_bugrigs_steer;
+       .float stat_bugrigs_friction_air;
+       .float stat_bugrigs_car_jumping;
+       .float stat_bugrigs_reverse_spinning;
+       .float stat_bugrigs_reverse_stopping;
+
+       // new properties
+       .float stat_sv_jumpvelocity;
+       .float stat_sv_airaccel_qw_stretchfactor;
+       .float stat_sv_maxairstrafespeed;
+       .float stat_sv_maxairspeed;
+       .float stat_sv_airstrafeaccelerate;
+       .float stat_sv_warsowbunny_turnaccel;
+       .float stat_sv_airaccel_sideways_friction;
+       .float stat_sv_aircontrol;
+       .float stat_sv_aircontrol_power;
+       .float stat_sv_aircontrol_penalty;
+       .float stat_sv_warsowbunny_airforwardaccel;
+       .float stat_sv_warsowbunny_topspeed;
+       .float stat_sv_warsowbunny_accel;
+       .float stat_sv_warsowbunny_backtosideratio;
+       .float stat_sv_friction;
+       .float stat_sv_accelerate;
+       .float stat_sv_stopspeed;
+       .float stat_sv_airaccelerate;
+       .float stat_sv_airstopaccelerate;
+
+       .float stat_nostep;
+       .float stat_jumpstep;
+
+       #define PHYS_INPUT_ANGLES(s)                            s.v_angle
+       #define PHYS_WORLD_ANGLES(s)                            s.angles
+
+       #define PHYS_INPUT_TIMELENGTH                           frametime
+       #define PHYS_INPUT_FRAMETIME                            sys_frametime
+
+       #define PHYS_INPUT_MOVEVALUES(s)                        s.movement
+       // TODO: cache
+       #define PHYS_INPUT_BUTTON_MASK(s)               (s.BUTTON_ATCK | 2 * s.BUTTON_JUMP | 4 * s.BUTTON_ATCK2 | 8 * s.BUTTON_ZOOM | 16 * s.BUTTON_CROUCH | 32 * s.BUTTON_HOOK | 64 * s.BUTTON_USE | 128 * (s.movement_x < 0) | 256 * (s.movement_x > 0) | 512 * (s.movement_y < 0) | 1024 * (s.movement_y > 0))
+       #define PHYS_INPUT_BUTTON_ATCK(s)                       s.BUTTON_ATCK
+       #define PHYS_INPUT_BUTTON_JUMP(s)                       s.BUTTON_JUMP
+       #define PHYS_INPUT_BUTTON_ATCK2(s)                      s.BUTTON_ATCK2
+       #define PHYS_INPUT_BUTTON_ZOOM(s)                       s.BUTTON_ZOOM
+       #define PHYS_INPUT_BUTTON_CROUCH(s)                     s.BUTTON_CROUCH
+       #define PHYS_INPUT_BUTTON_HOOK(s)                       s.BUTTON_HOOK
+       #define PHYS_INPUT_BUTTON_USE(s)                        s.BUTTON_USE
+       #define PHYS_INPUT_BUTTON_BACKWARD(s)           (s.movement_x < 0)
+       #define PHYS_INPUT_BUTTON_FORWARD(s)            (s.movement_x > 0)
+       #define PHYS_INPUT_BUTTON_LEFT(s)                       (s.movement_y < 0)
+       #define PHYS_INPUT_BUTTON_RIGHT(s)                      (s.movement_y > 0)
+       #define PHYS_INPUT_BUTTON_JETPACK(s)            s.BUTTON_JETPACK
+
+       #define PHYS_DEAD(s)                                            s.deadflag != DEAD_NO
+
+       #define GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE  autocvar_sv_gameplayfix_gravityunaffectedbyticrate
+       #define GAMEPLAYFIX_NOGRAVITYONGROUND                   cvar("sv_gameplayfix_nogravityonground")
+       #define GAMEPLAYFIX_Q2AIRACCELERATE                             autocvar_sv_gameplayfix_q2airaccelerate
+       #define GAMEPLAYFIX_EASIERWATERJUMP                             cvar("sv_gameplayfix_easierwaterjump")
+       #define GAMEPLAYFIX_DOWNTRACEONGROUND                   cvar("sv_gameplayfix_downtracesupportsongroundflag")
+       #define GAMEPLAYFIX_STEPMULTIPLETIMES                   cvar("sv_gameplayfix_stepmultipletimes")
+       #define GAMEPLAYFIX_UNSTICKPLAYERS                              cvar("sv_gameplayfix_unstickplayers")
+       #define GAMEPLAYFIX_STEPDOWN                                    cvar("sv_gameplayfix_stepdown")
+
+       #define IS_DUCKED(s)                                            s.crouch
+       #define SET_DUCKED(s)                                           s.crouch = true
+       #define UNSET_DUCKED(s)                                         s.crouch = false
+
+       #define IS_JUMP_HELD(s)                                         !(s.flags & FL_JUMPRELEASED)
+       #define SET_JUMP_HELD(s)                                        s.flags &= ~FL_JUMPRELEASED
+       #define UNSET_JUMP_HELD(s)                                      s.flags |= FL_JUMPRELEASED
+
+       #define IS_ONGROUND(s)                                          !!(s.flags & FL_ONGROUND)
+       #define SET_ONGROUND(s)                                         s.flags |= FL_ONGROUND
+       #define UNSET_ONGROUND(s)                                       s.flags &= ~FL_ONGROUND
+
+       #define WAS_ONGROUND(s)                                         !!((s).lastflags & FL_ONGROUND)
+
+       #define ITEMS_STAT(s)                                           s.items
+       #define BUFFS(s)                                                        (s).buffs
+
+       #define PHYS_AMMO_FUEL(s)                                       s.ammo_fuel
+
+       #define PHYS_FROZEN(s)                                          s.frozen
+
+       #define PHYS_DOUBLEJUMP                                         autocvar_sv_doublejump
+
+       #define PHYS_BUGRIGS                                            g_bugrigs
+       #define PHYS_BUGRIGS_ANGLE_SMOOTHING            g_bugrigs_angle_smoothing
+       #define PHYS_BUGRIGS_PLANAR_MOVEMENT            g_bugrigs_planar_movement
+       #define PHYS_BUGRIGS_REVERSE_SPEEDING           g_bugrigs_reverse_speeding
+       #define PHYS_BUGRIGS_FRICTION_FLOOR                     g_bugrigs_friction_floor
+       #define PHYS_BUGRIGS_AIR_STEERING                       g_bugrigs_air_steering
+       #define PHYS_BUGRIGS_FRICTION_BRAKE                     g_bugrigs_friction_brake
+       #define PHYS_BUGRIGS_ACCEL                                      g_bugrigs_accel
+       #define PHYS_BUGRIGS_SPEED_REF                          g_bugrigs_speed_ref
+       #define PHYS_BUGRIGS_SPEED_POW                          g_bugrigs_speed_pow
+       #define PHYS_BUGRIGS_STEER                                      g_bugrigs_steer
+       #define PHYS_BUGRIGS_FRICTION_AIR                       g_bugrigs_friction_air
+       #define PHYS_BUGRIGS_CAR_JUMPING                        g_bugrigs_planar_movement_car_jumping
+       #define PHYS_BUGRIGS_REVERSE_SPINNING           g_bugrigs_reverse_spinning
+       #define PHYS_BUGRIGS_REVERSE_STOPPING           g_bugrigs_reverse_stopping
+
+       #define PHYS_JUMPSPEEDCAP_MIN                           autocvar_sv_jumpspeedcap_min
+       #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_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
+       #define PHYS_AIRACCEL_SIDEWAYS_FRICTION         self.stat_sv_airaccel_sideways_friction
+       #define PHYS_AIRACCELERATE                                      self.stat_sv_airaccelerate
+       #define PHYS_AIRCONTROL                                         self.stat_sv_aircontrol
+       #define PHYS_AIRCONTROL_PENALTY                         self.stat_sv_aircontrol_penalty
+       #define PHYS_AIRCONTROL_POWER                           self.stat_sv_aircontrol_power
+       #define PHYS_AIRSPEEDLIMIT_NONQW(s)                     s.stat_sv_airspeedlimit_nonqw
+       #define PHYS_AIRSTOPACCELERATE                          self.stat_sv_airstopaccelerate
+       #define PHYS_AIRSTRAFEACCEL_QW(s)                       s.stat_sv_airstrafeaccel_qw
+       #define PHYS_AIRSTRAFEACCELERATE(s)                     s.stat_sv_airstrafeaccelerate
+       #define PHYS_ENTGRAVITY(s)                                      s.gravity
+       #define PHYS_FRICTION                                           self.stat_sv_friction
+       #define PHYS_FRICTION_SLICK                                     autocvar_sv_friction_slick
+       #define PHYS_FRICTION_ONLAND                            autocvar_sv_friction_on_land
+       #define PHYS_GRAVITY                                            autocvar_sv_gravity
+       #define PHYS_HIGHSPEED                                          autocvar_g_movement_highspeed
+       #define PHYS_JUMPVELOCITY                                       self.stat_sv_jumpvelocity
+       #define PHYS_MAXAIRSPEED(s)                                     self.stat_sv_maxairspeed
+       #define PHYS_MAXAIRSTRAFESPEED                          self.stat_sv_maxairstrafespeed
+       #define PHYS_MAXSPEED(s)                                        s.stat_sv_maxspeed
+       #define PHYS_STEPHEIGHT                                         autocvar_sv_stepheight
+       #define PHYS_STOPSPEED                                          self.stat_sv_stopspeed
+       #define PHYS_WARSOWBUNNY_ACCEL                          self.stat_sv_warsowbunny_accel
+       #define PHYS_WARSOWBUNNY_BACKTOSIDERATIO        self.stat_sv_warsowbunny_backtosideratio
+       #define PHYS_WARSOWBUNNY_AIRFORWARDACCEL        self.stat_sv_warsowbunny_airforwardaccel
+       #define PHYS_WARSOWBUNNY_TOPSPEED                       self.stat_sv_warsowbunny_topspeed
+       #define PHYS_WARSOWBUNNY_TURNACCEL                      self.stat_sv_warsowbunny_turnaccel
+
+       #define PHYS_WALLFRICTION                                       cvar("sv_wallfriction")
+
+       #define PHYS_JETPACK_ACCEL_UP                           autocvar_g_jetpack_acceleration_up
+       #define PHYS_JETPACK_ACCEL_SIDE                         autocvar_g_jetpack_acceleration_side
+       #define PHYS_JETPACK_ANTIGRAVITY                        autocvar_g_jetpack_antigravity
+       #define PHYS_JETPACK_FUEL                                       autocvar_g_jetpack_fuel
+       #define PHYS_JETPACK_MAXSPEED_UP                        autocvar_g_jetpack_maxspeed_up
+       #define PHYS_JETPACK_MAXSPEED_SIDE                      autocvar_g_jetpack_maxspeed_side
+
+       #define PHYS_DODGING_FROZEN                                     autocvar_sv_dodging_frozen
+
+       #define PHYS_NOSTEP                                                     cvar("sv_nostep")
+       #define PHYS_JUMPSTEP                                           cvar("sv_jumpstep")
+
+#endif
+#endif
index 5890fb89e17085271e6061684e3792a6bcc0a735..e46e12fa1eeb6ac7053fda8b6365599e2f18bebd 100644 (file)
@@ -6,7 +6,7 @@
     #include "constants.qh"
     #include "util.qh"
     #include "urllib.qh"
-    #include "weapons/weapons.qh"
+    #include "weapons/all.qh"
     #include "../server/weapons/accuracy.qh"
     #include "../server/defs.qh"
     #include "playerstats.qh"
index 8f68bafbc89bc5992713358468efe8a1d58dab7a..e6e93a6608fbd9a89108c3557011f5be2cba8168 100644 (file)
@@ -5,23 +5,38 @@
 // 255 is the current limit (MAX_CL_STATS - 1), engine will need to be modified if you wish to add more stats
 
 const int MAX_CL_STATS                = 256;
-const int STAT_HEALTH                 = 0;
+// -Wdouble-declaration
+// const int STAT_HEALTH                 = 0;
 // 1 empty?
 const int STAT_WEAPON                 = 2;
-const int STAT_AMMO                   = 3;
-const int STAT_ARMOR                  = 4;
-const int STAT_WEAPONFRAME            = 5;
-const int STAT_SHELLS                 = 6;
-const int STAT_NAILS                  = 7;
-const int STAT_ROCKETS                = 8;
-const int STAT_CELLS                  = 9;
-const int STAT_ACTIVEWEAPON           = 10;
-const int STAT_TOTALSECRETS           = 11;
-const int STAT_TOTALMONSTERS          = 12;
-const int STAT_SECRETS                = 13;
-const int STAT_MONSTERS               = 14;
-const int STAT_ITEMS                  = 15;
-const int STAT_VIEWHEIGHT             = 16;
+// -Wdouble-declaration
+// const int STAT_AMMO                   = 3;
+// -Wdouble-declaration
+// const int STAT_ARMOR                  = 4;
+// -Wdouble-declaration
+// const int STAT_WEAPONFRAME            = 5;
+// -Wdouble-declaration
+// const int STAT_SHELLS                 = 6;
+// -Wdouble-declaration
+// const int STAT_NAILS                  = 7;
+// -Wdouble-declaration
+// const int STAT_ROCKETS                = 8;
+// -Wdouble-declaration
+// const int STAT_CELLS                  = 9;
+// -Wdouble-declaration
+// const int STAT_ACTIVEWEAPON           = 10;
+// -Wdouble-declaration
+// const int STAT_TOTALSECRETS           = 11;
+// -Wdouble-declaration
+// const int STAT_TOTALMONSTERS          = 12;
+// -Wdouble-declaration
+// const int STAT_SECRETS                = 13;
+// -Wdouble-declaration
+// const int STAT_MONSTERS               = 14;
+// -Wdouble-declaration
+// const int STAT_ITEMS                  = 15;
+// -Wdouble-declaration
+// const int STAT_VIEWHEIGHT             = 16;
 // 17 empty?
 // 18 empty?
 // 19 empty?
@@ -92,9 +107,9 @@ const int STAT_HEALING_ORB_ALPHA      = 83;
 const int STAT_PLASMA                 = 84;
 const int STAT_OK_AMMO_CHARGE         = 85;
 const int STAT_OK_AMMO_CHARGEPOOL     = 86;
-const int STAT_BUFF_TIME              = 87;
-// 88 empty?
-// 89 empty?
+const int STAT_FROZEN                 = 87;
+const int STAT_REVIVE_PROGRESS        = 88;
+const int STAT_BUFF_TIME              = 89;
 // 90 empty?
 // 91 empty?
 // 92 empty?
@@ -138,22 +153,24 @@ const int STAT_KH_PINKKEY_TEAM        = 103;
 
 /* Gamemode-specific stats end here */
 
-
-const int STAT_FROZEN                 = 105;
-const int STAT_REVIVE_PROGRESS        = 106;
-// 107 empty?
-// 108 empty?
-// 109 empty?
-// 110 empty?
-// 111 empty?
-// 112 empty?
-// 113 empty?
-// 114 empty?
-// 115 empty?
-// 116 empty?
-// 117 empty?
-// 118 empty?
-// 119 empty?
+const int STAT_PL_VIEW_OFS1           = 105;
+const int STAT_PL_VIEW_OFS2           = 106;
+const int STAT_PL_VIEW_OFS3           = 107;
+const int STAT_PL_MIN1                = 108;
+const int STAT_PL_MIN2                = 109;
+const int STAT_PL_MIN3                = 110;
+const int STAT_PL_MAX1                = 111;
+const int STAT_PL_MAX2                = 112;
+const int STAT_PL_MAX3                = 113;
+const int STAT_PL_CROUCH_MIN1         = 114;
+const int STAT_PL_CROUCH_MIN2         = 115;
+const int STAT_PL_CROUCH_MIN3         = 116;
+const int STAT_PL_CROUCH_MAX1         = 117;
+const int STAT_PL_CROUCH_MAX2         = 118;
+const int STAT_PL_CROUCH_MAX3         = 119;
+const int STAT_PL_CROUCH_VIEW_OFS1    = 117;
+const int STAT_PL_CROUCH_VIEW_OFS2    = 118;
+const int STAT_PL_CROUCH_VIEW_OFS3    = 119;
 // 120 empty?
 // 121 empty?
 // 122 empty?
@@ -203,58 +220,58 @@ const int STAT_REVIVE_PROGRESS        = 106;
 // 165 empty?
 // 166 empty?
 // 167 empty?
-// 168 empty?
-// 169 empty?
-// 170 empty?
-// 171 empty?
-// 172 empty?
-// 173 empty?
-// 174 empty?
-// 175 empty?
-// 176 empty?
-// 177 empty?
-// 178 empty?
-// 179 empty?
-// 180 empty?
-// 181 empty?
-// 182 empty?
-// 183 empty?
-// 184 empty?
-// 185 empty?
-// 186 empty?
-// 187 empty?
-// 188 empty?
-// 189 empty?
-// 190 empty?
-// 191 empty?
-// 192 empty?
-// 193 empty?
-// 194 empty?
-// 195 empty?
-// 196 empty?
-// 197 empty?
-// 198 empty?
-// 199 empty?
-// 200 empty?
-// 201 empty?
-// 202 empty?
-// 203 empty?
-// 204 empty?
-// 205 empty?
-// 206 empty?
-// 207 empty?
-// 208 empty?
-// 209 empty?
-// 210 empty?
-// 211 empty?
-// 212 empty?
-// 213 empty?
-// 214 empty?
-// 215 empty?
-// 216 empty?
-// 217 empty?
-// 218 empty?
-// 219 empty?
+const int STAT_GAMEPLAYFIX_UPVELOCITYCLEARSONGROUND   = 168;
+const int STAT_BUGRIGS_REVERSE_STOPPING               = 169;
+const int STAT_BUGRIGS_REVERSE_SPINNING               = 170;
+const int STAT_BUGRIGS_CAR_JUMPING                    = 171;
+const int STAT_BUGRIGS_FRICTION_AIR                   = 172;
+const int STAT_BUGRIGS_STEER                          = 173;
+const int STAT_BUGRIGS_SPEED_POW                      = 174;
+const int STAT_BUGRIGS_SPEED_REF                      = 175;
+const int STAT_BUGRIGS_ACCEL                          = 176;
+const int STAT_BUGRIGS_FRICTION_BRAKE                 = 177;
+const int STAT_BUGRIGS_AIR_STEERING                   = 178;
+const int STAT_BUGRIGS_FRICTION_FLOOR                 = 179;
+const int STAT_BUGRIGS_REVERSE_SPEEDING               = 180;
+const int STAT_BUGRIGS_PLANAR_MOVEMENT                = 181;
+const int STAT_BUGRIGS_ANGLE_SMOOTHING                = 182;
+const int STAT_BUGRIGS                                = 183;
+const int STAT_GAMEPLAYFIX_STEPDOWN                   = 184;
+const int STAT_MOVEVARS_JUMPSTEP                      = 185;
+const int STAT_NOSTEP                                 = 186;
+const int STAT_GAMEPLAYFIX_UNSTICKPLAYERS             = 187;
+const int STAT_GAMEPLAYFIX_STEPMULTIPLETIMES          = 188;
+const int STAT_GAMEPLAYFIX_DOWNTRACEONGROUND          = 189;
+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;
+const int STAT_MOVEVARS_JUMPSPEEDCAP_MAX              = 194;
+const int STAT_MOVEVARS_JUMPSPEEDCAP_MIN              = 195;
+const int STAT_DOUBLEJUMP                             = 196;
+const int STAT_MOVEVARS_TRACK_CANJUMP                 = 197;
+const int STAT_MULTIJUMP_ADD                          = 198;
+const int STAT_MULTIJUMP_SPEED                        = 199;
+const int STAT_MULTIJUMP                              = 200;
+const int STAT_DODGING_TIMEOUT                        = 201;
+const int STAT_DODGING_WALL                           = 202;
+const int STAT_DODGING_UP_SPEED                       = 203;
+const int STAT_DODGING_RAMP_TIME                      = 204;
+const int STAT_DODGING_HEIGHT_THRESHOLD               = 205;
+const int STAT_DODGING_DISTANCE_THRESHOLD             = 206;
+const int STAT_DODGING_HORIZ_SPEED                    = 207;
+const int STAT_DODGING_DELAY                          = 208;
+const int STAT_DODGING_FROZEN_NO_DOUBLETAP            = 209;
+const int STAT_DODGING_HORIZ_SPEED_FROZEN             = 210;
+const int STAT_DODGING                                = 211;
+const int STAT_DODGING_FROZEN                         = 212;
+const int STAT_JETPACK_MAXSPEED_UP                    = 213;
+const int STAT_JETPACK_MAXSPEED_SIDE                  = 214;
+const int STAT_JETPACK_FUEL                           = 215;
+const int STAT_JETPACK_ANTIGRAVITY                    = 216;
+const int STAT_JETPACK_ACCEL_SIDE                     = 217;
+const int STAT_JETPACK_ACCEL_UP                       = 218;
+const int STAT_MOVEVARS_HIGHSPEED                     = 219;
 const int STAT_MOVEVARS_AIRACCEL_QW_STRETCHFACTOR     = 220;
 const int STAT_MOVEVARS_AIRCONTROL_PENALTY            = 221;
 const int STAT_MOVEVARS_AIRSPEEDLIMIT_NONQW           = 222;
@@ -270,14 +287,19 @@ const int STAT_MOVEVARS_AIRSTOPACCELERATE             = 231;
 const int STAT_MOVEVARS_AIRSTRAFEACCELERATE           = 232;
 const int STAT_MOVEVARS_MAXAIRSTRAFESPEED             = 233;
 const int STAT_MOVEVARS_AIRCONTROL                    = 234;
-const int STAT_FRAGLIMIT                              = 235;
-const int STAT_TIMELIMIT                              = 236;
+// -Wdouble-declaration
+// const int STAT_FRAGLIMIT                              = 235;
+// -Wdouble-declaration
+// const int STAT_TIMELIMIT                              = 236;
 const int STAT_MOVEVARS_WALLFRICTION                  = 237;
 const int STAT_MOVEVARS_FRICTION                      = 238;
 const int STAT_MOVEVARS_WATERFRICTION                 = 239;
-const int STAT_MOVEVARS_TICRATE                       = 240;
-const int STAT_MOVEVARS_TIMESCALE                     = 241;
-const int STAT_MOVEVARS_GRAVITY                       = 242;
+// -Wdouble-declaration
+// const int STAT_MOVEVARS_TICRATE                       = 240;
+// -Wdouble-declaration
+// const int STAT_MOVEVARS_TIMESCALE                     = 241;
+// -Wdouble-declaration
+// const int STAT_MOVEVARS_GRAVITY                       = 242;
 const int STAT_MOVEVARS_STOPSPEED                     = 243;
 const int STAT_MOVEVARS_MAXSPEED                      = 244;
 const int STAT_MOVEVARS_SPECTATORMAXSPEED             = 245;
diff --git a/qcsrc/common/triggers/func/bobbing.qc b/qcsrc/common/triggers/func/bobbing.qc
new file mode 100644 (file)
index 0000000..9fb2f56
--- /dev/null
@@ -0,0 +1,85 @@
+#ifdef SVQC
+.float height;
+void func_bobbing_controller_think()
+{
+       vector v;
+       self.nextthink = time + 0.1;
+
+       if(self.owner.active != ACTIVE_ACTIVE)
+       {
+               self.owner.velocity = '0 0 0';
+               return;
+       }
+
+       // calculate sinewave using makevectors
+       makevectors((self.nextthink * self.owner.cnt + self.owner.phase * 360) * '0 1 0');
+       v = self.owner.destvec + self.owner.movedir * v_forward_y;
+       if(self.owner.classname == "func_bobbing") // don't brake stuff if the func_bobbing was killtarget'ed
+               // * 10 so it will arrive in 0.1 sec
+               self.owner.velocity = (v - self.owner.SUB_ORIGIN) * 10;
+}
+
+/*QUAKED spawnfunc_func_bobbing (0 .5 .8) ? X_AXIS Y_AXIS
+Brush model that moves back and forth on one axis (default Z).
+speed : how long one cycle takes in seconds (default 4)
+height : how far the cycle moves (default 32)
+phase : cycle timing adjustment (0-1 as a fraction of the cycle, default 0)
+noise : path/name of looping .wav file to play.
+dmg : Do this mutch dmg every .dmgtime intervall when blocked
+dmgtime : See above.
+*/
+void spawnfunc_func_bobbing()
+{
+       entity controller;
+       if (self.noise != "")
+       {
+               precache_sound(self.noise);
+               soundto(MSG_INIT, self, CH_TRIGGER_SINGLE, self.noise, VOL_BASE, ATTEN_IDLE);
+       }
+       if (!self.speed)
+               self.speed = 4;
+       if (!self.height)
+               self.height = 32;
+       // center of bobbing motion
+       self.destvec = self.origin;
+       // time scale to get degrees
+       self.cnt = 360 / self.speed;
+
+       self.active = ACTIVE_ACTIVE;
+
+       // damage when blocked
+       self.blocked = generic_plat_blocked;
+       if(self.dmg && (self.message == ""))
+               self.message = " was squished";
+    if(self.dmg && (self.message2 == ""))
+               self.message2 = "was squished by";
+       if(self.dmg && (!self.dmgtime))
+               self.dmgtime = 0.25;
+       self.dmgtime2 = time;
+
+       // how far to bob
+       if (self.spawnflags & 1) // X
+               self.movedir = '1 0 0' * self.height;
+       else if (self.spawnflags & 2) // Y
+               self.movedir = '0 1 0' * self.height;
+       else // Z
+               self.movedir = '0 0 1' * self.height;
+
+       if (!InitMovingBrushTrigger())
+               return;
+
+       // wait for targets to spawn
+       controller = spawn();
+       controller.classname = "func_bobbing_controller";
+       controller.owner = self;
+       controller.nextthink = time + 1;
+       controller.think = func_bobbing_controller_think;
+       self.SUB_NEXTTHINK = self.SUB_LTIME + 999999999;
+       self.SUB_THINK = SUB_NullThink;
+
+       // Savage: Reduce bandwith, critical on e.g. nexdm02
+       self.effects |= EF_LOWPRECISION;
+
+       // TODO make a reset function for this one
+}
+#endif
diff --git a/qcsrc/common/triggers/func/breakable.qc b/qcsrc/common/triggers/func/breakable.qc
new file mode 100644 (file)
index 0000000..85120ef
--- /dev/null
@@ -0,0 +1,324 @@
+#ifdef SVQC
+
+#include "../../../server/_all.qh"
+
+#include "../../../server/g_subs.qh"
+#include "../../../server/waypointsprites.qh"
+#include "../../../server/g_damage.qh"
+#include "../../../server/bot/bot.qh"
+#include "../../common/csqcmodel_settings.qh"
+#include "../../../csqcmodellib/sv_model.qh"
+#include "../../../server/weapons/common.qh"
+
+.entity sprite;
+
+.float dmg;
+.float dmg_edge;
+.float dmg_radius;
+.float dmg_force;
+.float debrismovetype;
+.float debrissolid;
+.vector debrisvelocity;
+.vector debrisvelocityjitter;
+.vector debrisavelocityjitter;
+.float debristime;
+.float debristimejitter;
+.float debrisfadetime;
+.float debrisdamageforcescale;
+.float debrisskin;
+
+.string mdl_dead; // or "" to hide when broken
+.string debris; // space separated list of debris models
+// other fields:
+//   mdl = particle effect name
+//   count = particle effect multiplier
+//   targetname = target to trigger to unbreak the model
+//   target = targets to trigger when broken
+//   health = amount of damage it can take
+//   spawnflags:
+//     1 = start disabled (needs to be triggered to activate)
+//     2 = indicate damage
+// notes:
+//   for mdl_dead to work, origin must be set (using a common/origin brush).
+//   Otherwise mdl_dead will be displayed at the map origin, and nobody would
+//   want that!
+
+void func_breakable_damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force);
+
+//
+// func_breakable
+// - basically func_assault_destructible for general gameplay use
+//
+void LaunchDebris (string debrisname, vector force)
+{
+       entity dbr = spawn();
+       setorigin(dbr, self.absmin
+                  + '1 0 0' * random() * (self.absmax.x - self.absmin.x)
+                  + '0 1 0' * random() * (self.absmax.y - self.absmin.y)
+                  + '0 0 1' * random() * (self.absmax.z - self.absmin.z));
+       setmodel (dbr, debrisname );
+       dbr.skin = self.debrisskin;
+       dbr.colormap = self.colormap; // inherit team colors
+       dbr.owner = self; // do not be affected by our own explosion
+       dbr.movetype = self.debrismovetype;
+       dbr.solid = self.debrissolid;
+       if(dbr.solid != SOLID_BSP) // SOLID_BSP has exact collision, MAYBE this works? TODO check this out
+               setsize(dbr, '0 0 0', '0 0 0'); // needed for performance, until engine can deal better with it
+       dbr.velocity_x = self.debrisvelocity.x + self.debrisvelocityjitter.x * crandom();
+       dbr.velocity_y = self.debrisvelocity.y + self.debrisvelocityjitter.y * crandom();
+       dbr.velocity_z = self.debrisvelocity.z + self.debrisvelocityjitter.z * crandom();
+       self.velocity = self.velocity + force * self.debrisdamageforcescale;
+       dbr.avelocity_x = random()*self.debrisavelocityjitter.x;
+       dbr.avelocity_y = random()*self.debrisavelocityjitter.y;
+       dbr.avelocity_z = random()*self.debrisavelocityjitter.z;
+       dbr.damageforcescale = self.debrisdamageforcescale;
+       if(dbr.damageforcescale)
+               dbr.takedamage = DAMAGE_YES;
+       SUB_SetFade(dbr, time + self.debristime + crandom() * self.debristimejitter, self.debrisfadetime);
+}
+
+void func_breakable_colormod()
+{
+       float h;
+       if (!(self.spawnflags & 2))
+               return;
+       h = self.health / self.max_health;
+       if(h < 0.25)
+               self.colormod = '1 0 0';
+       else if(h <= 0.75)
+               self.colormod = '1 0 0' + '0 1 0' * (2 * h - 0.5);
+       else
+               self.colormod = '1 1 1';
+
+       CSQCMODEL_AUTOUPDATE();
+}
+
+void func_breakable_look_destroyed()
+{
+       float floorZ;
+
+       if(self.solid == SOLID_BSP) // in case a misc_follow moved me, save the current origin first
+               self.dropped_origin = self.origin;
+
+       if(self.mdl_dead == "")
+               self.effects |= EF_NODRAW;
+       else {
+               if (self.origin == '0 0 0')     {       // probably no origin brush, so don't spawn in the middle of the map..
+                       floorZ = self.absmin.z;
+                       setorigin(self,((self.absmax+self.absmin)*.5));
+                       self.origin_z = floorZ;
+               }
+               setmodel(self, self.mdl_dead);
+               self.effects &= ~EF_NODRAW;
+       }
+
+       CSQCMODEL_AUTOUPDATE();
+
+       self.solid = SOLID_NOT;
+}
+
+void func_breakable_look_restore()
+{
+       setmodel(self, self.mdl);
+       self.effects &= ~EF_NODRAW;
+
+       if(self.mdl_dead != "") // only do this if we use mdl_dead, to behave better with misc_follow
+               setorigin(self, self.dropped_origin);
+
+       CSQCMODEL_AUTOUPDATE();
+
+       self.solid = SOLID_BSP;
+}
+
+void func_breakable_behave_destroyed()
+{
+       self.health = self.max_health;
+       self.takedamage = DAMAGE_NO;
+       self.bot_attack = false;
+       self.event_damage = func_null;
+       self.state = 1;
+       func_breakable_colormod();
+       if (self.noise1)
+               stopsound (self, CH_TRIGGER_SINGLE);
+}
+
+void func_breakable_behave_restore()
+{
+       self.health = self.max_health;
+       if(self.sprite)
+       {
+               WaypointSprite_UpdateMaxHealth(self.sprite, self.max_health);
+               WaypointSprite_UpdateHealth(self.sprite, self.health);
+       }
+       self.takedamage = DAMAGE_AIM;
+       self.bot_attack = true;
+       self.event_damage = func_breakable_damage;
+       self.state = 0;
+       self.nextthink = 0; // cancel auto respawn
+       func_breakable_colormod();
+       if (self.noise1)
+               sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTEN_NORM);
+}
+
+void func_breakable_init_for_player(entity player)
+{
+       if (self.noise1 && self.state == 0 && clienttype(player) == CLIENTTYPE_REAL)
+       {
+               msg_entity = player;
+               soundto (MSG_ONE, self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTEN_NORM);
+       }
+}
+
+void func_breakable_destroyed()
+{
+       func_breakable_look_destroyed();
+       func_breakable_behave_destroyed();
+
+       CSQCMODEL_AUTOUPDATE();
+}
+
+void func_breakable_restore()
+{
+       func_breakable_look_restore();
+       func_breakable_behave_restore();
+
+       CSQCMODEL_AUTOUPDATE();
+}
+
+vector debrisforce; // global, set before calling this
+void func_breakable_destroy() {
+       float n, i;
+       string oldmsg;
+
+       activator = self.owner;
+       self.owner = world; // set by W_PrepareExplosionByDamage
+
+       // now throw around the debris
+       n = tokenize_console(self.debris);
+       for(i = 0; i < n; ++i)
+               LaunchDebris(argv(i), debrisforce);
+
+       func_breakable_destroyed();
+
+       if(self.noise)
+               sound (self, CH_TRIGGER, self.noise, VOL_BASE, ATTEN_NORM);
+
+       if(self.dmg)
+               RadiusDamage(self, activator, self.dmg, self.dmg_edge, self.dmg_radius, self, world, self.dmg_force, DEATH_HURTTRIGGER, world);
+
+       if(self.cnt)
+               pointparticles(self.cnt, self.absmin * 0.5 + self.absmax * 0.5, '0 0 0', self.count);
+
+       if(self.respawntime)
+       {
+               self.think = func_breakable_restore;
+               self.nextthink = time + self.respawntime + crandom() * self.respawntimejitter;
+       }
+
+       oldmsg = self.message;
+       self.message = "";
+       SUB_UseTargets();
+       self.message = oldmsg;
+}
+
+void func_breakable_damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
+{
+       if(self.state == 1)
+               return;
+       if(self.spawnflags & DOOR_NOSPLASH)
+               if(!(DEATH_ISSPECIAL(deathtype)) && (deathtype & HITTYPE_SPLASH))
+                       return;
+       if(self.team)
+               if(attacker.team == self.team)
+                       return;
+       self.health = self.health - damage;
+       if(self.sprite)
+       {
+               WaypointSprite_Ping(self.sprite);
+               WaypointSprite_UpdateHealth(self.sprite, self.health);
+       }
+       func_breakable_colormod();
+
+       if(self.health <= 0)
+       {
+               debrisforce = force;
+               W_PrepareExplosionByDamage(attacker, func_breakable_destroy);
+       }
+}
+
+void func_breakable_reset()
+{
+       self.team = self.team_saved;
+       func_breakable_look_restore();
+       if(self.spawnflags & 1)
+               func_breakable_behave_destroyed();
+       else
+               func_breakable_behave_restore();
+
+       CSQCMODEL_AUTOUPDATE();
+}
+
+// destructible walls that can be used to trigger target_objective_decrease
+void spawnfunc_func_breakable()
+{
+       float n, i;
+       if(!self.health)
+               self.health = 100;
+       self.max_health = self.health;
+
+       // yes, I know, MOVETYPE_NONE is not available here, not that one would want it here anyway
+       if(!self.debrismovetype) self.debrismovetype = MOVETYPE_BOUNCE;
+       if(!self.debrissolid) self.debrissolid = SOLID_NOT;
+       if(self.debrisvelocity == '0 0 0') self.debrisvelocity = '0 0 140';
+       if(self.debrisvelocityjitter == '0 0 0') self.debrisvelocityjitter = '70 70 70';
+       if(self.debrisavelocityjitter == '0 0 0') self.debrisavelocityjitter = '600 600 600';
+       if(!self.debristime) self.debristime = 3.5;
+       if(!self.debristimejitter) self.debristime = 2.5;
+
+       if(self.mdl != "")
+               self.cnt = particleeffectnum(self.mdl);
+       if(self.count == 0)
+               self.count = 1;
+
+       if(self.message == "")
+               self.message = "got too close to an explosion";
+       if(self.message2 == "")
+               self.message2 = "was pushed into an explosion by";
+       if(!self.dmg_radius)
+               self.dmg_radius = 150;
+       if(!self.dmg_force)
+               self.dmg_force = 200;
+
+       self.mdl = self.model;
+       SetBrushEntityModel();
+
+       self.use = func_breakable_restore;
+
+       // precache all the models
+       if (self.mdl_dead)
+               precache_model(self.mdl_dead);
+       n = tokenize_console(self.debris);
+       for(i = 0; i < n; ++i)
+               precache_model(argv(i));
+       if(self.noise)
+               precache_sound(self.noise);
+       if(self.noise1)
+               precache_sound(self.noise1);
+
+       self.team_saved = self.team;
+       self.dropped_origin = self.origin;
+
+       self.reset = func_breakable_reset;
+       func_breakable_reset();
+
+       self.init_for_player_needed = 1;
+       self.init_for_player = func_breakable_init_for_player;
+
+       CSQCMODEL_AUTOINIT();
+}
+
+// for use in maps with a "model" key set
+void spawnfunc_misc_breakablemodel() {
+       spawnfunc_func_breakable();
+}
+#endif
diff --git a/qcsrc/common/triggers/func/breakable.qh b/qcsrc/common/triggers/func/breakable.qh
new file mode 100644 (file)
index 0000000..b641d94
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef TRIGGERS_FUNC_BREAKABLE_H
+#define TRIGGERS_FUNC_BREAKABLE_H
+
+#ifdef SVQC
+void spawnfunc_func_breakable();
+#endif
+
+#endif
diff --git a/qcsrc/common/triggers/func/button.qc b/qcsrc/common/triggers/func/button.qc
new file mode 100644 (file)
index 0000000..bb8875b
--- /dev/null
@@ -0,0 +1,155 @@
+#ifdef SVQC
+// button and multiple button
+
+void() button_wait;
+void() button_return;
+
+void button_wait()
+{
+       self.state = STATE_TOP;
+       self.SUB_NEXTTHINK = self.SUB_LTIME + self.wait;
+       self.SUB_THINK = button_return;
+       activator = self.enemy;
+       SUB_UseTargets();
+       self.frame = 1;                 // use alternate textures
+}
+
+void button_done()
+{
+       self.state = STATE_BOTTOM;
+}
+
+void button_return()
+{
+       self.state = STATE_DOWN;
+       SUB_CalcMove (self.pos1, TSPEED_LINEAR, self.speed, button_done);
+       self.frame = 0;                 // use normal textures
+       if (self.health)
+               self.takedamage = DAMAGE_YES;   // can be shot again
+}
+
+
+void button_blocked()
+{
+       // do nothing, just don't come all the way back out
+}
+
+
+void button_fire()
+{
+       self.health = self.max_health;
+       self.takedamage = DAMAGE_NO;    // will be reset upon return
+
+       if (self.state == STATE_UP || self.state == STATE_TOP)
+               return;
+
+       if (self.noise != "")
+               sound (self, CH_TRIGGER, self.noise, VOL_BASE, ATTEN_NORM);
+
+       self.state = STATE_UP;
+       SUB_CalcMove (self.pos2, TSPEED_LINEAR, self.speed, button_wait);
+}
+
+void button_reset()
+{
+       self.health = self.max_health;
+       setorigin(self, self.pos1);
+       self.frame = 0;                 // use normal textures
+       self.state = STATE_BOTTOM;
+       if (self.health)
+               self.takedamage = DAMAGE_YES;   // can be shot again
+}
+
+void button_use()
+{
+       if(self.active != ACTIVE_ACTIVE)
+               return;
+
+       self.enemy = activator;
+       button_fire ();
+}
+
+void button_touch()
+{
+       if (!other)
+               return;
+       if (!other.iscreature)
+               return;
+       if(other.velocity * self.movedir < 0)
+               return;
+       self.enemy = other;
+       if (other.owner)
+               self.enemy = other.owner;
+       button_fire ();
+}
+
+void button_damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
+{
+       if(self.spawnflags & DOOR_NOSPLASH)
+               if(!(DEATH_ISSPECIAL(deathtype)) && (deathtype & HITTYPE_SPLASH))
+                       return;
+       self.health = self.health - damage;
+       if (self.health <= 0)
+       {
+               self.enemy = damage_attacker;
+               button_fire ();
+       }
+}
+
+
+/*QUAKED spawnfunc_func_button (0 .5 .8) ?
+When a button is touched, it moves some distance in the direction of it's angle, triggers all of it's targets, waits some time, then returns to it's original position where it can be triggered again.
+
+"angle"                determines the opening direction
+"target"       all entities with a matching targetname will be used
+"speed"                override the default 40 speed
+"wait"         override the default 1 second wait (-1 = never return)
+"lip"          override the default 4 pixel lip remaining at end of move
+"health"       if set, the button must be killed instead of touched. If set to -1, the button will fire on ANY attack, even damageless ones like the InstaGib laser
+"sounds"
+0) steam metal
+1) wooden clunk
+2) metallic click
+3) in-out
+*/
+void spawnfunc_func_button()
+{
+       SetMovedir ();
+
+       if (!InitMovingBrushTrigger())
+               return;
+       self.effects |= EF_LOWPRECISION;
+
+       self.blocked = button_blocked;
+       self.use = button_use;
+
+//     if (self.health == 0) // all buttons are now shootable
+//             self.health = 10;
+       if (self.health)
+       {
+               self.max_health = self.health;
+               self.event_damage = button_damage;
+               self.takedamage = DAMAGE_YES;
+       }
+       else
+               self.touch = button_touch;
+
+       if (!self.speed)
+               self.speed = 40;
+       if (!self.wait)
+               self.wait = 1;
+       if (!self.lip)
+               self.lip = 4;
+
+    if(self.noise != "")
+        precache_sound(self.noise);
+
+       self.active = ACTIVE_ACTIVE;
+
+       self.pos1 = self.origin;
+       self.pos2 = self.pos1 + self.movedir*(fabs(self.movedir*self.size) - self.lip);
+    self.flags |= FL_NOTARGET;
+
+       button_reset();
+}
+#endif
diff --git a/qcsrc/common/triggers/func/conveyor.qc b/qcsrc/common/triggers/func/conveyor.qc
new file mode 100644 (file)
index 0000000..6ed01b0
--- /dev/null
@@ -0,0 +1,197 @@
+void conveyor_think()
+{
+#ifdef CSQC
+       // TODO: check if this is what is causing the glitchiness when switching between them
+       float dt = time - self.move_time;
+       self.move_time = time;
+       if(dt <= 0) { return; }
+#endif
+       entity e;
+
+       // set myself as current conveyor where possible
+       for(e = world; (e = findentity(e, conveyor, self)); )
+               e.conveyor = world;
+
+       if(self.state)
+       {
+               for(e = findradius((self.absmin + self.absmax) * 0.5, vlen(self.absmax - self.absmin) * 0.5 + 1); e; e = e.chain)
+                       if(!e.conveyor.state)
+                               if(isPushable(e))
+                               {
+                                       vector emin = e.absmin;
+                                       vector emax = e.absmax;
+                                       if(self.solid == SOLID_BSP)
+                                       {
+                                               emin -= '1 1 1';
+                                               emax += '1 1 1';
+                                       }
+                                       if(boxesoverlap(emin, emax, self.absmin, self.absmax)) // quick
+                                               if(WarpZoneLib_BoxTouchesBrush(emin, emax, self, e)) // accurate
+                                                       e.conveyor = self;
+                               }
+
+               for(e = world; (e = findentity(e, conveyor, self)); )
+               {
+                       if(IS_CLIENT(e)) // doing it via velocity has quite some advantages
+                               continue; // done in SV_PlayerPhysics   continue;
+
+                       setorigin(e, e.origin + self.movedir * PHYS_INPUT_FRAMETIME);
+                       move_out_of_solid(e);
+#ifdef SVQC
+                       UpdateCSQCProjectile(e);
+#endif
+                       /*
+                       // stupid conveyor code
+                       tracebox(e.origin, e.mins, e.maxs, e.origin + self.movedir * sys_frametime, MOVE_NORMAL, e);
+                       if(trace_fraction > 0)
+                               setorigin(e, trace_endpos);
+                       */
+               }
+       }
+
+#ifdef SVQC
+       self.nextthink = time;
+#endif
+}
+
+#ifdef SVQC
+
+void conveyor_use()
+{
+       self.state = !self.state;
+
+       self.SendFlags |= 2;
+}
+
+void conveyor_reset()
+{
+       self.state = (self.spawnflags & 1);
+
+       self.SendFlags |= 2;
+}
+
+bool conveyor_send(entity to, int sf)
+{
+       WriteByte(MSG_ENTITY, ENT_CLIENT_CONVEYOR);
+       WriteByte(MSG_ENTITY, sf);
+
+       if(sf & 1)
+       {
+               WriteByte(MSG_ENTITY, self.warpzone_isboxy);
+               WriteCoord(MSG_ENTITY, self.origin_x);
+               WriteCoord(MSG_ENTITY, self.origin_y);
+               WriteCoord(MSG_ENTITY, self.origin_z);
+
+               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);
+
+               WriteCoord(MSG_ENTITY, self.movedir_x);
+               WriteCoord(MSG_ENTITY, self.movedir_y);
+               WriteCoord(MSG_ENTITY, self.movedir_z);
+
+               WriteByte(MSG_ENTITY, self.speed);
+               WriteByte(MSG_ENTITY, self.state);
+
+               WriteString(MSG_ENTITY, self.targetname);
+               WriteString(MSG_ENTITY, self.target);
+       }
+
+       if(sf & 2)
+               WriteByte(MSG_ENTITY, self.state);
+
+       return true;
+}
+
+void conveyor_init()
+{
+       if (!self.speed)
+               self.speed = 200;
+       self.movedir = self.movedir * self.speed;
+       self.think = conveyor_think;
+       self.nextthink = time;
+       IFTARGETED
+       {
+               self.use = conveyor_use;
+               self.reset = conveyor_reset;
+               conveyor_reset();
+       }
+       else
+               self.state = 1;
+
+       FixSize(self);
+
+       Net_LinkEntity(self, 0, false, conveyor_send);
+
+       self.SendFlags |= 1;
+}
+
+void spawnfunc_trigger_conveyor()
+{
+       SetMovedir();
+       EXACTTRIGGER_INIT;
+       conveyor_init();
+}
+
+void spawnfunc_func_conveyor()
+{
+       SetMovedir();
+       InitMovingBrushTrigger();
+       self.movetype = MOVETYPE_NONE;
+       conveyor_init();
+}
+
+#elif defined(CSQC)
+
+void conveyor_init()
+{
+       self.draw = conveyor_think;
+       self.drawmask = MASK_NORMAL;
+
+       self.movetype = MOVETYPE_NONE;
+       self.model = "";
+       self.solid = SOLID_TRIGGER;
+       self.move_origin = self.origin;
+       self.move_time = time;
+}
+
+void ent_conveyor()
+{
+       float sf = ReadByte();
+
+       if(sf & 1)
+       {
+               self.warpzone_isboxy = ReadByte();
+               self.origin_x = ReadCoord();
+               self.origin_y = ReadCoord();
+               self.origin_z = ReadCoord();
+               setorigin(self, self.origin);
+
+               self.mins_x = ReadCoord();
+               self.mins_y = ReadCoord();
+               self.mins_z = ReadCoord();
+               self.maxs_x = ReadCoord();
+               self.maxs_y = ReadCoord();
+               self.maxs_z = ReadCoord();
+               setsize(self, self.mins, self.maxs);
+
+               self.movedir_x = ReadCoord();
+               self.movedir_y = ReadCoord();
+               self.movedir_z = ReadCoord();
+
+               self.speed = ReadByte();
+               self.state = ReadByte();
+
+               self.targetname = strzone(ReadString());
+               self.target = strzone(ReadString());
+
+               conveyor_init();
+       }
+
+       if(sf & 2)
+               self.state = ReadByte();
+}
+#endif
diff --git a/qcsrc/common/triggers/func/conveyor.qh b/qcsrc/common/triggers/func/conveyor.qh
new file mode 100644 (file)
index 0000000..f272030
--- /dev/null
@@ -0,0 +1,3 @@
+#ifdef CSQC
+void ent_conveyor();
+#endif
diff --git a/qcsrc/common/triggers/func/door.qc b/qcsrc/common/triggers/func/door.qc
new file mode 100644 (file)
index 0000000..e3f82af
--- /dev/null
@@ -0,0 +1,886 @@
+/*
+
+Doors are similar to buttons, but can spawn a fat trigger field around them
+to open without a touch, and they link together to form simultanious
+double/quad doors.
+
+Door.owner is the master door.  If there is only one door, it points to itself.
+If multiple doors, all will point to a single one.
+
+Door.enemy chains from the master door through all doors linked in the chain.
+
+*/
+
+
+/*
+=============================================================================
+
+THINK FUNCTIONS
+
+=============================================================================
+*/
+
+void() door_go_down;
+void() door_go_up;
+void() door_rotating_go_down;
+void() door_rotating_go_up;
+
+void door_blocked()
+{
+       if((self.spawnflags & 8) 
+#ifdef SVQC
+               && (other.takedamage != DAMAGE_NO)
+#elif defined(CSQC)
+               && !PHYS_DEAD(other)
+#endif
+       )
+       { // KIll Kill Kill!!
+#ifdef SVQC
+               Damage (other, self, self, 10000, DEATH_HURTTRIGGER, other.origin, '0 0 0');
+#endif
+       }
+       else
+       {
+#ifdef SVQC
+               if((self.dmg) && (other.takedamage == DAMAGE_YES))    // Shall we bite?
+                       Damage (other, self, self, self.dmg, DEATH_HURTTRIGGER, other.origin, '0 0 0');
+#endif
+
+                // don't change direction for dead or dying stuff
+               if(PHYS_DEAD(other)
+#ifdef SVQC
+                       && (other.takedamage == DAMAGE_NO)
+#endif
+               )
+               {
+                       if (self.wait >= 0)
+                       {
+                               if (self.state == STATE_DOWN)
+                       if (self.classname == "door")
+                       {
+                               door_go_up ();
+                       } else
+                       {
+                               door_rotating_go_up ();
+                       }
+                               else
+                       if (self.classname == "door")
+                       {
+                               door_go_down ();
+                       } else
+                       {
+                               door_rotating_go_down ();
+                       }
+                       }
+               }
+#ifdef SVQC
+               else
+               {
+                       //gib dying stuff just to make sure
+                       if((self.dmg) && (other.takedamage != DAMAGE_NO))    // Shall we bite?
+                               Damage (other, self, self, 10000, DEATH_HURTTRIGGER, other.origin, '0 0 0');
+               }
+#endif
+       }
+}
+
+void door_hit_top()
+{
+       if (self.noise1 != "")
+               sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTEN_NORM);
+       self.state = STATE_TOP;
+       if (self.spawnflags & DOOR_TOGGLE)
+               return;         // don't come down automatically
+       if (self.classname == "door")
+       {
+               self.SUB_THINK = door_go_down;
+       } else
+       {
+               self.SUB_THINK = door_rotating_go_down;
+       }
+       self.SUB_NEXTTHINK = self.SUB_LTIME + self.wait;
+}
+
+void door_hit_bottom()
+{
+       if (self.noise1 != "")
+               sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTEN_NORM);
+       self.state = STATE_BOTTOM;
+}
+
+void door_go_down()
+{
+       if (self.noise2 != "")
+               sound (self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTEN_NORM);
+       if (self.max_health)
+       {
+               self.takedamage = DAMAGE_YES;
+               self.health = self.max_health;
+       }
+
+       self.state = STATE_DOWN;
+       SUB_CalcMove (self.pos1, TSPEED_LINEAR, self.speed, door_hit_bottom);
+}
+
+void door_go_up()
+{
+       if (self.state == STATE_UP)
+               return;         // already going up
+
+       if (self.state == STATE_TOP)
+       {       // reset top wait time
+               self.SUB_NEXTTHINK = self.SUB_LTIME + self.wait;
+               return;
+       }
+
+       if (self.noise2 != "")
+               sound (self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTEN_NORM);
+       self.state = STATE_UP;
+       SUB_CalcMove (self.pos2, TSPEED_LINEAR, self.speed, door_hit_top);
+
+       string oldmessage;
+       oldmessage = self.message;
+       self.message = "";
+       SUB_UseTargets();
+       self.message = oldmessage;
+}
+
+
+/*
+=============================================================================
+
+ACTIVATION FUNCTIONS
+
+=============================================================================
+*/
+
+float door_check_keys(void)
+{
+       local entity door;
+
+
+       if (self.owner)
+               door = self.owner;
+       else
+               door = self;
+
+       // no key needed
+       if (!door.itemkeys)
+               return true;
+
+       // this door require a key
+       // only a player can have a key
+       if (!IS_PLAYER(other))
+               return false;
+
+#ifdef SVQC
+       if (item_keys_usekey(door, other))
+       {
+               // some keys were used
+               if (other.key_door_messagetime <= time)
+               {
+
+                       play2(other, "misc/talk.wav");
+                       Send_Notification(NOTIF_ONE, other, MSG_CENTER, CENTER_DOOR_LOCKED_ALSONEED, item_keys_keylist(door.itemkeys));
+                       other.key_door_messagetime = time + 2;
+               }
+       }
+       else
+       {
+               // no keys were used
+               if (other.key_door_messagetime <= time)
+               {
+                       play2(other, "misc/talk.wav");
+                       Send_Notification(NOTIF_ONE, other, MSG_CENTER, CENTER_DOOR_LOCKED_NEED, item_keys_keylist(door.itemkeys));
+
+                       other.key_door_messagetime = time + 2;
+               }
+       }
+#endif
+
+       if (door.itemkeys)
+       {
+#ifdef SVQC
+               // door is now unlocked
+               play2(other, "misc/talk.wav");
+               Send_Notification(NOTIF_ONE, other, MSG_CENTER, CENTER_DOOR_UNLOCKED);
+#endif
+               return true;
+       }
+       else
+               return false;
+}
+
+void door_fire()
+{
+       entity  oself;
+       entity  starte;
+
+       if (self.owner != self)
+               objerror ("door_fire: self.owner != self");
+
+       oself = self;
+
+       if (self.spawnflags & DOOR_TOGGLE)
+       {
+               if (self.state == STATE_UP || self.state == STATE_TOP)
+               {
+                       starte = self;
+                       do
+                       {
+                               if (self.classname == "door")
+                               {
+                                       door_go_down ();
+                               }
+                               else
+                               {
+                                       door_rotating_go_down ();
+                               }
+                               self = self.enemy;
+                       } while ( (self != starte) && (self != world) );
+                       self = oself;
+                       return;
+               }
+       }
+
+// trigger all paired doors
+       starte = self;
+       do
+       {
+               if (self.classname == "door")
+               {
+                       door_go_up ();
+               } else
+               {
+                       // if the BIDIR spawnflag (==2) is set and the trigger has set trigger_reverse, reverse the opening direction
+                       if ((self.spawnflags & 2) && other.trigger_reverse!=0 && self.lip!=666 && self.state == STATE_BOTTOM)
+                       {
+                               self.lip = 666; // self.lip is used to remember reverse opening direction for door_rotating
+                               self.pos2 = '0 0 0' - self.pos2;
+                       }
+                       // if BIDIR_IN_DOWN (==8) is set, prevent the door from reoping during closing if it is triggered from the wrong side
+                       if (!((self.spawnflags & 2) &&  (self.spawnflags & 8) && self.state == STATE_DOWN
+                               && (((self.lip==666) && (other.trigger_reverse==0)) || ((self.lip!=666) && (other.trigger_reverse!=0)))))
+                       {
+                               door_rotating_go_up ();
+                       }
+               }
+               self = self.enemy;
+       } while ( (self != starte) && (self != world) );
+       self = oself;
+}
+
+void door_use()
+{
+       entity oself;
+
+       //dprint("door_use (model: ");dprint(self.model);dprint(")\n");
+
+       if (self.owner)
+       {
+               oself = self;
+               self = self.owner;
+               door_fire ();
+               self = oself;
+       }
+}
+
+void door_damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
+{
+       entity oself;
+       if(self.spawnflags & DOOR_NOSPLASH)
+               if(!(DEATH_ISSPECIAL(deathtype)) && (deathtype & HITTYPE_SPLASH))
+                       return;
+       self.health = self.health - damage;
+
+       if (self.itemkeys)
+       {
+               // don't allow opening doors through damage if keys are required
+               return;
+       }
+
+       if (self.health <= 0)
+       {
+               oself = self;
+               self = self.owner;
+               self.health = self.max_health;
+               self.takedamage = DAMAGE_NO;    // wil be reset upon return
+               door_use ();
+               self = oself;
+       }
+}
+
+
+/*
+================
+door_touch
+
+Prints messages
+================
+*/
+
+void door_touch()
+{
+       if (!IS_PLAYER(other))
+               return;
+       if (self.owner.attack_finished_single > time)
+               return;
+
+       self.owner.attack_finished_single = time + 2;
+
+#ifdef SVQC
+       if (!(self.owner.dmg) && (self.owner.message != ""))
+       {
+               if (IS_CLIENT(other))
+                       centerprint(other, self.owner.message);
+               play2(other, "misc/talk.wav");
+       }
+#endif
+}
+
+void door_generic_plat_blocked()
+{
+
+       if((self.spawnflags & 8) && (other.takedamage != DAMAGE_NO)) { // KIll Kill Kill!!
+#ifdef SVQC
+               Damage (other, self, self, 10000, DEATH_HURTTRIGGER, other.origin, '0 0 0');
+#endif
+       }
+       else
+       {
+
+#ifdef SVQC
+               if((self.dmg) && (other.takedamage == DAMAGE_YES))    // Shall we bite?
+                       Damage (other, self, self, self.dmg, DEATH_HURTTRIGGER, other.origin, '0 0 0');
+#endif
+
+                //Dont chamge direction for dead or dying stuff
+               if(PHYS_DEAD(other) && (other.takedamage == DAMAGE_NO))
+               {
+                       if (self.wait >= 0)
+                       {
+                               if (self.state == STATE_DOWN)
+                                       door_rotating_go_up ();
+                               else
+                                       door_rotating_go_down ();
+                       }
+               }
+#ifdef SVQC
+               else
+               {
+                       //gib dying stuff just to make sure
+                       if((self.dmg) && (other.takedamage != DAMAGE_NO))    // Shall we bite?
+                               Damage (other, self, self, 10000, DEATH_HURTTRIGGER, other.origin, '0 0 0');
+               }
+#endif
+       }
+}
+
+void door_rotating_hit_top()
+{
+       if (self.noise1 != "")
+               sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTEN_NORM);
+       self.state = STATE_TOP;
+       if (self.spawnflags & DOOR_TOGGLE)
+               return;         // don't come down automatically
+       self.SUB_THINK = door_rotating_go_down;
+       self.SUB_NEXTTHINK = self.SUB_LTIME + self.wait;
+}
+
+void door_rotating_hit_bottom()
+{
+       if (self.noise1 != "")
+               sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTEN_NORM);
+       if (self.lip==666) // self.lip is used to remember reverse opening direction for door_rotating
+       {
+               self.pos2 = '0 0 0' - self.pos2;
+               self.lip = 0;
+       }
+       self.state = STATE_BOTTOM;
+}
+
+void door_rotating_go_down()
+{
+       if (self.noise2 != "")
+               sound (self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTEN_NORM);
+       if (self.max_health)
+       {
+               self.takedamage = DAMAGE_YES;
+               self.health = self.max_health;
+       }
+
+       self.state = STATE_DOWN;
+       SUB_CalcAngleMove (self.pos1, TSPEED_LINEAR, self.speed, door_rotating_hit_bottom);
+}
+
+void door_rotating_go_up()
+{
+       if (self.state == STATE_UP)
+               return;         // already going up
+
+       if (self.state == STATE_TOP)
+       {       // reset top wait time
+               self.SUB_NEXTTHINK = self.SUB_LTIME + self.wait;
+               return;
+       }
+       if (self.noise2 != "")
+               sound (self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTEN_NORM);
+       self.state = STATE_UP;
+       SUB_CalcAngleMove (self.pos2, TSPEED_LINEAR, self.speed, door_rotating_hit_top);
+
+       string oldmessage;
+       oldmessage = self.message;
+       self.message = "";
+       SUB_UseTargets();
+       self.message = oldmessage;
+}
+
+
+/*
+=========================================
+door trigger
+
+Spawned if a door lacks a real activator
+=========================================
+*/
+
+void door_trigger_touch()
+{
+       if (other.health < 1)
+#ifdef SVQC
+               if (!((other.iscreature || (other.flags & FL_PROJECTILE)) && !PHYS_DEAD(other)))
+#elif defined(CSQC)
+               if(!((IS_CLIENT(other) || other.classname == "csqcprojectile") && !PHYS_DEAD(other)))
+#endif
+                       return;
+
+       if (time < self.attack_finished_single)
+               return;
+
+       // check if door is locked
+       if (!door_check_keys())
+               return;
+
+       self.attack_finished_single = time + 1;
+
+       activator = other;
+
+       self = self.owner;
+       door_use ();
+}
+
+void spawn_field(vector fmins, vector fmaxs)
+{
+       entity  trigger;
+       vector  t1 = fmins, t2 = fmaxs;
+
+       trigger = spawn();
+       trigger.classname = "doortriggerfield";
+       trigger.movetype = MOVETYPE_NONE;
+       trigger.solid = SOLID_TRIGGER;
+       trigger.owner = self;
+#ifdef SVQC
+       trigger.touch = door_trigger_touch;
+#elif defined(CSQC)
+       trigger.trigger_touch = door_trigger_touch;
+       trigger.draw = trigger_draw_generic;
+       trigger.drawmask = MASK_NORMAL;
+#endif
+
+       setsize (trigger, t1 - '60 60 8', t2 + '60 60 8');
+}
+
+
+/*
+=============
+LinkDoors
+
+
+=============
+*/
+
+entity LinkDoors_nextent(entity cur, entity near, entity pass)
+{
+       while((cur = find(cur, classname, self.classname)) && ((cur.spawnflags & 4) || cur.enemy))
+       {
+       }
+       return cur;
+}
+
+bool LinkDoors_isconnected(entity e1, entity e2, entity pass)
+{
+       float DELTA = 4;
+       if((e1.absmin_x > e2.absmax_x + DELTA)
+       || (e1.absmin_y > e2.absmax_y + DELTA)
+       || (e1.absmin_z > e2.absmax_z + DELTA)
+       || (e2.absmin_x > e1.absmax_x + DELTA)
+       || (e2.absmin_y > e1.absmax_y + DELTA)
+       || (e2.absmin_z > e1.absmax_z + DELTA)
+       ) { return false; }
+       return true;
+}
+
+#ifdef SVQC
+void door_link();
+#endif
+void LinkDoors()
+{
+       entity  t;
+       vector  cmins, cmaxs;
+
+#ifdef SVQC
+       door_link();
+#endif
+
+       if (self.enemy)
+               return;         // already linked by another door
+       if (self.spawnflags & 4)
+       {
+               self.owner = self.enemy = self;
+
+               if (self.health)
+                       return;
+               IFTARGETED
+                       return;
+               if (self.items)
+                       return;
+
+               spawn_field(self.absmin, self.absmax);
+
+               return;         // don't want to link this door
+       }
+
+       FindConnectedComponent(self, enemy, LinkDoors_nextent, LinkDoors_isconnected, world);
+
+       // set owner, and make a loop of the chain
+       dprint("LinkDoors: linking doors:");
+       for(t = self; ; t = t.enemy)
+       {
+               dprint(" ", etos(t));
+               t.owner = self;
+               if(t.enemy == world)
+               {
+                       t.enemy = self;
+                       break;
+               }
+       }
+       dprint("\n");
+
+       // collect health, targetname, message, size
+       cmins = self.absmin;
+       cmaxs = self.absmax;
+       for(t = self; ; t = t.enemy)
+       {
+               if(t.health && !self.health)
+                       self.health = t.health;
+               if((t.targetname != "") && (self.targetname == ""))
+                       self.targetname = t.targetname;
+               if((t.message != "") && (self.message == ""))
+                       self.message = t.message;
+               if (t.absmin_x < cmins_x)
+                       cmins_x = t.absmin_x;
+               if (t.absmin_y < cmins_y)
+                       cmins_y = t.absmin_y;
+               if (t.absmin_z < cmins_z)
+                       cmins_z = t.absmin_z;
+               if (t.absmax_x > cmaxs_x)
+                       cmaxs_x = t.absmax_x;
+               if (t.absmax_y > cmaxs_y)
+                       cmaxs_y = t.absmax_y;
+               if (t.absmax_z > cmaxs_z)
+                       cmaxs_z = t.absmax_z;
+               if(t.enemy == self)
+                       break;
+       }
+
+       // distribute health, targetname, message
+       for(t = self; t; t = t.enemy)
+       {
+               t.health = self.health;
+               t.targetname = self.targetname;
+               t.message = self.message;
+               if(t.enemy == self)
+                       break;
+       }
+
+       // shootable, or triggered doors just needed the owner/enemy links,
+       // they don't spawn a field
+
+       if (self.health)
+               return;
+       IFTARGETED
+               return;
+       if (self.items)
+               return;
+
+       spawn_field(cmins, cmaxs);
+}
+
+#ifdef SVQC
+/*QUAKED spawnfunc_func_door (0 .5 .8) ? START_OPEN x DOOR_DONT_LINK GOLD_KEY SILVER_KEY TOGGLE
+if two doors touch, they are assumed to be connected and operate as a unit.
+
+TOGGLE causes the door to wait in both the start and end states for a trigger event.
+
+START_OPEN causes the door to move to its destination when spawned, and operate in reverse.  It is used to temporarily or permanently close off an area when triggered (not useful for touch or takedamage doors).
+
+GOLD_KEY causes the door to open only if the activator holds a gold key.
+
+SILVER_KEY causes the door to open only if the activator holds a silver key.
+
+"message"      is printed when the door is touched if it is a trigger door and it hasn't been fired yet
+"angle"                determines the opening direction
+"targetname" if set, no touch field will be spawned and a remote button or trigger field activates the door.
+"health"       if set, door must be shot open
+"speed"                movement speed (100 default)
+"wait"         wait before returning (3 default, -1 = never return)
+"lip"          lip remaining at end of move (8 default)
+"dmg"          damage to inflict when blocked (2 default)
+"sounds"
+0)     no sound
+1)     stone
+2)     base
+3)     stone chain
+4)     screechy metal
+FIXME: only one sound set available at the time being
+
+*/
+
+float door_send(entity to, float sf)
+{
+       WriteByte(MSG_ENTITY, ENT_CLIENT_DOOR);
+       WriteByte(MSG_ENTITY, sf);
+
+       if(sf & SF_TRIGGER_INIT)
+       {
+               WriteString(MSG_ENTITY, self.classname);
+               WriteByte(MSG_ENTITY, self.spawnflags);
+
+               WriteString(MSG_ENTITY, self.model);
+
+               trigger_common_write(true);
+
+               WriteCoord(MSG_ENTITY, self.pos1_x);
+               WriteCoord(MSG_ENTITY, self.pos1_y);
+               WriteCoord(MSG_ENTITY, self.pos1_z);
+               WriteCoord(MSG_ENTITY, self.pos2_x);
+               WriteCoord(MSG_ENTITY, self.pos2_y);
+               WriteCoord(MSG_ENTITY, self.pos2_z);
+
+               WriteCoord(MSG_ENTITY, self.size_x);
+               WriteCoord(MSG_ENTITY, self.size_y);
+               WriteCoord(MSG_ENTITY, self.size_z);
+
+               WriteShort(MSG_ENTITY, self.wait);
+               WriteShort(MSG_ENTITY, self.speed);
+               WriteByte(MSG_ENTITY, self.lip);
+               WriteByte(MSG_ENTITY, self.state);
+               WriteCoord(MSG_ENTITY, self.SUB_LTIME);
+       }
+
+       if(sf & SF_TRIGGER_RESET)
+       {
+               // client makes use of this, we do not
+       }
+
+       if(sf & SF_TRIGGER_UPDATE)
+       {
+               WriteCoord(MSG_ENTITY, self.origin_x);
+               WriteCoord(MSG_ENTITY, self.origin_y);
+               WriteCoord(MSG_ENTITY, self.origin_z);
+
+               WriteCoord(MSG_ENTITY, self.pos1_x);
+               WriteCoord(MSG_ENTITY, self.pos1_y);
+               WriteCoord(MSG_ENTITY, self.pos1_z);
+               WriteCoord(MSG_ENTITY, self.pos2_x);
+               WriteCoord(MSG_ENTITY, self.pos2_y);
+               WriteCoord(MSG_ENTITY, self.pos2_z);
+       }
+
+       return true;
+}
+
+void door_link()
+{
+       // set size now, as everything is loaded
+       //FixSize(self);
+       //Net_LinkEntity(self, false, 0, door_send);
+}
+#endif
+
+void door_init_startopen()
+{
+       SUB_SETORIGIN(self, self.pos2);
+       self.pos2 = self.pos1;
+       self.pos1 = self.origin;
+
+#ifdef SVQC
+       self.SendFlags |= SF_TRIGGER_UPDATE;
+#endif
+}
+
+void door_reset()
+{
+       SUB_SETORIGIN(self, self.pos1);
+       self.SUB_VELOCITY = '0 0 0';
+       self.state = STATE_BOTTOM;
+       self.SUB_THINK = func_null;
+       self.SUB_NEXTTHINK = 0;
+
+#ifdef SVQC
+       self.SendFlags |= SF_TRIGGER_RESET;
+#endif
+}
+
+#ifdef SVQC
+
+// spawnflags require key (for now only func_door)
+void spawnfunc_func_door()
+{
+       // Quake 1 keys compatibility
+       if (self.spawnflags & SPAWNFLAGS_GOLD_KEY)
+               self.itemkeys |= ITEM_KEY_BIT(0);
+       if (self.spawnflags & SPAWNFLAGS_SILVER_KEY)
+               self.itemkeys |= ITEM_KEY_BIT(1);
+
+       SetMovedir ();
+
+       self.max_health = self.health;
+       if (!InitMovingBrushTrigger())
+               return;
+       self.effects |= EF_LOWPRECISION;
+       self.classname = "door";
+
+       self.blocked = door_blocked;
+       self.use = door_use;
+
+       if(self.dmg && (self.message == ""))
+               self.message = "was squished";
+       if(self.dmg && (self.message2 == ""))
+               self.message2 = "was squished by";
+
+       if (self.sounds > 0)
+       {
+               precache_sound ("plats/medplat1.wav");
+               precache_sound ("plats/medplat2.wav");
+               self.noise2 = "plats/medplat1.wav";
+               self.noise1 = "plats/medplat2.wav";
+       }
+
+       if (!self.speed)
+               self.speed = 100;
+       if (!self.wait)
+               self.wait = 3;
+       if (!self.lip)
+               self.lip = 8;
+
+       self.pos1 = self.SUB_ORIGIN;
+       self.pos2 = self.pos1 + self.movedir*(fabs(self.movedir*self.size) - self.lip);
+
+// DOOR_START_OPEN is to allow an entity to be lighted in the closed position
+// but spawn in the open position
+       if (self.spawnflags & DOOR_START_OPEN)
+               InitializeEntity(self, door_init_startopen, INITPRIO_SETLOCATION);
+
+       self.state = STATE_BOTTOM;
+
+       if (self.health)
+       {
+               self.takedamage = DAMAGE_YES;
+               self.event_damage = door_damage;
+       }
+
+       if (self.items)
+               self.wait = -1;
+
+       self.touch = door_touch;
+
+// LinkDoors can't be done until all of the doors have been spawned, so
+// the sizes can be detected properly.
+       InitializeEntity(self, LinkDoors, INITPRIO_LINKDOORS);
+
+       self.reset = door_reset;
+}
+
+#elif defined(CSQC)
+
+void door_draw()
+{
+       Movetype_Physics_NoMatchServer();
+
+       trigger_draw_generic();
+}
+
+void ent_door()
+{
+       float sf = ReadByte();
+
+       if(sf & SF_TRIGGER_INIT)
+       {
+               self.classname = strzone(ReadString());
+               self.spawnflags = ReadByte();
+
+               self.mdl = strzone(ReadString());
+               setmodel(self, self.mdl);
+
+               trigger_common_read(true);
+
+               self.pos1_x = ReadCoord();
+               self.pos1_y = ReadCoord();
+               self.pos1_z = ReadCoord();
+               self.pos2_x = ReadCoord();
+               self.pos2_y = ReadCoord();
+               self.pos2_z = ReadCoord();
+
+               self.size_x = ReadCoord();
+               self.size_y = ReadCoord();
+               self.size_z = ReadCoord();
+
+               self.wait = ReadShort();
+               self.speed = ReadShort();
+               self.lip = ReadByte();
+               self.state = ReadByte();
+               self.SUB_LTIME = ReadCoord();
+
+               self.solid = SOLID_BSP;
+               self.movetype = MOVETYPE_PUSH;
+               self.trigger_touch = door_touch;
+               self.draw = door_draw;
+               self.drawmask = MASK_NORMAL;
+               self.use = door_use;
+
+               LinkDoors();
+
+               if(self.spawnflags & DOOR_START_OPEN)
+                       door_init_startopen();
+
+               self.move_time = time;
+               self.move_origin = self.origin;
+               self.move_movetype = MOVETYPE_PUSH;
+               self.move_angles = self.angles;
+               self.move_blocked = door_blocked;
+       }
+
+       if(sf & SF_TRIGGER_RESET)
+       {
+               door_reset();
+       }
+
+       if(sf & SF_TRIGGER_UPDATE)
+       {
+               self.origin_x = ReadCoord();
+               self.origin_y = ReadCoord();
+               self.origin_z = ReadCoord();
+               setorigin(self, self.origin);
+               self.move_origin = self.origin;
+
+               self.pos1_x = ReadCoord();
+               self.pos1_y = ReadCoord();
+               self.pos1_z = ReadCoord();
+               self.pos2_x = ReadCoord();
+               self.pos2_y = ReadCoord();
+               self.pos2_z = ReadCoord();
+       }
+}
+
+#endif
diff --git a/qcsrc/common/triggers/func/door.qh b/qcsrc/common/triggers/func/door.qh
new file mode 100644 (file)
index 0000000..e91061f
--- /dev/null
@@ -0,0 +1,17 @@
+// door constants
+const int DOOR_START_OPEN = 1;
+const int DOOR_DONT_LINK = 4;
+const int DOOR_TOGGLE = 32;
+
+const int DOOR_NOSPLASH = 256; // generic anti-splashdamage spawnflag
+
+const int SPAWNFLAGS_GOLD_KEY = 8;
+const int SPAWNFLAGS_SILVER_KEY = 16;
+
+#ifdef CSQC
+// stuff for preload
+void ent_door();
+
+// abused
+.float attack_finished_single;
+#endif
diff --git a/qcsrc/common/triggers/func/door_rotating.qc b/qcsrc/common/triggers/func/door_rotating.qc
new file mode 100644 (file)
index 0000000..bdf05a0
--- /dev/null
@@ -0,0 +1,126 @@
+#ifdef SVQC
+/*QUAKED spawnfunc_func_door_rotating (0 .5 .8) ? START_OPEN BIDIR DOOR_DONT_LINK BIDIR_IN_DOWN x TOGGLE X_AXIS Y_AXIS
+if two doors touch, they are assumed to be connected and operate as a unit.
+
+TOGGLE causes the door to wait in both the start and end states for a trigger event.
+
+BIDIR makes the door work bidirectional, so that the opening direction is always away from the requestor.
+The usage of bidirectional doors requires two manually instantiated triggers (trigger_multiple), the one to open it in the other direction
+must have set trigger_reverse to 1.
+BIDIR_IN_DOWN will the door prevent from reopening while closing if it is triggered from the other side.
+
+START_OPEN causes the door to move to its destination when spawned, and operate in reverse.  It is used to temporarily or permanently close off an area when triggered (not usefull for touch or takedamage doors).
+
+"message"      is printed when the door is touched if it is a trigger door and it hasn't been fired yet
+"angle"                determines the destination angle for opening. negative values reverse the direction.
+"targetname"    if set, no touch field will be spawned and a remote button or trigger field activates the door.
+"health"       if set, door must be shot open
+"speed"                movement speed (100 default)
+"wait"         wait before returning (3 default, -1 = never return)
+"dmg"          damage to inflict when blocked (2 default)
+"sounds"
+0)     no sound
+1)     stone
+2)     base
+3)     stone chain
+4)     screechy metal
+FIXME: only one sound set available at the time being
+*/
+
+void door_rotating_reset()
+{
+       self.angles = self.pos1;
+       self.avelocity = '0 0 0';
+       self.state = STATE_BOTTOM;
+       self.think = func_null;
+       self.nextthink = 0;
+}
+
+void door_rotating_init_startopen()
+{
+       self.angles = self.movedir;
+       self.pos2 = '0 0 0';
+       self.pos1 = self.movedir;
+}
+
+
+void spawnfunc_func_door_rotating()
+{
+
+       //if (!self.deathtype) // map makers can override this
+       //      self.deathtype = " got in the way";
+
+       // I abuse "movedir" for denoting the axis for now
+       if (self.spawnflags & 64) // X (untested)
+               self.movedir = '0 0 1';
+       else if (self.spawnflags & 128) // Y (untested)
+               self.movedir = '1 0 0';
+       else // Z
+               self.movedir = '0 1 0';
+
+       if (self.angles_y==0) self.angles_y = 90;
+
+       self.movedir = self.movedir * self.angles_y;
+       self.angles = '0 0 0';
+
+       self.max_health = self.health;
+       self.avelocity = self.movedir;
+       if (!InitMovingBrushTrigger())
+               return;
+       self.velocity = '0 0 0';
+       //self.effects |= EF_LOWPRECISION;
+       self.classname = "door_rotating";
+
+       self.blocked = door_blocked;
+       self.use = door_use;
+
+    if(self.spawnflags & 8)
+        self.dmg = 10000;
+
+    if(self.dmg && (self.message == ""))
+               self.message = "was squished";
+    if(self.dmg && (self.message2 == ""))
+               self.message2 = "was squished by";
+
+    if (self.sounds > 0)
+       {
+               precache_sound ("plats/medplat1.wav");
+               precache_sound ("plats/medplat2.wav");
+               self.noise2 = "plats/medplat1.wav";
+               self.noise1 = "plats/medplat2.wav";
+       }
+
+       if (!self.speed)
+               self.speed = 50;
+       if (!self.wait)
+               self.wait = 1;
+       self.lip = 0; // self.lip is used to remember reverse opening direction for door_rotating
+
+       self.pos1 = '0 0 0';
+       self.pos2 = self.movedir;
+
+// DOOR_START_OPEN is to allow an entity to be lighted in the closed position
+// but spawn in the open position
+       if (self.spawnflags & DOOR_START_OPEN)
+               InitializeEntity(self, door_rotating_init_startopen, INITPRIO_SETLOCATION);
+
+       self.state = STATE_BOTTOM;
+
+       if (self.health)
+       {
+               self.takedamage = DAMAGE_YES;
+               self.event_damage = door_damage;
+       }
+
+       if (self.items)
+               self.wait = -1;
+
+       self.touch = door_touch;
+
+// LinkDoors can't be done until all of the doors have been spawned, so
+// the sizes can be detected properly.
+       InitializeEntity(self, LinkDoors, INITPRIO_LINKDOORS);
+
+       self.reset = door_rotating_reset;
+}
+#endif
diff --git a/qcsrc/common/triggers/func/door_secret.qc b/qcsrc/common/triggers/func/door_secret.qc
new file mode 100644 (file)
index 0000000..a0a44bb
--- /dev/null
@@ -0,0 +1,236 @@
+#ifdef SVQC
+void() fd_secret_move1;
+void() fd_secret_move2;
+void() fd_secret_move3;
+void() fd_secret_move4;
+void() fd_secret_move5;
+void() fd_secret_move6;
+void() fd_secret_done;
+
+const float SECRET_OPEN_ONCE = 1;              // stays open
+const float SECRET_1ST_LEFT = 2;               // 1st move is left of arrow
+const float SECRET_1ST_DOWN = 4;               // 1st move is down from arrow
+const float SECRET_NO_SHOOT = 8;               // only opened by trigger
+const float SECRET_YES_SHOOT = 16;     // shootable even if targeted
+
+void fd_secret_use()
+{
+       float temp;
+       string message_save;
+
+       self.health = 10000;
+       self.bot_attack = true;
+
+       // exit if still moving around...
+       if (self.origin != self.oldorigin)
+               return;
+
+       message_save = self.message;
+       self.message = ""; // no more message
+       SUB_UseTargets();                               // fire all targets / killtargets
+       self.message = message_save;
+
+       self.velocity = '0 0 0';
+
+       // Make a sound, wait a little...
+
+       if (self.noise1 != "")
+               sound(self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTEN_NORM);
+       self.SUB_NEXTTHINK = self.SUB_LTIME + 0.1;
+
+       temp = 1 - (self.spawnflags & SECRET_1ST_LEFT); // 1 or -1
+       makevectors(self.mangle);
+
+       if (!self.t_width)
+       {
+               if (self.spawnflags & SECRET_1ST_DOWN)
+                       self.t_width = fabs(v_up * self.size);
+               else
+                       self.t_width = fabs(v_right * self.size);
+       }
+
+       if (!self.t_length)
+               self.t_length = fabs(v_forward * self.size);
+
+       if (self.spawnflags & SECRET_1ST_DOWN)
+               self.dest1 = self.origin - v_up * self.t_width;
+       else
+               self.dest1 = self.origin + v_right * (self.t_width * temp);
+
+       self.dest2 = self.dest1 + v_forward * self.t_length;
+       SUB_CalcMove(self.dest1, TSPEED_LINEAR, self.speed, fd_secret_move1);
+       if (self.noise2 != "")
+               sound(self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTEN_NORM);
+}
+
+void fd_secret_damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
+{
+       fd_secret_use();
+}
+
+// Wait after first movement...
+void fd_secret_move1()
+{
+       self.SUB_NEXTTHINK = self.SUB_LTIME + 1.0;
+       self.think = fd_secret_move2;
+       if (self.noise3 != "")
+               sound(self, CH_TRIGGER_SINGLE, self.noise3, VOL_BASE, ATTEN_NORM);
+}
+
+// Start moving sideways w/sound...
+void fd_secret_move2()
+{
+       if (self.noise2 != "")
+               sound(self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTEN_NORM);
+       SUB_CalcMove(self.dest2, TSPEED_LINEAR, self.speed, fd_secret_move3);
+}
+
+// Wait here until time to go back...
+void fd_secret_move3()
+{
+       if (self.noise3 != "")
+               sound(self, CH_TRIGGER_SINGLE, self.noise3, VOL_BASE, ATTEN_NORM);
+       if (!(self.spawnflags & SECRET_OPEN_ONCE))
+       {
+               self.SUB_NEXTTHINK = self.SUB_LTIME + self.wait;
+               self.think = fd_secret_move4;
+       }
+}
+
+// Move backward...
+void fd_secret_move4()
+{
+       if (self.noise2 != "")
+               sound(self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTEN_NORM);
+       SUB_CalcMove(self.dest1, TSPEED_LINEAR, self.speed, fd_secret_move5);
+}
+
+// Wait 1 second...
+void fd_secret_move5()
+{
+       self.SUB_NEXTTHINK = self.SUB_LTIME + 1.0;
+       self.think = fd_secret_move6;
+       if (self.noise3 != "")
+               sound(self, CH_TRIGGER_SINGLE, self.noise3, VOL_BASE, ATTEN_NORM);
+}
+
+void fd_secret_move6()
+{
+       if (self.noise2 != "")
+               sound(self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTEN_NORM);
+       SUB_CalcMove(self.oldorigin, TSPEED_LINEAR, self.speed, fd_secret_done);
+}
+
+void fd_secret_done()
+{
+       if (self.spawnflags&SECRET_YES_SHOOT)
+       {
+               self.health = 10000;
+               self.takedamage = DAMAGE_YES;
+               //self.th_pain = fd_secret_use;
+       }
+       if (self.noise3 != "")
+               sound(self, CH_TRIGGER_SINGLE, self.noise3, VOL_BASE, ATTEN_NORM);
+}
+
+void secret_blocked()
+{
+       if (time < self.attack_finished_single)
+               return;
+       self.attack_finished_single = time + 0.5;
+       //T_Damage (other, self, self, self.dmg, self.dmg, self.deathtype, DT_IMPACT, (self.absmin + self.absmax) * 0.5, '0 0 0', Obituary_Generic);
+}
+
+/*
+==============
+secret_touch
+
+Prints messages
+================
+*/
+void secret_touch()
+{
+       if (!other.iscreature)
+               return;
+       if (self.attack_finished_single > time)
+               return;
+
+       self.attack_finished_single = time + 2;
+
+       if (self.message)
+       {
+               if (IS_CLIENT(other))
+                       centerprint(other, self.message);
+               play2(other, "misc/talk.wav");
+       }
+}
+
+void secret_reset()
+{
+       if (self.spawnflags&SECRET_YES_SHOOT)
+       {
+               self.health = 10000;
+               self.takedamage = DAMAGE_YES;
+       }
+       setorigin(self, self.oldorigin);
+       self.think = func_null;
+       self.SUB_NEXTTHINK = 0;
+}
+
+/*QUAKED spawnfunc_func_door_secret (0 .5 .8) ? open_once 1st_left 1st_down no_shoot always_shoot
+Basic secret door. Slides back, then to the side. Angle determines direction.
+wait  = # of seconds before coming back
+1st_left = 1st move is left of arrow
+1st_down = 1st move is down from arrow
+always_shoot = even if targeted, keep shootable
+t_width = override WIDTH to move back (or height if going down)
+t_length = override LENGTH to move sideways
+"dmg"          damage to inflict when blocked (2 default)
+
+If a secret door has a targetname, it will only be opened by it's botton or trigger, not by damage.
+"sounds"
+1) medieval
+2) metal
+3) base
+*/
+
+void spawnfunc_func_door_secret()
+{
+       /*if (!self.deathtype) // map makers can override this
+               self.deathtype = " got in the way";*/
+
+       if (!self.dmg)
+               self.dmg = 2;
+
+       // Magic formula...
+       self.mangle = self.angles;
+       self.angles = '0 0 0';
+       self.classname = "door";
+       if (!InitMovingBrushTrigger())
+               return;
+       self.effects |= EF_LOWPRECISION;
+
+       self.touch = secret_touch;
+       self.blocked = secret_blocked;
+       self.speed = 50;
+       self.use = fd_secret_use;
+       IFTARGETED
+       {
+       }
+       else
+               self.spawnflags |= SECRET_YES_SHOOT;
+
+       if(self.spawnflags&SECRET_YES_SHOOT)
+       {
+               self.health = 10000;
+               self.takedamage = DAMAGE_YES;
+               self.event_damage = fd_secret_damage;
+       }
+       self.oldorigin = self.origin;
+       if (!self.wait)
+               self.wait = 5;          // 5 seconds before closing
+
+       self.reset = secret_reset;
+       secret_reset();
+}
+#endif
diff --git a/qcsrc/common/triggers/func/fourier.qc b/qcsrc/common/triggers/func/fourier.qc
new file mode 100644 (file)
index 0000000..19dceef
--- /dev/null
@@ -0,0 +1,89 @@
+#ifdef SVQC
+/*QUAKED spawnfunc_func_fourier (0 .5 .8) ?
+Brush model that moves in a pattern of added up sine waves, can be used e.g. for circular motions.
+netname: list of <frequencymultiplier> <phase> <x> <y> <z> quadruples, separated by spaces; note that phase 0 represents a sine wave, and phase 0.25 a cosine wave (by default, it uses 1 0 0 0 1, to match func_bobbing's defaults
+speed: how long one cycle of frequency multiplier 1 in seconds (default 4)
+height: amplitude modifier (default 32)
+phase: cycle timing adjustment (0-1 as a fraction of the cycle, default 0)
+noise: path/name of looping .wav file to play.
+dmg: Do this mutch dmg every .dmgtime intervall when blocked
+dmgtime: See above.
+*/
+
+void func_fourier_controller_think()
+{
+       vector v;
+       float n, i, t;
+
+       self.nextthink = time + 0.1;
+       if(self.owner.active != ACTIVE_ACTIVE)
+       {
+               self.owner.velocity = '0 0 0';
+               return;
+       }
+
+
+       n = floor((tokenize_console(self.owner.netname)) / 5);
+       t = self.nextthink * self.owner.cnt + self.owner.phase * 360;
+
+       v = self.owner.destvec;
+
+       for(i = 0; i < n; ++i)
+       {
+               makevectors((t * stof(argv(i*5)) + stof(argv(i*5+1)) * 360) * '0 1 0');
+               v = v + ('1 0 0' * stof(argv(i*5+2)) + '0 1 0' * stof(argv(i*5+3)) + '0 0 1' * stof(argv(i*5+4))) * self.owner.height * v_forward_y;
+       }
+
+       if(self.owner.classname == "func_fourier") // don't brake stuff if the func_fourier was killtarget'ed
+               // * 10 so it will arrive in 0.1 sec
+               self.owner.velocity = (v - self.owner.origin) * 10;
+}
+
+void spawnfunc_func_fourier()
+{
+       entity controller;
+       if (self.noise != "")
+       {
+               precache_sound(self.noise);
+               soundto(MSG_INIT, self, CH_TRIGGER_SINGLE, self.noise, VOL_BASE, ATTEN_IDLE);
+       }
+
+       if (!self.speed)
+               self.speed = 4;
+       if (!self.height)
+               self.height = 32;
+       self.destvec = self.origin;
+       self.cnt = 360 / self.speed;
+
+       self.blocked = generic_plat_blocked;
+       if(self.dmg && (self.message == ""))
+               self.message = " was squished";
+    if(self.dmg && (self.message2 == ""))
+               self.message2 = "was squished by";
+       if(self.dmg && (!self.dmgtime))
+               self.dmgtime = 0.25;
+       self.dmgtime2 = time;
+
+       if(self.netname == "")
+               self.netname = "1 0 0 0 1";
+
+       if (!InitMovingBrushTrigger())
+               return;
+
+       self.active = ACTIVE_ACTIVE;
+
+       // wait for targets to spawn
+       controller = spawn();
+       controller.classname = "func_fourier_controller";
+       controller.owner = self;
+       controller.nextthink = time + 1;
+       controller.think = func_fourier_controller_think;
+       self.SUB_NEXTTHINK = self.SUB_LTIME + 999999999;
+       self.SUB_THINK = SUB_NullThink; // for PushMove
+
+       // Savage: Reduce bandwith, critical on e.g. nexdm02
+       self.effects |= EF_LOWPRECISION;
+
+       // TODO make a reset function for this one
+}
+#endif
diff --git a/qcsrc/common/triggers/func/include.qc b/qcsrc/common/triggers/func/include.qc
new file mode 100644 (file)
index 0000000..290c2e9
--- /dev/null
@@ -0,0 +1,19 @@
+#include "include.qh"
+
+#include "bobbing.qc"
+#include "breakable.qc"
+#include "button.qc"
+#include "conveyor.qc"
+#include "door.qc"
+#include "door_rotating.qc"
+#include "door_secret.qc"
+#include "fourier.qc"
+#include "ladder.qc"
+#include "pendulum.qc"
+#include "plat.qc"
+#include "pointparticles.qc"
+#include "rainsnow.qc"
+#include "rotating.qc"
+#include "stardust.qc"
+#include "train.qc"
+#include "vectormamamam.qc"
diff --git a/qcsrc/common/triggers/func/include.qh b/qcsrc/common/triggers/func/include.qh
new file mode 100644 (file)
index 0000000..624c0b5
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef TRIGGERS_FUNC_INCLUDE_H
+#define TRIGGERS_FUNC_INCLUDE_H
+
+#include "conveyor.qh"
+#include "door.qh"
+#include "ladder.qh"
+#include "plat.qh"
+#include "rainsnow.qh"
+#include "pointparticles.qh"
+#include "train.qh"
+
+#endif
diff --git a/qcsrc/common/triggers/func/ladder.qc b/qcsrc/common/triggers/func/ladder.qc
new file mode 100644 (file)
index 0000000..f0216cc
--- /dev/null
@@ -0,0 +1,83 @@
+void func_ladder_touch()
+{
+#ifdef SVQC
+       if (!other.iscreature)
+               return;
+       if (other.vehicle_flags & VHF_ISVEHICLE)
+               return;
+#endif
+#ifdef CSQC
+       if(other.classname != "csqcmodel")
+               return;
+#endif
+
+       EXACTTRIGGER_TOUCH;
+
+       other.ladder_time = time + 0.1;
+       other.ladder_entity = self;
+}
+
+#ifdef SVQC
+float func_ladder_send(entity to, float sf)
+{
+       WriteByte(MSG_ENTITY, ENT_CLIENT_LADDER);
+
+       WriteString(MSG_ENTITY, self.classname);
+       WriteByte(MSG_ENTITY, self.skin);
+       WriteByte(MSG_ENTITY, self.speed);
+       WriteString(MSG_ENTITY, self.mdl);
+
+       trigger_common_write(false);
+
+       return true;
+}
+
+void func_ladder_link()
+{
+       //self.SendEntity = func_ladder_send;
+       //self.SendFlags = 0xFFFFFF;
+       //self.model = "null";
+}
+
+void spawnfunc_func_ladder()
+{
+       self.mdl = self.model;
+       EXACTTRIGGER_INIT;
+       self.touch = func_ladder_touch;
+
+       func_ladder_link();
+}
+
+void spawnfunc_func_water()
+{
+       self.mdl = self.model;
+       EXACTTRIGGER_INIT;
+       self.touch = func_ladder_touch;
+
+       func_ladder_link();
+}
+
+#elif defined(CSQC)
+.float speed;
+
+void ent_func_ladder()
+{
+       self.classname = strzone(ReadString());
+       self.skin = ReadByte();
+       self.speed = ReadByte();
+       self.model = strzone(ReadString());
+
+       trigger_common_read(false);
+       self.mins = self.maxs = '0 0 0';
+
+       self.solid = SOLID_TRIGGER;
+       self.draw = trigger_draw_generic;
+       self.trigger_touch = func_ladder_touch;
+       self.drawmask = MASK_NORMAL;
+       self.move_time = time;
+       self.entremove = trigger_remove_generic;
+
+       //precache_model(self.mdl);
+       EXACTTRIGGER_INIT;
+}
+#endif
diff --git a/qcsrc/common/triggers/func/ladder.qh b/qcsrc/common/triggers/func/ladder.qh
new file mode 100644 (file)
index 0000000..11eeeda
--- /dev/null
@@ -0,0 +1,6 @@
+.float ladder_time;
+.entity ladder_entity;
+
+#ifdef CSQC
+void ent_func_ladder();
+#endif
diff --git a/qcsrc/common/triggers/func/pendulum.qc b/qcsrc/common/triggers/func/pendulum.qc
new file mode 100644 (file)
index 0000000..7d3eff7
--- /dev/null
@@ -0,0 +1,77 @@
+#ifdef SVQC
+.float freq;
+void func_pendulum_controller_think()
+{
+       float v;
+       self.nextthink = time + 0.1;
+
+       if (!(self.owner.active == ACTIVE_ACTIVE))
+       {
+               self.owner.avelocity_x = 0;
+               return;
+       }
+
+       // calculate sinewave using makevectors
+       makevectors((self.nextthink * self.owner.freq + self.owner.phase) * '0 360 0');
+       v = self.owner.speed * v_forward_y + self.cnt;
+       if(self.owner.classname == "func_pendulum") // don't brake stuff if the func_bobbing was killtarget'ed
+       {
+               // * 10 so it will arrive in 0.1 sec
+               self.owner.avelocity_z = (remainder(v - self.owner.angles_z, 360)) * 10;
+       }
+}
+
+void spawnfunc_func_pendulum()
+{
+       entity controller;
+       if (self.noise != "")
+       {
+               precache_sound(self.noise);
+               soundto(MSG_INIT, self, CH_TRIGGER_SINGLE, self.noise, VOL_BASE, ATTEN_IDLE);
+       }
+
+       self.active = ACTIVE_ACTIVE;
+
+       // keys: angle, speed, phase, noise, freq
+
+       if(!self.speed)
+               self.speed = 30;
+       // not initializing self.dmg to 2, to allow damageless pendulum
+
+       if(self.dmg && (self.message == ""))
+               self.message = " was squished";
+       if(self.dmg && (self.message2 == ""))
+               self.message2 = "was squished by";
+       if(self.dmg && (!self.dmgtime))
+               self.dmgtime = 0.25;
+       self.dmgtime2 = time;
+
+       self.blocked = generic_plat_blocked;
+
+       self.avelocity_z = 0.0000001;
+       if (!InitMovingBrushTrigger())
+               return;
+
+       if(!self.freq)
+       {
+               // find pendulum length (same formula as Q3A)
+               self.freq = 1 / (M_PI * 2) * sqrt(autocvar_sv_gravity / (3 * max(8, fabs(self.mins_z))));
+       }
+
+       // copy initial angle
+       self.cnt = self.angles_z;
+
+       // wait for targets to spawn
+       controller = spawn();
+       controller.classname = "func_pendulum_controller";
+       controller.owner = self;
+       controller.nextthink = time + 1;
+       controller.think = func_pendulum_controller_think;
+       self.nextthink = self.SUB_LTIME + 999999999;
+       self.SUB_THINK = SUB_NullThink; // for PushMove
+
+       //self.effects |= EF_LOWPRECISION;
+
+       // TODO make a reset function for this one
+}
+#endif
diff --git a/qcsrc/common/triggers/func/plat.qc b/qcsrc/common/triggers/func/plat.qc
new file mode 100644 (file)
index 0000000..d36b1c6
--- /dev/null
@@ -0,0 +1,201 @@
+#ifdef SVQC
+void plat_link();
+
+void plat_delayedinit()
+{
+       plat_link();
+       plat_spawn_inside_trigger(); // the "start moving" trigger
+}
+
+float plat_send(entity to, float sf)
+{
+       WriteByte(MSG_ENTITY, ENT_CLIENT_PLAT);
+       WriteByte(MSG_ENTITY, sf);
+
+       if(sf & SF_TRIGGER_INIT)
+       {
+               WriteByte(MSG_ENTITY, self.platmovetype_start);
+               WriteByte(MSG_ENTITY, self.platmovetype_turn);
+               WriteByte(MSG_ENTITY, self.platmovetype_end);
+               WriteByte(MSG_ENTITY, self.spawnflags);
+
+               WriteString(MSG_ENTITY, self.model);
+
+               trigger_common_write(true);
+
+               WriteCoord(MSG_ENTITY, self.pos1_x);
+               WriteCoord(MSG_ENTITY, self.pos1_y);
+               WriteCoord(MSG_ENTITY, self.pos1_z);
+               WriteCoord(MSG_ENTITY, self.pos2_x);
+               WriteCoord(MSG_ENTITY, self.pos2_y);
+               WriteCoord(MSG_ENTITY, self.pos2_z);
+
+               WriteCoord(MSG_ENTITY, self.size_x);
+               WriteCoord(MSG_ENTITY, self.size_y);
+               WriteCoord(MSG_ENTITY, self.size_z);
+
+               WriteAngle(MSG_ENTITY, self.mangle_x);
+               WriteAngle(MSG_ENTITY, self.mangle_y);
+               WriteAngle(MSG_ENTITY, self.mangle_z);
+
+               WriteShort(MSG_ENTITY, self.speed);
+               WriteShort(MSG_ENTITY, self.height);
+               WriteByte(MSG_ENTITY, self.lip);
+               WriteByte(MSG_ENTITY, self.state);
+
+               WriteShort(MSG_ENTITY, self.dmg);
+       }
+
+       if(sf & SF_TRIGGER_RESET)
+       {
+               // used on client
+       }
+
+       return true;
+}
+
+void plat_link()
+{
+       //Net_LinkEntity(self, 0, false, plat_send);
+}
+
+void spawnfunc_func_plat()
+{
+       if (self.sounds == 0)
+               self.sounds = 2;
+
+    if(self.spawnflags & 4)
+        self.dmg = 10000;
+
+    if(self.dmg && (self.message == ""))
+               self.message = "was squished";
+    if(self.dmg && (self.message2 == ""))
+               self.message2 = "was squished by";
+
+       if (self.sounds == 1)
+       {
+               precache_sound ("plats/plat1.wav");
+               precache_sound ("plats/plat2.wav");
+               self.noise = "plats/plat1.wav";
+               self.noise1 = "plats/plat2.wav";
+       }
+
+       if (self.sounds == 2)
+       {
+               precache_sound ("plats/medplat1.wav");
+               precache_sound ("plats/medplat2.wav");
+               self.noise = "plats/medplat1.wav";
+               self.noise1 = "plats/medplat2.wav";
+       }
+
+       if (self.sound1)
+       {
+               precache_sound (self.sound1);
+               self.noise = self.sound1;
+       }
+       if (self.sound2)
+       {
+               precache_sound (self.sound2);
+               self.noise1 = self.sound2;
+       }
+
+       self.mangle = self.angles;
+       self.angles = '0 0 0';
+
+       self.classname = "plat";
+       if (!InitMovingBrushTrigger())
+               return;
+       self.effects |= EF_LOWPRECISION;
+       setsize (self, self.mins , self.maxs);
+
+       self.blocked = plat_crush;
+
+       if (!self.speed)
+               self.speed = 150;
+       if (!self.lip)
+               self.lip = 16;
+       if (!self.height)
+               self.height = self.size_z - self.lip;
+
+       self.pos1 = self.origin;
+       self.pos2 = self.origin;
+       self.pos2_z = self.origin_z - self.height;
+
+       self.reset = plat_reset;
+       plat_reset();
+
+       InitializeEntity(self, plat_delayedinit, INITPRIO_FINDTARGET);
+}
+#elif defined(CSQC)
+void plat_draw()
+{
+       Movetype_Physics_NoMatchServer();
+       //Movetype_Physics_MatchServer(autocvar_cl_projectiles_sloppy);
+}
+
+void ent_plat()
+{
+       float sf = ReadByte();
+
+       if(sf & SF_TRIGGER_INIT)
+       {
+               self.platmovetype_start = ReadByte();
+               self.platmovetype_turn = ReadByte();
+               self.platmovetype_end = ReadByte();
+               self.spawnflags = ReadByte();
+
+               self.model = strzone(ReadString());
+               setmodel(self, self.model);
+
+               trigger_common_read(true);
+
+               self.pos1_x = ReadCoord();
+               self.pos1_y = ReadCoord();
+               self.pos1_z = ReadCoord();
+               self.pos2_x = ReadCoord();
+               self.pos2_y = ReadCoord();
+               self.pos2_z = ReadCoord();
+
+               self.size_x = ReadCoord();
+               self.size_y = ReadCoord();
+               self.size_z = ReadCoord();
+
+               self.mangle_x = ReadAngle();
+               self.mangle_y = ReadAngle();
+               self.mangle_z = ReadAngle();
+
+               self.speed = ReadShort();
+               self.height = ReadShort();
+               self.lip = ReadByte();
+               self.state = ReadByte();
+
+               self.dmg = ReadShort();
+
+               self.classname = "plat";
+               self.solid = SOLID_BSP;
+               self.movetype = MOVETYPE_PUSH;
+               self.drawmask = MASK_NORMAL;
+               self.draw = plat_draw;
+               self.use = plat_use;
+               self.entremove = trigger_remove_generic;
+
+               plat_reset(); // also called here
+
+               self.move_movetype = MOVETYPE_PUSH;
+               self.move_origin = self.origin;
+               self.move_angles = self.angles;
+               self.move_time = time;
+
+               plat_spawn_inside_trigger();
+       }
+
+       if(sf & SF_TRIGGER_RESET)
+       {
+               plat_reset();
+
+               self.move_origin = self.origin;
+               self.move_angles = self.angles;
+               self.move_time = time;
+       }
+}
+#endif
diff --git a/qcsrc/common/triggers/func/plat.qh b/qcsrc/common/triggers/func/plat.qh
new file mode 100644 (file)
index 0000000..e3562f4
--- /dev/null
@@ -0,0 +1,3 @@
+#ifdef CSQC
+void ent_plat();
+#endif
diff --git a/qcsrc/common/triggers/func/pointparticles.qc b/qcsrc/common/triggers/func/pointparticles.qc
new file mode 100644 (file)
index 0000000..9b32371
--- /dev/null
@@ -0,0 +1,362 @@
+#ifdef CSQC
+       #include "../../../client/particles.qh"
+#endif
+
+#ifdef SVQC
+// NOTE: also contains func_sparks
+
+float pointparticles_SendEntity(entity to, float fl)
+{
+       WriteByte(MSG_ENTITY, ENT_CLIENT_POINTPARTICLES);
+
+       // optional features to save space
+       fl = fl & 0x0F;
+       if(self.spawnflags & 2)
+               fl |= 0x10; // absolute count on toggle-on
+       if(self.movedir != '0 0 0' || self.velocity != '0 0 0')
+               fl |= 0x20; // 4 bytes - saves CPU
+       if(self.waterlevel || self.count != 1)
+               fl |= 0x40; // 4 bytes - obscure features almost never used
+       if(self.mins != '0 0 0' || self.maxs != '0 0 0')
+               fl |= 0x80; // 14 bytes - saves lots of space
+
+       WriteByte(MSG_ENTITY, fl);
+       if(fl & 2)
+       {
+               if(self.state)
+                       WriteCoord(MSG_ENTITY, self.impulse);
+               else
+                       WriteCoord(MSG_ENTITY, 0); // off
+       }
+       if(fl & 4)
+       {
+               WriteCoord(MSG_ENTITY, self.origin_x);
+               WriteCoord(MSG_ENTITY, self.origin_y);
+               WriteCoord(MSG_ENTITY, self.origin_z);
+       }
+       if(fl & 1)
+       {
+               if(self.model != "null")
+               {
+                       WriteShort(MSG_ENTITY, self.modelindex);
+                       if(fl & 0x80)
+                       {
+                               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);
+                       }
+               }
+               else
+               {
+                       WriteShort(MSG_ENTITY, 0);
+                       if(fl & 0x80)
+                       {
+                               WriteCoord(MSG_ENTITY, self.maxs_x);
+                               WriteCoord(MSG_ENTITY, self.maxs_y);
+                               WriteCoord(MSG_ENTITY, self.maxs_z);
+                       }
+               }
+               WriteShort(MSG_ENTITY, self.cnt);
+               if(fl & 0x20)
+               {
+                       WriteShort(MSG_ENTITY, compressShortVector(self.velocity));
+                       WriteShort(MSG_ENTITY, compressShortVector(self.movedir));
+               }
+               if(fl & 0x40)
+               {
+                       WriteShort(MSG_ENTITY, self.waterlevel * 16.0);
+                       WriteByte(MSG_ENTITY, self.count * 16.0);
+               }
+               WriteString(MSG_ENTITY, self.noise);
+               if(self.noise != "")
+               {
+                       WriteByte(MSG_ENTITY, floor(self.atten * 64));
+                       WriteByte(MSG_ENTITY, floor(self.volume * 255));
+               }
+               WriteString(MSG_ENTITY, self.bgmscript);
+               if(self.bgmscript != "")
+               {
+                       WriteByte(MSG_ENTITY, floor(self.bgmscriptattack * 64));
+                       WriteByte(MSG_ENTITY, floor(self.bgmscriptdecay * 64));
+                       WriteByte(MSG_ENTITY, floor(self.bgmscriptsustain * 255));
+                       WriteByte(MSG_ENTITY, floor(self.bgmscriptrelease * 64));
+               }
+       }
+       return 1;
+}
+
+void pointparticles_use()
+{
+       self.state = !self.state;
+       self.SendFlags |= 2;
+}
+
+void pointparticles_think()
+{
+       if(self.origin != self.oldorigin)
+       {
+               self.SendFlags |= 4;
+               self.oldorigin = self.origin;
+       }
+       self.nextthink = time;
+}
+
+void pointparticles_reset()
+{
+       if(self.spawnflags & 1)
+               self.state = 1;
+       else
+               self.state = 0;
+}
+
+void spawnfunc_func_pointparticles()
+{
+       if(self.model != "")
+               setmodel(self, self.model);
+       if(self.noise != "")
+               precache_sound (self.noise);
+
+       if(!self.bgmscriptsustain)
+               self.bgmscriptsustain = 1;
+       else if(self.bgmscriptsustain < 0)
+               self.bgmscriptsustain = 0;
+
+       if(!self.atten)
+               self.atten = ATTEN_NORM;
+       else if(self.atten < 0)
+               self.atten = 0;
+       if(!self.volume)
+               self.volume = 1;
+       if(!self.count)
+               self.count = 1;
+       if(!self.impulse)
+               self.impulse = 1;
+
+       if(!self.modelindex)
+       {
+               setorigin(self, self.origin + self.mins);
+               setsize(self, '0 0 0', self.maxs - self.mins);
+       }
+       if(!self.cnt)
+               self.cnt = particleeffectnum(self.mdl);
+
+       Net_LinkEntity(self, (self.spawnflags & 4), 0, pointparticles_SendEntity);
+
+       IFTARGETED
+       {
+               self.use = pointparticles_use;
+               self.reset = pointparticles_reset;
+               self.reset();
+       }
+       else
+               self.state = 1;
+       self.think = pointparticles_think;
+       self.nextthink = time;
+}
+
+void spawnfunc_func_sparks()
+{
+       // self.cnt is the amount of sparks that one burst will spawn
+       if(self.cnt < 1) {
+               self.cnt = 25.0; // nice default value
+       }
+
+       // self.wait is the probability that a sparkthink will spawn a spark shower
+       // range: 0 - 1, but 0 makes little sense, so...
+       if(self.wait < 0.05) {
+               self.wait = 0.25; // nice default value
+       }
+
+       self.count = self.cnt;
+       self.mins = '0 0 0';
+       self.maxs = '0 0 0';
+       self.velocity = '0 0 -1';
+       self.mdl = "TE_SPARK";
+       self.impulse = 10 * self.wait; // by default 2.5/sec
+       self.wait = 0;
+       self.cnt = 0; // use mdl
+
+       spawnfunc_func_pointparticles();
+}
+#elif defined(CSQC)
+
+void Draw_PointParticles()
+{
+       float n, i, fail;
+       vector p;
+       vector sz;
+       vector o;
+       o = self.origin;
+       sz = self.maxs - self.mins;
+       n = doBGMScript(self);
+       if(self.absolute == 2)
+       {
+               if(n >= 0)
+                       n = self.just_toggled ? self.impulse : 0;
+               else
+                       n = self.impulse * drawframetime;
+       }
+       else
+       {
+               n *= self.impulse * drawframetime;
+               if(self.just_toggled)
+                       if(n < 1)
+                               n = 1;
+       }
+       if(n == 0)
+               return;
+       fail = 0;
+       for(i = random(); i <= n && fail <= 64*n; ++i)
+       {
+               p = o + self.mins;
+               p.x += random() * sz.x;
+               p.y += random() * sz.y;
+               p.z += random() * sz.z;
+               if(WarpZoneLib_BoxTouchesBrush(p, p, self, world))
+               {
+                       if(self.movedir != '0 0 0')
+                       {
+                               traceline(p, p + normalize(self.movedir) * 4096, 0, world);
+                               p = trace_endpos;
+                               pointparticles(self.cnt, p, trace_plane_normal * vlen(self.movedir) + self.velocity + randomvec() * self.waterlevel, self.count);
+                       }
+                       else
+                       {
+                               pointparticles(self.cnt, p, self.velocity + randomvec() * self.waterlevel, self.count);
+                       }
+                       if(self.noise != "")
+                       {
+                               setorigin(self, p);
+                               sound(self, CH_AMBIENT, self.noise, VOL_BASE * self.volume, self.atten);
+                       }
+                       self.just_toggled = 0;
+               }
+               else if(self.absolute)
+               {
+                       ++fail;
+                       --i;
+               }
+       }
+       setorigin(self, o);
+}
+
+void Ent_PointParticles_Remove()
+{
+       if(self.noise)
+               strunzone(self.noise);
+       self.noise = string_null;
+       if(self.bgmscript)
+               strunzone(self.bgmscript);
+       self.bgmscript = string_null;
+}
+
+void Ent_PointParticles()
+{
+       float i;
+       vector v;
+       int f = ReadByte();
+       if(f & 2)
+       {
+               i = ReadCoord(); // density (<0: point, >0: volume)
+               if(i && !self.impulse && self.cnt) // self.cnt check is so it only happens if the ent already existed
+                       self.just_toggled = 1;
+               self.impulse = i;
+       }
+       if(f & 4)
+       {
+               self.origin_x = ReadCoord();
+               self.origin_y = ReadCoord();
+               self.origin_z = ReadCoord();
+       }
+       if(f & 1)
+       {
+               self.modelindex = ReadShort();
+               if(f & 0x80)
+               {
+                       if(self.modelindex)
+                       {
+                               self.mins_x = ReadCoord();
+                               self.mins_y = ReadCoord();
+                               self.mins_z = ReadCoord();
+                               self.maxs_x = ReadCoord();
+                               self.maxs_y = ReadCoord();
+                               self.maxs_z = ReadCoord();
+                       }
+                       else
+                       {
+                               self.mins    = '0 0 0';
+                               self.maxs_x = ReadCoord();
+                               self.maxs_y = ReadCoord();
+                               self.maxs_z = ReadCoord();
+                       }
+               }
+               else
+               {
+                       self.mins = self.maxs = '0 0 0';
+               }
+
+               self.cnt = ReadShort(); // effect number
+
+               if(f & 0x20)
+               {
+                       self.velocity = decompressShortVector(ReadShort());
+                       self.movedir = decompressShortVector(ReadShort());
+               }
+               else
+               {
+                       self.velocity = self.movedir = '0 0 0';
+               }
+               if(f & 0x40)
+               {
+                       self.waterlevel = ReadShort() / 16.0;
+                       self.count = ReadByte() / 16.0;
+               }
+               else
+               {
+                       self.waterlevel = 0;
+                       self.count = 1;
+               }
+               if(self.noise)
+                       strunzone(self.noise);
+               if(self.bgmscript)
+                       strunzone(self.bgmscript);
+               self.noise = strzone(ReadString());
+               if(self.noise != "")
+               {
+                       self.atten = ReadByte() / 64.0;
+                       self.volume = ReadByte() / 255.0;
+               }
+               self.bgmscript = strzone(ReadString());
+               if(self.bgmscript != "")
+               {
+                       self.bgmscriptattack = ReadByte() / 64.0;
+                       self.bgmscriptdecay = ReadByte() / 64.0;
+                       self.bgmscriptsustain = ReadByte() / 255.0;
+                       self.bgmscriptrelease = ReadByte() / 64.0;
+               }
+               BGMScript_InitEntity(self);
+       }
+
+       if(f & 2)
+       {
+               self.absolute = (self.impulse >= 0);
+               if(!self.absolute)
+               {
+                       v = self.maxs - self.mins;
+                       self.impulse *= -v.x * v.y * v.z / 262144; // relative: particles per 64^3 cube
+               }
+       }
+
+       if(f & 0x10)
+               self.absolute = 2;
+
+       setorigin(self, self.origin);
+       setsize(self, self.mins, self.maxs);
+       self.solid = SOLID_NOT;
+       self.draw = Draw_PointParticles;
+       self.entremove = Ent_PointParticles_Remove;
+}
+#endif
diff --git a/qcsrc/common/triggers/func/pointparticles.qh b/qcsrc/common/triggers/func/pointparticles.qh
new file mode 100644 (file)
index 0000000..d446e72
--- /dev/null
@@ -0,0 +1,5 @@
+#ifdef CSQC
+
+void Ent_PointParticles();
+
+#endif
\ No newline at end of file
diff --git a/qcsrc/common/triggers/func/rainsnow.qc b/qcsrc/common/triggers/func/rainsnow.qc
new file mode 100644 (file)
index 0000000..deb5ee5
--- /dev/null
@@ -0,0 +1,128 @@
+#ifdef SVQC
+float rainsnow_SendEntity(entity to, float sf)
+{
+       WriteByte(MSG_ENTITY, ENT_CLIENT_RAINSNOW);
+       WriteByte(MSG_ENTITY, self.state);
+       WriteCoord(MSG_ENTITY, self.origin_x + self.mins_x);
+       WriteCoord(MSG_ENTITY, self.origin_y + self.mins_y);
+       WriteCoord(MSG_ENTITY, self.origin_z + self.mins_z);
+       WriteCoord(MSG_ENTITY, self.maxs_x - self.mins_x);
+       WriteCoord(MSG_ENTITY, self.maxs_y - self.mins_y);
+       WriteCoord(MSG_ENTITY, self.maxs_z - self.mins_z);
+       WriteShort(MSG_ENTITY, compressShortVector(self.dest));
+       WriteShort(MSG_ENTITY, self.count);
+       WriteByte(MSG_ENTITY, self.cnt);
+       return 1;
+}
+
+/*QUAKED spawnfunc_func_rain (0 .5 .8) ?
+This is an invisible area like a trigger, which rain falls inside of.
+
+Keys:
+"velocity"
+ falling direction (should be something like '0 0 -700', use the X and Y velocity for wind)
+"cnt"
+ sets color of rain (default 12 - white)
+"count"
+ adjusts density, this many particles fall every second for a 1024x1024 area, default is 2000
+*/
+void spawnfunc_func_rain()
+{
+       self.dest = self.velocity;
+       self.velocity = '0 0 0';
+       if (!self.dest)
+               self.dest = '0 0 -700';
+       self.angles = '0 0 0';
+       self.movetype = MOVETYPE_NONE;
+       self.solid = SOLID_NOT;
+       SetBrushEntityModel();
+       if (!self.cnt)
+               self.cnt = 12;
+       if (!self.count)
+               self.count = 2000;
+       self.count = 0.01 * self.count * (self.size_x / 1024) * (self.size_y / 1024);
+       if (self.count < 1)
+               self.count = 1;
+       if(self.count > 65535)
+               self.count = 65535;
+
+       self.state = 1; // 1 is rain, 0 is snow
+       self.Version = 1;
+
+       Net_LinkEntity(self, false, 0, rainsnow_SendEntity);
+}
+
+
+/*QUAKED spawnfunc_func_snow (0 .5 .8) ?
+This is an invisible area like a trigger, which snow falls inside of.
+
+Keys:
+"velocity"
+ falling direction (should be something like '0 0 -300', use the X and Y velocity for wind)
+"cnt"
+ sets color of rain (default 12 - white)
+"count"
+ adjusts density, this many particles fall every second for a 1024x1024 area, default is 2000
+*/
+void spawnfunc_func_snow()
+{
+       self.dest = self.velocity;
+       self.velocity = '0 0 0';
+       if (!self.dest)
+               self.dest = '0 0 -300';
+       self.angles = '0 0 0';
+       self.movetype = MOVETYPE_NONE;
+       self.solid = SOLID_NOT;
+       SetBrushEntityModel();
+       if (!self.cnt)
+               self.cnt = 12;
+       if (!self.count)
+               self.count = 2000;
+       self.count = 0.01 * self.count * (self.size_x / 1024) * (self.size_y / 1024);
+       if (self.count < 1)
+               self.count = 1;
+       if(self.count > 65535)
+               self.count = 65535;
+
+       self.state = 0; // 1 is rain, 0 is snow
+       self.Version = 1;
+
+       Net_LinkEntity(self, false, 0, rainsnow_SendEntity);
+}
+#elif defined(CSQC)
+void Draw_Rain()
+{
+    te_particlerain(self.origin + self.mins, self.origin + self.maxs, self.velocity, floor(self.count * drawframetime + random()), self.glow_color);
+}
+
+void Draw_Snow()
+{
+    te_particlesnow(self.origin + self.mins, self.origin + self.maxs, self.velocity, floor(self.count * drawframetime + random()), self.glow_color);
+}
+
+void Ent_RainOrSnow()
+{
+       self.impulse = ReadByte(); // Rain, Snow, or Whatever
+       self.origin_x = ReadCoord();
+       self.origin_y = ReadCoord();
+       self.origin_z = ReadCoord();
+       self.maxs_x = ReadCoord();
+       self.maxs_y = ReadCoord();
+       self.maxs_z = ReadCoord();
+       self.velocity = decompressShortVector(ReadShort());
+       self.count = ReadShort() * 10;
+       self.glow_color = ReadByte(); // color
+
+       self.mins    = -0.5 * self.maxs;
+       self.maxs    =  0.5 * self.maxs;
+       self.origin  = self.origin - self.mins;
+
+       setorigin(self, self.origin);
+       setsize(self, self.mins, self.maxs);
+       self.solid = SOLID_NOT;
+       if(self.impulse)
+               self.draw = Draw_Rain;
+       else
+               self.draw = Draw_Snow;
+}
+#endif
diff --git a/qcsrc/common/triggers/func/rainsnow.qh b/qcsrc/common/triggers/func/rainsnow.qh
new file mode 100644 (file)
index 0000000..5d8d923
--- /dev/null
@@ -0,0 +1,3 @@
+#ifdef CSQC
+void Ent_RainOrSnow();
+#endif
diff --git a/qcsrc/common/triggers/func/rotating.qc b/qcsrc/common/triggers/func/rotating.qc
new file mode 100644 (file)
index 0000000..93d4a30
--- /dev/null
@@ -0,0 +1,77 @@
+#ifdef SVQC
+void func_rotating_setactive(float astate)
+{
+
+       if (astate == ACTIVE_TOGGLE)
+       {
+               if(self.active == ACTIVE_ACTIVE)
+                       self.active = ACTIVE_NOT;
+               else
+                       self.active = ACTIVE_ACTIVE;
+       }
+       else
+               self.active = astate;
+
+       if(self.active  == ACTIVE_NOT)
+               self.avelocity = '0 0 0';
+       else
+               self.avelocity = self.pos1;
+}
+
+/*QUAKED spawnfunc_func_rotating (0 .5 .8) ? - - X_AXIS Y_AXIS
+Brush model that spins in place on one axis (default Z).
+speed   : speed to rotate (in degrees per second)
+noise   : path/name of looping .wav file to play.
+dmg     : Do this mutch dmg every .dmgtime intervall when blocked
+dmgtime : See above.
+*/
+
+void spawnfunc_func_rotating()
+{
+       if (self.noise != "")
+       {
+               precache_sound(self.noise);
+               ambientsound(self.origin, self.noise, VOL_BASE, ATTEN_IDLE);
+       }
+
+       self.active = ACTIVE_ACTIVE;
+       self.setactive = func_rotating_setactive;
+
+       if (!self.speed)
+               self.speed = 100;
+       // FIXME: test if this turns the right way, then remove this comment (negate as needed)
+       if (self.spawnflags & 4) // X (untested)
+               self.avelocity = '0 0 1' * self.speed;
+       // FIXME: test if this turns the right way, then remove this comment (negate as needed)
+       else if (self.spawnflags & 8) // Y (untested)
+               self.avelocity = '1 0 0' * self.speed;
+       // FIXME: test if this turns the right way, then remove this comment (negate as needed)
+       else // Z
+               self.avelocity = '0 1 0' * self.speed;
+
+       self.pos1 = self.avelocity;
+
+    if(self.dmg && (self.message == ""))
+        self.message = " was squished";
+    if(self.dmg && (self.message2 == ""))
+               self.message2 = "was squished by";
+
+
+    if(self.dmg && (!self.dmgtime))
+        self.dmgtime = 0.25;
+
+    self.dmgtime2 = time;
+
+       if (!InitMovingBrushTrigger())
+               return;
+       // no EF_LOWPRECISION here, as rounding angles is bad
+
+    self.blocked = generic_plat_blocked;
+
+       // wait for targets to spawn
+       self.SUB_NEXTTHINK = self.SUB_LTIME + 999999999;
+       self.SUB_THINK = SUB_NullThink; // for PushMove
+
+       // TODO make a reset function for this one
+}
+#endif
diff --git a/qcsrc/common/triggers/func/stardust.qc b/qcsrc/common/triggers/func/stardust.qc
new file mode 100644 (file)
index 0000000..30c406f
--- /dev/null
@@ -0,0 +1,8 @@
+#ifdef SVQC
+void spawnfunc_func_stardust()
+{
+       self.effects = EF_STARDUST;
+
+       CSQCMODEL_AUTOINIT();
+}
+#endif
diff --git a/qcsrc/common/triggers/func/train.qc b/qcsrc/common/triggers/func/train.qc
new file mode 100644 (file)
index 0000000..001a759
--- /dev/null
@@ -0,0 +1,316 @@
+.float train_wait_turning;
+void() train_next;
+void train_wait()
+{
+       entity oldself;
+       oldself = self;
+       self = self.enemy;
+       SUB_UseTargets();
+       self = oldself;
+       self.enemy = world;
+
+       // if turning is enabled, the train will turn toward the next point while waiting
+       if(self.platmovetype_turn && !self.train_wait_turning)
+       {
+               entity targ, cp;
+               vector ang;
+               targ = find(world, targetname, self.target);
+               if((self.spawnflags & 1) && targ.curvetarget)
+                       cp = find(world, targetname, targ.curvetarget);
+               else
+                       cp = world;
+
+               if(cp) // bezier curves movement
+                       ang = cp.origin - (self.origin - self.view_ofs); // use the origin of the control point of the next path_corner
+               else // linear movement
+                       ang = targ.origin - (self.origin - self.view_ofs); // use the origin of the next path_corner
+               ang = vectoangles(ang);
+               ang_x = -ang_x; // flip up / down orientation
+
+               if(self.wait > 0) // slow turning
+                       SUB_CalcAngleMove(ang, TSPEED_TIME, self.SUB_LTIME - time + self.wait, train_wait);
+               else // instant turning
+                       SUB_CalcAngleMove(ang, TSPEED_TIME, 0.0000001, train_wait);
+               self.train_wait_turning = true;
+               return;
+       }
+
+#ifdef SVQC
+       if(self.noise != "")
+               stopsoundto(MSG_BROADCAST, self, CH_TRIGGER_SINGLE); // send this as unreliable only, as the train will resume operation shortly anyway
+#endif
+
+       if(self.wait < 0 || self.train_wait_turning) // no waiting or we already waited while turning
+       {
+               self.train_wait_turning = false;
+               train_next();
+       }
+       else
+       {
+               self.SUB_THINK = train_next;
+               self.SUB_NEXTTHINK = self.SUB_LTIME + self.wait;
+       }
+}
+
+void train_next()
+{
+       entity targ, cp = world;
+       vector cp_org = '0 0 0';
+
+       targ = find(world, targetname, self.target);
+       self.target = targ.target;
+       if (self.spawnflags & 1)
+       {
+               if(targ.curvetarget)
+               {
+                       cp = find(world, targetname, targ.curvetarget); // get its second target (the control point)
+                       cp_org = cp.origin - self.view_ofs; // no control point found, assume a straight line to the destination
+               }
+       }
+       if (self.target == "")
+               objerror("train_next: no next target");
+       self.wait = targ.wait;
+       if (!self.wait)
+               self.wait = 0.1;
+
+       if(targ.platmovetype)
+       {
+               // this path_corner contains a movetype overrider, apply it
+               self.platmovetype_start = targ.platmovetype_start;
+               self.platmovetype_end = targ.platmovetype_end;
+       }
+       else
+       {
+               // this path_corner doesn't contain a movetype overrider, use the train's defaults
+               self.platmovetype_start = self.platmovetype_start_default;
+               self.platmovetype_end = self.platmovetype_end_default;
+       }
+
+       if (targ.speed)
+       {
+               if (cp)
+                       SUB_CalcMove_Bezier(cp_org, targ.origin - self.view_ofs, TSPEED_LINEAR, targ.speed, train_wait);
+               else
+                       SUB_CalcMove(targ.origin - self.view_ofs, TSPEED_LINEAR, targ.speed, train_wait);
+       }
+       else
+       {
+               if (cp)
+                       SUB_CalcMove_Bezier(cp_org, targ.origin - self.view_ofs, TSPEED_LINEAR, self.speed, train_wait);
+               else
+                       SUB_CalcMove(targ.origin - self.view_ofs, TSPEED_LINEAR, self.speed, train_wait);
+       }
+
+       if(self.noise != "")
+               sound(self, CH_TRIGGER_SINGLE, self.noise, VOL_BASE, ATTEN_IDLE);
+}
+
+#ifdef SVQC
+float train_send(entity to, float sf)
+{
+       WriteByte(MSG_ENTITY, ENT_CLIENT_TRAIN);
+       WriteByte(MSG_ENTITY, sf);
+
+       if(sf & SF_TRIGGER_INIT)
+       {
+               WriteString(MSG_ENTITY, self.platmovetype);
+               WriteByte(MSG_ENTITY, self.platmovetype_turn);
+               WriteByte(MSG_ENTITY, self.spawnflags);
+
+               WriteString(MSG_ENTITY, self.model);
+
+               trigger_common_write(true);
+
+               WriteString(MSG_ENTITY, self.curvetarget);
+
+               WriteCoord(MSG_ENTITY, self.pos1_x);
+               WriteCoord(MSG_ENTITY, self.pos1_y);
+               WriteCoord(MSG_ENTITY, self.pos1_z);
+               WriteCoord(MSG_ENTITY, self.pos2_x);
+               WriteCoord(MSG_ENTITY, self.pos2_y);
+               WriteCoord(MSG_ENTITY, self.pos2_z);
+
+               WriteCoord(MSG_ENTITY, self.size_x);
+               WriteCoord(MSG_ENTITY, self.size_y);
+               WriteCoord(MSG_ENTITY, self.size_z);
+
+               WriteCoord(MSG_ENTITY, self.view_ofs_x);
+               WriteCoord(MSG_ENTITY, self.view_ofs_y);
+               WriteCoord(MSG_ENTITY, self.view_ofs_z);
+
+               WriteAngle(MSG_ENTITY, self.mangle_x);
+               WriteAngle(MSG_ENTITY, self.mangle_y);
+               WriteAngle(MSG_ENTITY, self.mangle_z);
+
+               WriteShort(MSG_ENTITY, self.speed);
+               WriteShort(MSG_ENTITY, self.height);
+               WriteByte(MSG_ENTITY, self.lip);
+               WriteByte(MSG_ENTITY, self.state);
+               WriteByte(MSG_ENTITY, self.wait);
+
+               WriteShort(MSG_ENTITY, self.dmg);
+               WriteByte(MSG_ENTITY, self.dmgtime);
+       }
+
+       if(sf & SF_TRIGGER_RESET)
+       {
+               // used on client
+       }
+
+       return true;
+}
+
+void train_link()
+{
+       //Net_LinkEntity(self, 0, false, train_send);
+}
+
+void func_train_find()
+{
+       entity targ;
+       targ = find(world, targetname, self.target);
+       self.target = targ.target;
+       if (self.target == "")
+               objerror("func_train_find: no next target");
+       SUB_SETORIGIN(self, targ.origin - self.view_ofs);
+       self.SUB_NEXTTHINK = self.SUB_LTIME + 1;
+       self.SUB_THINK = train_next;
+
+       train_link();
+}
+
+#endif
+
+/*QUAKED spawnfunc_func_train (0 .5 .8) ?
+Ridable platform, targets spawnfunc_path_corner path to follow.
+speed : speed the train moves (can be overridden by each spawnfunc_path_corner)
+target : targetname of first spawnfunc_path_corner (starts here)
+*/
+#ifdef SVQC
+void spawnfunc_func_train()
+{
+       if (self.noise != "")
+               precache_sound(self.noise);
+
+       if (self.target == "")
+               objerror("func_train without a target");
+       if (!self.speed)
+               self.speed = 100;
+
+       if (!InitMovingBrushTrigger())
+               return;
+       self.effects |= EF_LOWPRECISION;
+       
+       if (self.spawnflags & 2)
+       {
+               self.platmovetype_turn = true;
+               self.view_ofs = '0 0 0'; // don't offset a rotating train, origin works differently now
+       }
+       else
+               self.view_ofs = self.mins;
+
+       // wait for targets to spawn
+       InitializeEntity(self, func_train_find, INITPRIO_FINDTARGET);
+
+       self.blocked = generic_plat_blocked;
+       if(self.dmg && (self.message == ""))
+               self.message = " was squished";
+    if(self.dmg && (self.message2 == ""))
+               self.message2 = "was squished by";
+       if(self.dmg && (!self.dmgtime))
+               self.dmgtime = 0.25;
+       self.dmgtime2 = time;
+
+       if(!set_platmovetype(self, self.platmovetype))
+               return;
+       self.platmovetype_start_default = self.platmovetype_start;
+       self.platmovetype_end_default = self.platmovetype_end;
+
+       // TODO make a reset function for this one
+}
+#elif defined(CSQC)
+void train_draw()
+{
+       //Movetype_Physics_NoMatchServer();
+       Movetype_Physics_MatchServer(autocvar_cl_projectiles_sloppy);
+}
+
+void ent_train()
+{
+       float sf = ReadByte();
+
+       if(sf & SF_TRIGGER_INIT)
+       {
+               self.platmovetype = strzone(ReadString());
+               self.platmovetype_turn = ReadByte();
+               self.spawnflags = ReadByte();
+
+               self.model = strzone(ReadString());
+               setmodel(self, self.model);
+
+               trigger_common_read(true);
+
+               self.curvetarget = strzone(ReadString());
+
+               self.pos1_x = ReadCoord();
+               self.pos1_y = ReadCoord();
+               self.pos1_z = ReadCoord();
+               self.pos2_x = ReadCoord();
+               self.pos2_y = ReadCoord();
+               self.pos2_z = ReadCoord();
+
+               self.size_x = ReadCoord();
+               self.size_y = ReadCoord();
+               self.size_z = ReadCoord();
+
+               self.view_ofs_x = ReadCoord();
+               self.view_ofs_y = ReadCoord();
+               self.view_ofs_z = ReadCoord();
+
+               self.mangle_x = ReadAngle();
+               self.mangle_y = ReadAngle();
+               self.mangle_z = ReadAngle();
+
+               self.speed = ReadShort();
+               self.height = ReadShort();
+               self.lip = ReadByte();
+               self.state = ReadByte();
+               self.wait = ReadByte();
+
+               self.dmg = ReadShort();
+               self.dmgtime = ReadByte();
+
+               self.classname = "func_train";
+               self.solid = SOLID_BSP;
+               self.movetype = MOVETYPE_PUSH;
+               self.drawmask = MASK_NORMAL;
+               self.draw = train_draw;
+               self.entremove = trigger_remove_generic;
+
+               if(set_platmovetype(self, self.platmovetype))
+               {
+                       self.platmovetype_start_default = self.platmovetype_start;
+                       self.platmovetype_end_default = self.platmovetype_end;
+               }
+
+               // everything is set up by the time the train is linked, we shouldn't need this
+               //func_train_find();
+
+               // but we will need these
+               //self.move_nextthink = self.move_ltime + 0.1;
+               //self.move_think = train_next;
+               train_next();
+
+               self.move_movetype = MOVETYPE_PUSH;
+               self.move_origin = self.origin;
+               self.move_angles = self.angles;
+               self.move_time = time;
+       }
+
+       if(sf & SF_TRIGGER_RESET)
+       {
+               // TODO: make a reset function for trains
+       }
+}
+
+#endif
diff --git a/qcsrc/common/triggers/func/train.qh b/qcsrc/common/triggers/func/train.qh
new file mode 100644 (file)
index 0000000..f69515f
--- /dev/null
@@ -0,0 +1,4 @@
+#ifdef CSQC
+.float dmgtime;
+void ent_train();
+#endif
diff --git a/qcsrc/common/triggers/func/vectormamamam.qc b/qcsrc/common/triggers/func/vectormamamam.qc
new file mode 100644 (file)
index 0000000..521ac87
--- /dev/null
@@ -0,0 +1,159 @@
+#ifdef SVQC
+// reusing some fields havocbots declared
+.entity wp00, wp01, wp02, wp03;
+
+.float targetfactor, target2factor, target3factor, target4factor;
+.vector targetnormal, target2normal, target3normal, target4normal;
+
+vector func_vectormamamam_origin(entity o, float t)
+{
+       vector v, p;
+       float f;
+       entity e;
+
+       f = o.spawnflags;
+       v = '0 0 0';
+
+       e = o.wp00;
+       if(e)
+       {
+               p = e.origin + t * e.velocity;
+               if(f & 1)
+                       v = v + (p * o.targetnormal) * o.targetnormal * o.targetfactor;
+               else
+                       v = v + (p - (p * o.targetnormal) * o.targetnormal) * o.targetfactor;
+       }
+
+       e = o.wp01;
+       if(e)
+       {
+               p = e.origin + t * e.velocity;
+               if(f & 2)
+                       v = v + (p * o.target2normal) * o.target2normal * o.target2factor;
+               else
+                       v = v + (p - (p * o.target2normal) * o.target2normal) * o.target2factor;
+       }
+
+       e = o.wp02;
+       if(e)
+       {
+               p = e.origin + t * e.velocity;
+               if(f & 4)
+                       v = v + (p * o.target3normal) * o.target3normal * o.target3factor;
+               else
+                       v = v + (p - (p * o.target3normal) * o.target3normal) * o.target3factor;
+       }
+
+       e = o.wp03;
+       if(e)
+       {
+               p = e.origin + t * e.velocity;
+               if(f & 8)
+                       v = v + (p * o.target4normal) * o.target4normal * o.target4factor;
+               else
+                       v = v + (p - (p * o.target4normal) * o.target4normal) * o.target4factor;
+       }
+
+       return v;
+}
+
+void func_vectormamamam_controller_think()
+{
+       self.nextthink = time + 0.1;
+
+       if(self.owner.active != ACTIVE_ACTIVE)
+       {
+               self.owner.velocity = '0 0 0';
+               return;
+       }
+
+       if(self.owner.classname == "func_vectormamamam") // don't brake stuff if the func_vectormamamam was killtarget'ed
+               self.owner.velocity = (self.owner.destvec + func_vectormamamam_origin(self.owner, 0.1) - self.owner.origin) * 10;
+}
+
+void func_vectormamamam_findtarget()
+{
+       if(self.target != "")
+               self.wp00 = find(world, targetname, self.target);
+
+       if(self.target2 != "")
+               self.wp01 = find(world, targetname, self.target2);
+
+       if(self.target3 != "")
+               self.wp02 = find(world, targetname, self.target3);
+
+       if(self.target4 != "")
+               self.wp03 = find(world, targetname, self.target4);
+
+       if(!self.wp00 && !self.wp01 && !self.wp02 && !self.wp03)
+               objerror("No reference entity found, so there is nothing to move. Aborting.");
+
+       self.destvec = self.origin - func_vectormamamam_origin(self, 0);
+
+       entity controller;
+       controller = spawn();
+       controller.classname = "func_vectormamamam_controller";
+       controller.owner = self;
+       controller.nextthink = time + 1;
+       controller.think = func_vectormamamam_controller_think;
+}
+
+void spawnfunc_func_vectormamamam()
+{
+       if (self.noise != "")
+       {
+               precache_sound(self.noise);
+               soundto(MSG_INIT, self, CH_TRIGGER_SINGLE, self.noise, VOL_BASE, ATTEN_IDLE);
+       }
+
+       if(!self.targetfactor)
+               self.targetfactor = 1;
+
+       if(!self.target2factor)
+               self.target2factor = 1;
+
+       if(!self.target3factor)
+               self.target3factor = 1;
+
+       if(!self.target4factor)
+               self.target4factor = 1;
+
+       if(vlen(self.targetnormal))
+               self.targetnormal = normalize(self.targetnormal);
+
+       if(vlen(self.target2normal))
+               self.target2normal = normalize(self.target2normal);
+
+       if(vlen(self.target3normal))
+               self.target3normal = normalize(self.target3normal);
+
+       if(vlen(self.target4normal))
+               self.target4normal = normalize(self.target4normal);
+
+       self.blocked = generic_plat_blocked;
+       if(self.dmg && (self.message == ""))
+               self.message = " was squished";
+    if(self.dmg && (self.message == ""))
+               self.message2 = "was squished by";
+       if(self.dmg && (!self.dmgtime))
+               self.dmgtime = 0.25;
+       self.dmgtime2 = time;
+
+       if(self.netname == "")
+               self.netname = "1 0 0 0 1";
+
+       if (!InitMovingBrushTrigger())
+               return;
+
+       // wait for targets to spawn
+       self.SUB_NEXTTHINK = self.SUB_LTIME + 999999999;
+       self.SUB_THINK = SUB_NullThink; // for PushMove
+
+       // Savage: Reduce bandwith, critical on e.g. nexdm02
+       self.effects |= EF_LOWPRECISION;
+
+       self.active = ACTIVE_ACTIVE;
+
+       InitializeEntity(self, func_vectormamamam_findtarget, INITPRIO_FINDTARGET);
+}
+#endif
diff --git a/qcsrc/common/triggers/include.qc b/qcsrc/common/triggers/include.qc
new file mode 100644 (file)
index 0000000..59da1f2
--- /dev/null
@@ -0,0 +1,20 @@
+#include "include.qh"
+
+// some required common stuff
+#include "subs.qc"
+#include "triggers.qc"
+#include "platforms.qc"
+#include "teleporters.qc"
+
+// func
+#include "func/include.qc"
+
+// misc
+#include "misc/include.qc"
+
+// target
+#include "target/include.qc"
+
+// trigger
+#include "trigger/include.qc"
+
diff --git a/qcsrc/common/triggers/include.qh b/qcsrc/common/triggers/include.qh
new file mode 100644 (file)
index 0000000..138d267
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef TRIGGERS_INCLUDE_H
+#define TRIGGERS_INCLUDE_H
+
+// some required common stuff
+#ifdef CSQC
+       #include "../../server/item_key.qh"
+#endif
+#include "triggers.qh"
+#include "subs.qh"
+#include "platforms.qh"
+#include "teleporters.qh"
+
+// func
+#include "func/include.qh"
+
+// misc
+#include "misc/include.qh"
+
+// target
+#include "target/include.qh"
+
+// trigger
+#include "trigger/include.qh"
+
+#endif
diff --git a/qcsrc/common/triggers/misc/corner.qc b/qcsrc/common/triggers/misc/corner.qc
new file mode 100644 (file)
index 0000000..4294eac
--- /dev/null
@@ -0,0 +1,85 @@
+#ifdef SVQC
+bool corner_send(entity to, int sf)
+{
+       WriteByte(MSG_ENTITY, ENT_CLIENT_CORNER);
+
+       WriteString(MSG_ENTITY, self.platmovetype);
+
+       WriteCoord(MSG_ENTITY, self.origin_x);
+       WriteCoord(MSG_ENTITY, self.origin_y);
+       WriteCoord(MSG_ENTITY, self.origin_z);
+
+       WriteString(MSG_ENTITY, self.target);
+       WriteString(MSG_ENTITY, self.target2);
+       WriteString(MSG_ENTITY, self.target3);
+       WriteString(MSG_ENTITY, self.target4);
+       WriteString(MSG_ENTITY, self.targetname);
+       WriteByte(MSG_ENTITY, self.target_random);
+
+       WriteByte(MSG_ENTITY, self.wait);
+
+       return true;
+}
+
+void corner_link()
+{
+       //Net_LinkEntity(self, false, 0, corner_send);
+}
+
+void spawnfunc_path_corner()
+{
+       // setup values for overriding train movement
+       // if a second value does not exist, both start and end speeds are the single value specified
+       set_platmovetype(self, self.platmovetype);
+
+       corner_link();
+}
+#elif defined(CSQC)
+
+void corner_remove()
+{
+       if(self.target) { strunzone(self.target); }
+       self.target = string_null;
+
+       if(self.target2) { strunzone(self.target2); }
+       self.target2 = string_null;
+
+       if(self.target3) { strunzone(self.target3); }
+       self.target3 = string_null;
+
+       if(self.target4) { strunzone(self.target4); }
+       self.target4 = string_null;
+
+       if(self.targetname) { strunzone(self.targetname); }
+       self.targetname = string_null;
+
+       if(self.platmovetype) { strunzone(self.platmovetype); }
+       self.platmovetype = string_null;
+}
+
+void ent_corner()
+{
+       self.platmovetype = strzone(ReadString());
+
+       self.origin_x = ReadCoord();
+       self.origin_y = ReadCoord();
+       self.origin_z = ReadCoord();
+       setorigin(self, self.origin);
+
+       self.target = strzone(ReadString());
+       self.target2 = strzone(ReadString());
+       self.target3 = strzone(ReadString());
+       self.target4 = strzone(ReadString());
+       self.targetname = strzone(ReadString());
+       self.target_random = ReadByte();
+
+       self.wait = ReadByte();
+
+       self.classname = "path_corner";
+       self.drawmask = MASK_NORMAL;
+       self.entremove = corner_remove;
+
+       set_platmovetype(self, self.platmovetype);
+}
+
+#endif
diff --git a/qcsrc/common/triggers/misc/corner.qh b/qcsrc/common/triggers/misc/corner.qh
new file mode 100644 (file)
index 0000000..62b3aae
--- /dev/null
@@ -0,0 +1,3 @@
+#ifdef CSQC
+void ent_corner();
+#endif
diff --git a/qcsrc/common/triggers/misc/follow.qc b/qcsrc/common/triggers/misc/follow.qc
new file mode 100644 (file)
index 0000000..bfeb865
--- /dev/null
@@ -0,0 +1,69 @@
+// the way this entity works makes it no use to CSQC, as it removes itself instantly
+
+#ifdef SVQC
+void follow_init()
+{
+       entity src, dst;
+       src = world;
+       dst = world;
+       if(self.killtarget != "")
+               src = find(world, targetname, self.killtarget);
+       if(self.target != "")
+               dst = find(world, targetname, self.target);
+
+       if(!src && !dst)
+       {
+               objerror("follow: could not find target/killtarget");
+               return;
+       }
+
+       if(self.jointtype)
+       {
+               // already done :P entity must stay
+               self.aiment = src;
+               self.enemy = dst;
+       }
+       else if(!src || !dst)
+       {
+               objerror("follow: could not find target/killtarget");
+               return;
+       }
+       else if(self.spawnflags & 1)
+       {
+               // attach
+               if(self.spawnflags & 2)
+               {
+                       setattachment(dst, src, self.message);
+               }
+               else
+               {
+                       attach_sameorigin(dst, src, self.message);
+               }
+
+               dst.solid = SOLID_NOT; // solid doesn't work with attachment
+               remove(self);
+       }
+       else
+       {
+               if(self.spawnflags & 2)
+               {
+                       dst.movetype = MOVETYPE_FOLLOW;
+                       dst.aiment = src;
+                       // dst.punchangle = '0 0 0'; // keep unchanged
+                       dst.view_ofs = dst.origin;
+                       dst.v_angle = dst.angles;
+               }
+               else
+               {
+                       follow_sameorigin(dst, src);
+               }
+
+               remove(self);
+       }
+}
+
+void spawnfunc_misc_follow()
+{
+       InitializeEntity(self, follow_init, INITPRIO_FINDTARGET);
+}
+#endif
diff --git a/qcsrc/common/triggers/misc/include.qc b/qcsrc/common/triggers/misc/include.qc
new file mode 100644 (file)
index 0000000..c05f8c3
--- /dev/null
@@ -0,0 +1,6 @@
+#include "include.qh"
+
+#include "corner.qc"
+#include "follow.qc"
+#include "laser.qc"
+#include "teleport_dest.qc"
diff --git a/qcsrc/common/triggers/misc/include.qh b/qcsrc/common/triggers/misc/include.qh
new file mode 100644 (file)
index 0000000..71b2205
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef TRIGGERS_MISC_INCLUDE_H
+#define TRIGGERS_MISC_INCLUDE_H
+
+#include "corner.qh"
+#include "laser.qh"
+
+#endif
diff --git a/qcsrc/common/triggers/misc/laser.qc b/qcsrc/common/triggers/misc/laser.qc
new file mode 100644 (file)
index 0000000..2d9f095
--- /dev/null
@@ -0,0 +1,393 @@
+#if defined(CSQC)
+       #include "../../../client/_all.qh"
+       #include "../../buffs.qh"
+       #include "../../../csqcmodellib/interpolate.qh"
+       #include "../../../client/main.qh"
+       #include "../../../csqcmodellib/cl_model.qh"
+#elif defined(MENUQC)
+#elif defined(SVQC)
+#endif
+
+#ifdef SVQC
+.float modelscale;
+void misc_laser_aim()
+{
+       vector a;
+       if(self.enemy)
+       {
+               if(self.spawnflags & 2)
+               {
+                       if(self.enemy.origin != self.mangle)
+                       {
+                               self.mangle = self.enemy.origin;
+                               self.SendFlags |= 2;
+                       }
+               }
+               else
+               {
+                       a = vectoangles(self.enemy.origin - self.origin);
+                       a_x = -a_x;
+                       if(a != self.mangle)
+                       {
+                               self.mangle = a;
+                               self.SendFlags |= 2;
+                       }
+               }
+       }
+       else
+       {
+               if(self.angles != self.mangle)
+               {
+                       self.mangle = self.angles;
+                       self.SendFlags |= 2;
+               }
+       }
+       if(self.origin != self.oldorigin)
+       {
+               self.SendFlags |= 1;
+               self.oldorigin = self.origin;
+       }
+}
+
+void misc_laser_init()
+{
+       if(self.target != "")
+               self.enemy = find(world, targetname, self.target);
+}
+
+.entity pusher;
+void misc_laser_think()
+{
+       vector o;
+       entity oldself;
+       entity hitent;
+       vector hitloc;
+
+       self.nextthink = time;
+
+       if(!self.state)
+               return;
+
+       misc_laser_aim();
+
+       if(self.enemy)
+       {
+               o = self.enemy.origin;
+               if (!(self.spawnflags & 2))
+                       o = self.origin + normalize(o - self.origin) * 32768;
+       }
+       else
+       {
+               makevectors(self.mangle);
+               o = self.origin + v_forward * 32768;
+       }
+
+       if(self.dmg || self.enemy.target != "")
+       {
+               traceline(self.origin, o, MOVE_NORMAL, self);
+       }
+       hitent = trace_ent;
+       hitloc = trace_endpos;
+
+       if(self.enemy.target != "") // DETECTOR laser
+       {
+               if(trace_ent.iscreature)
+               {
+                       self.pusher = hitent;
+                       if(!self.count)
+                       {
+                               self.count = 1;
+
+                               oldself = self;
+                               self = self.enemy;
+                               activator = self.pusher;
+                               SUB_UseTargets();
+                               self = oldself;
+                       }
+               }
+               else
+               {
+                       if(self.count)
+                       {
+                               self.count = 0;
+
+                               oldself = self;
+                               self = self.enemy;
+                               activator = self.pusher;
+                               SUB_UseTargets();
+                               self = oldself;
+                       }
+               }
+       }
+
+       if(self.dmg)
+       {
+               if(self.team)
+                       if(((self.spawnflags & 8) == 0) == (self.team != hitent.team))
+                               return;
+               if(hitent.takedamage)
+                       Damage(hitent, self, self, ((self.dmg < 0) ? 100000 : (self.dmg * frametime)), DEATH_HURTTRIGGER, hitloc, '0 0 0');
+       }
+}
+
+float laser_SendEntity(entity to, float fl)
+{
+       WriteByte(MSG_ENTITY, ENT_CLIENT_LASER);
+       fl = fl - (fl & 0xF0); // use that bit to indicate finite length laser
+       if(self.spawnflags & 2)
+               fl |= 0x80;
+       if(self.alpha)
+               fl |= 0x40;
+       if(self.scale != 1 || self.modelscale != 1)
+               fl |= 0x20;
+       if(self.spawnflags & 4)
+               fl |= 0x10;
+       WriteByte(MSG_ENTITY, fl);
+       if(fl & 1)
+       {
+               WriteCoord(MSG_ENTITY, self.origin_x);
+               WriteCoord(MSG_ENTITY, self.origin_y);
+               WriteCoord(MSG_ENTITY, self.origin_z);
+       }
+       if(fl & 8)
+       {
+               WriteByte(MSG_ENTITY, self.colormod_x * 255.0);
+               WriteByte(MSG_ENTITY, self.colormod_y * 255.0);
+               WriteByte(MSG_ENTITY, self.colormod_z * 255.0);
+               if(fl & 0x40)
+                       WriteByte(MSG_ENTITY, self.alpha * 255.0);
+               if(fl & 0x20)
+               {
+                       WriteByte(MSG_ENTITY, bound(0, self.scale * 16.0, 255));
+                       WriteByte(MSG_ENTITY, bound(0, self.modelscale * 16.0, 255));
+               }
+               if((fl & 0x80) || !(fl & 0x10)) // effect doesn't need sending if the laser is infinite and has collision testing turned off
+                       WriteShort(MSG_ENTITY, self.cnt + 1);
+       }
+       if(fl & 2)
+       {
+               if(fl & 0x80)
+               {
+                       WriteCoord(MSG_ENTITY, self.enemy.origin_x);
+                       WriteCoord(MSG_ENTITY, self.enemy.origin_y);
+                       WriteCoord(MSG_ENTITY, self.enemy.origin_z);
+               }
+               else
+               {
+                       WriteAngle(MSG_ENTITY, self.mangle_x);
+                       WriteAngle(MSG_ENTITY, self.mangle_y);
+               }
+       }
+       if(fl & 4)
+               WriteByte(MSG_ENTITY, self.state);
+       return 1;
+}
+
+/*QUAKED spawnfunc_misc_laser (.5 .5 .5) ? START_ON DEST_IS_FIXED
+Any object touching the beam will be hurt
+Keys:
+"target"
+ spawnfunc_target_position where the laser ends
+"mdl"
+ name of beam end effect to use
+"colormod"
+ color of the beam (default: red)
+"dmg"
+ damage per second (-1 for a laser that kills immediately)
+*/
+void laser_use()
+{
+       self.state = !self.state;
+       self.SendFlags |= 4;
+       misc_laser_aim();
+}
+
+void laser_reset()
+{
+       if(self.spawnflags & 1)
+               self.state = 1;
+       else
+               self.state = 0;
+}
+
+void spawnfunc_misc_laser()
+{
+       if(self.mdl)
+       {
+               if(self.mdl == "none")
+                       self.cnt = -1;
+               else
+               {
+                       self.cnt = particleeffectnum(self.mdl);
+                       if(self.cnt < 0)
+                               if(self.dmg)
+                                       self.cnt = particleeffectnum("laser_deadly");
+               }
+       }
+       else if(!self.cnt)
+       {
+               if(self.dmg)
+                       self.cnt = particleeffectnum("laser_deadly");
+               else
+                       self.cnt = -1;
+       }
+       if(self.cnt < 0)
+               self.cnt = -1;
+
+       if(self.colormod == '0 0 0')
+               if(!self.alpha)
+                       self.colormod = '1 0 0';
+       if(self.message == "")
+               self.message = "saw the light";
+       if (self.message2 == "")
+               self.message2 = "was pushed into a laser by";
+       if(!self.scale)
+               self.scale = 1;
+       if(!self.modelscale)
+               self.modelscale = 1;
+       else if(self.modelscale < 0)
+               self.modelscale = 0;
+       self.think = misc_laser_think;
+       self.nextthink = time;
+       InitializeEntity(self, misc_laser_init, INITPRIO_FINDTARGET);
+
+       self.mangle = self.angles;
+
+       Net_LinkEntity(self, false, 0, laser_SendEntity);
+
+       IFTARGETED
+       {
+               self.reset = laser_reset;
+               laser_reset();
+               self.use = laser_use;
+       }
+       else
+               self.state = 1;
+}
+#elif defined(CSQC)
+
+// a laser goes from origin in direction angles
+// it has color 'colormod'
+// and stops when something is in the way
+entityclass(Laser);
+class(Laser) .int cnt; // end effect
+class(Laser) .vector colormod;
+class(Laser) .int state; // on-off
+class(Laser) .int count; // flags for the laser
+class(Laser) .vector velocity;
+class(Laser) .float alpha;
+class(Laser) .float scale; // scaling factor of the thickness
+class(Laser) .float modelscale; // scaling factor of the dlight
+
+void Draw_Laser()
+{
+       if(!self.state)
+               return;
+       InterpolateOrigin_Do();
+       if(self.count & 0x80)
+       {
+               if(self.count & 0x10)
+               {
+                       trace_endpos = self.velocity;
+                       trace_dphitq3surfaceflags = 0;
+               }
+               else
+                       traceline(self.origin, self.velocity, 0, self);
+       }
+       else
+       {
+               if(self.count & 0x10)
+               {
+                       makevectors(self.angles);
+                       trace_endpos = self.origin + v_forward * 1048576;
+                       trace_dphitq3surfaceflags = Q3SURFACEFLAG_SKY;
+               }
+               else
+               {
+                       makevectors(self.angles);
+                       traceline(self.origin, self.origin + v_forward * 32768, 0, self);
+                       if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_SKY)
+                               trace_endpos = self.origin + v_forward * 1048576;
+               }
+       }
+       if(self.scale != 0)
+       {
+               if(self.alpha)
+               {
+                       Draw_CylindricLine(self.origin, trace_endpos, self.scale, "particles/laserbeam", 0, time * 3, self.colormod, self.alpha, DRAWFLAG_NORMAL, view_origin);
+               }
+               else
+               {
+                       Draw_CylindricLine(self.origin, trace_endpos, self.scale, "particles/laserbeam", 0, time * 3, self.colormod, 0.5, DRAWFLAG_ADDITIVE, view_origin);
+               }
+       }
+       if (!(trace_dphitq3surfaceflags & (Q3SURFACEFLAG_SKY | Q3SURFACEFLAG_NOIMPACT)))
+       {
+               if(self.cnt >= 0)
+                       pointparticles(self.cnt, trace_endpos, trace_plane_normal, drawframetime * 1000);
+               if(self.colormod != '0 0 0' && self.modelscale != 0)
+                       adddynamiclight(trace_endpos + trace_plane_normal * 1, self.modelscale, self.colormod * 5);
+       }
+}
+
+void Ent_Laser()
+{
+       InterpolateOrigin_Undo();
+
+       // 30 bytes, or 13 bytes for just moving
+       int f = ReadByte();
+       self.count = (f & 0xF0);
+
+       if(self.count & 0x80)
+               self.iflags = IFLAG_VELOCITY | IFLAG_ORIGIN;
+       else
+               self.iflags = IFLAG_ANGLES | IFLAG_ORIGIN;
+
+       if(f & 1)
+       {
+               self.origin_x = ReadCoord();
+               self.origin_y = ReadCoord();
+               self.origin_z = ReadCoord();
+               setorigin(self, self.origin);
+       }
+       if(f & 8)
+       {
+               self.colormod_x = ReadByte() / 255.0;
+               self.colormod_y = ReadByte() / 255.0;
+               self.colormod_z = ReadByte() / 255.0;
+               if(f & 0x40)
+                       self.alpha = ReadByte() / 255.0;
+               else
+                       self.alpha = 0;
+               self.scale = 2;
+               self.modelscale = 50;
+               if(f & 0x20)
+               {
+                       self.scale *= ReadByte() / 16.0; // beam radius
+                       self.modelscale *= ReadByte() / 16.0; // dlight radius
+               }
+               if((f & 0x80) || !(f & 0x10))
+                       self.cnt = ReadShort() - 1; // effect number
+               else
+                       self.cnt = 0;
+       }
+       if(f & 2)
+       {
+               if(f & 0x80)
+               {
+                       self.velocity_x = ReadCoord();
+                       self.velocity_y = ReadCoord();
+                       self.velocity_z = ReadCoord();
+               }
+               else
+               {
+                       self.angles_x = ReadAngle();
+                       self.angles_y = ReadAngle();
+               }
+       }
+       if(f & 4)
+               self.state = ReadByte();
+       InterpolateOrigin_Note();
+       self.draw = Draw_Laser;
+}
+#endif
diff --git a/qcsrc/common/triggers/misc/laser.qh b/qcsrc/common/triggers/misc/laser.qh
new file mode 100644 (file)
index 0000000..a77c4c5
--- /dev/null
@@ -0,0 +1,3 @@
+#ifdef CSQC
+void Ent_Laser();
+#endif
diff --git a/qcsrc/common/triggers/misc/teleport_dest.qc b/qcsrc/common/triggers/misc/teleport_dest.qc
new file mode 100644 (file)
index 0000000..b80ce82
--- /dev/null
@@ -0,0 +1,30 @@
+#ifdef SVQC
+
+void spawnfunc_info_teleport_destination (void)
+{
+       self.classname = "info_teleport_destination";
+
+       self.mangle = self.angles;
+       self.angles = '0 0 0';
+
+       //setorigin (self, self.origin + '0 0 27');     // To fix a mappers' habit as old as Quake
+       setorigin (self, self.origin);
+
+       IFTARGETED
+       {
+       }
+       else
+               objerror ("^3Teleport destination without a targetname");
+}
+
+void spawnfunc_misc_teleporter_dest (void)
+{
+       spawnfunc_info_teleport_destination();
+}
+
+void spawnfunc_target_teleporter (void)
+{
+       spawnfunc_info_teleport_destination();
+}
+
+#endif
diff --git a/qcsrc/common/triggers/platforms.qc b/qcsrc/common/triggers/platforms.qc
new file mode 100644 (file)
index 0000000..b837d7c
--- /dev/null
@@ -0,0 +1,235 @@
+void generic_plat_blocked()
+{
+#ifdef SVQC
+       if(self.dmg && other.takedamage != DAMAGE_NO)
+       {
+               if(self.dmgtime2 < time)
+               {
+                       Damage (other, self, self, self.dmg, DEATH_HURTTRIGGER, other.origin, '0 0 0');
+                       self.dmgtime2 = time + self.dmgtime;
+               }
+
+               // Gib dead/dying stuff
+               if(other.deadflag != DEAD_NO)
+                       Damage (other, self, self, 10000, DEATH_HURTTRIGGER, other.origin, '0 0 0');
+       }
+#endif
+}
+
+void plat_spawn_inside_trigger()
+{
+       entity trigger;
+       vector tmin, tmax;
+
+       trigger = spawn();
+       trigger.touch = plat_center_touch;
+       trigger.movetype = MOVETYPE_NONE;
+       trigger.solid = SOLID_TRIGGER;
+       trigger.enemy = self;
+
+#ifdef CSQC
+       trigger.drawmask = MASK_NORMAL;
+       trigger.trigger_touch = plat_center_touch;
+       trigger.draw = trigger_draw_generic;
+#endif
+
+       tmin = self.absmin + '25 25 0';
+       tmax = self.absmax - '25 25 -8';
+       tmin_z = tmax_z - (self.pos1_z - self.pos2_z + 8);
+       if (self.spawnflags & PLAT_LOW_TRIGGER)
+               tmax_z = tmin_z + 8;
+
+       if (self.size_x <= 50)
+       {
+               tmin_x = (self.mins_x + self.maxs_x) / 2;
+               tmax_x = tmin_x + 1;
+       }
+       if (self.size_y <= 50)
+       {
+               tmin_y = (self.mins_y + self.maxs_y) / 2;
+               tmax_y = tmin_y + 1;
+       }
+
+       if(tmin_x < tmax_x)
+               if(tmin_y < tmax_y)
+                       if(tmin_z < tmax_z)
+                       {
+                               setsize (trigger, tmin, tmax);
+                               return;
+                       }
+
+       // otherwise, something is fishy...
+       remove(trigger);
+       objerror("plat_spawn_inside_trigger: platform has odd size or lip, can't spawn");
+}
+
+void plat_hit_top()
+{
+       sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTEN_NORM);
+       self.state = 1;
+
+       self.SUB_THINK = plat_go_down;
+       self.SUB_NEXTTHINK = self.SUB_LTIME + 3;
+}
+
+void plat_hit_bottom()
+{
+       sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTEN_NORM);
+       self.state = 2;
+}
+
+void plat_go_down()
+{
+       sound (self, CH_TRIGGER_SINGLE, self.noise, VOL_BASE, ATTEN_NORM);
+       self.state = 3;
+       SUB_CalcMove (self.pos2, TSPEED_LINEAR, self.speed, plat_hit_bottom);
+}
+
+void plat_go_up()
+{
+       sound (self, CH_TRIGGER_SINGLE, self.noise, VOL_BASE, ATTEN_NORM);
+       self.state = 4;
+       SUB_CalcMove (self.pos1, TSPEED_LINEAR, self.speed, plat_hit_top);
+}
+
+void plat_center_touch()
+{
+#ifdef SVQC
+       if (!other.iscreature)
+               return;
+
+       if (other.health <= 0)
+               return;
+#elif defined(CSQC)
+       if (!IS_PLAYER(other))
+               return;
+       if(PHYS_DEAD(other))
+               return;
+#endif
+
+       self = self.enemy;
+       if (self.state == 2)
+               plat_go_up ();
+       else if (self.state == 1)
+               self.SUB_NEXTTHINK = self.SUB_LTIME + 1;
+}
+
+void plat_outside_touch()
+{
+#ifdef SVQC
+       if (!other.iscreature)
+               return;
+
+       if (other.health <= 0)
+               return;
+#elif defined(CSQC)
+       if (!IS_PLAYER(other))
+               return;
+#endif
+
+       self = self.enemy;
+       if (self.state == 1)
+               plat_go_down ();
+}
+
+void plat_trigger_use()
+{
+#ifdef SVQC
+       if (self.think)
+               return;         // already activated
+#elif defined(CSQC)
+       if(self.move_think)
+               return;
+#endif
+       plat_go_down();
+}
+
+
+void plat_crush()
+{
+       if((self.spawnflags & 4) && (other.takedamage != DAMAGE_NO))
+       { // KIll Kill Kill!!
+#ifdef SVQC
+               Damage (other, self, self, 10000, DEATH_HURTTRIGGER, other.origin, '0 0 0');
+#endif
+       }
+       else
+       {
+#ifdef SVQC
+               if((self.dmg) && (other.takedamage != DAMAGE_NO))
+               {   // Shall we bite?
+                       Damage (other, self, self, self.dmg, DEATH_HURTTRIGGER, other.origin, '0 0 0');
+                       // Gib dead/dying stuff
+                       if(other.deadflag != DEAD_NO)
+                               Damage (other, self, self, 10000, DEATH_HURTTRIGGER, other.origin, '0 0 0');
+               }
+#endif
+
+               if (self.state == 4)
+                       plat_go_down ();
+               else if (self.state == 3)
+                       plat_go_up ();
+       // when in other states, then the plat_crush event came delayed after
+       // plat state already had changed
+       // this isn't a bug per se!
+       }
+}
+
+void plat_use()
+{
+       self.use = func_null;
+       if (self.state != 4)
+               objerror ("plat_use: not in up state");
+       plat_go_down();
+}
+
+.string sound1, sound2;
+
+void plat_reset()
+{
+       IFTARGETED
+       {
+               setorigin (self, self.pos1);
+               self.state = 4;
+               self.use = plat_use;
+       }
+       else
+       {
+               setorigin (self, self.pos2);
+               self.state = 2;
+               self.use = plat_trigger_use;
+       }
+
+#ifdef SVQC
+       self.SendFlags |= SF_TRIGGER_RESET;
+#endif
+}
+
+.float platmovetype_start_default, platmovetype_end_default;
+bool set_platmovetype(entity e, string s)
+{
+       // sets platmovetype_start and platmovetype_end based on a string consisting of two values
+
+       int n = tokenize_console(s);
+       if(n > 0)
+               e.platmovetype_start = stof(argv(0));
+       else
+               e.platmovetype_start = 0;
+
+       if(n > 1)
+               e.platmovetype_end = stof(argv(1));
+       else
+               e.platmovetype_end = e.platmovetype_start;
+
+       if(n > 2)
+               if(argv(2) == "force")
+                       return true; // no checking, return immediately
+
+       if(!cubic_speedfunc_is_sane(e.platmovetype_start, e.platmovetype_end))
+       {
+               objerror("Invalid platform move type; platform would go in reverse, which is not allowed.");
+               return false;
+       }
+
+       return true;
+}
diff --git a/qcsrc/common/triggers/platforms.qh b/qcsrc/common/triggers/platforms.qh
new file mode 100644 (file)
index 0000000..e0a581b
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef PLATFORMS_H
+#define PLATFORMS_H
+
+.float dmgtime2;
+
+void() plat_center_touch;
+void() plat_outside_touch;
+void() plat_trigger_use;
+void() plat_go_up;
+void() plat_go_down;
+void() plat_crush;
+const float PLAT_LOW_TRIGGER = 1;
+
+.float dmg;
+
+#endif
diff --git a/qcsrc/common/triggers/subs.qc b/qcsrc/common/triggers/subs.qc
new file mode 100644 (file)
index 0000000..f21455d
--- /dev/null
@@ -0,0 +1,392 @@
+void SUB_NullThink(void) { }
+
+void()  SUB_CalcMoveDone;
+void() SUB_CalcAngleMoveDone;
+//void() SUB_UseTargets;
+
+/*
+==================
+SUB_Remove
+
+Remove self
+==================
+*/
+void SUB_Remove()
+{
+       remove (self);
+}
+
+/*
+==================
+SUB_Friction
+
+Applies some friction to self
+==================
+*/
+.float friction;
+void SUB_Friction (void)
+{
+       self.SUB_NEXTTHINK = time;
+       if(self.SUB_FLAGS & FL_ONGROUND)
+               self.SUB_VELOCITY = self.SUB_VELOCITY * (1 - frametime * self.friction);
+}
+
+/*
+==================
+SUB_VanishOrRemove
+
+Makes client invisible or removes non-client
+==================
+*/
+void SUB_VanishOrRemove (entity ent)
+{
+       if (IS_CLIENT(ent))
+       {
+               // vanish
+               ent.alpha = -1;
+               ent.effects = 0;
+#ifdef SVQC
+               ent.glow_size = 0;
+               ent.pflags = 0;
+#endif
+       }
+       else
+       {
+               // remove
+               remove (ent);
+       }
+}
+
+void SUB_SetFade_Think (void)
+{
+       if(self.alpha == 0)
+               self.alpha = 1;
+       self.SUB_THINK = SUB_SetFade_Think;
+       self.SUB_NEXTTHINK = time;
+       self.alpha -= frametime * self.fade_rate;
+       if (self.alpha < 0.01)
+               SUB_VanishOrRemove(self);
+       else
+               self.SUB_NEXTTHINK = time;
+}
+
+/*
+==================
+SUB_SetFade
+
+Fade 'ent' out when time >= 'when'
+==================
+*/
+void SUB_SetFade (entity ent, float when, float fading_time)
+{
+       ent.fade_rate = 1/fading_time;
+       ent.SUB_THINK = SUB_SetFade_Think;
+       ent.SUB_NEXTTHINK = when;
+}
+
+/*
+=============
+SUB_CalcMove
+
+calculate self.SUB_VELOCITY and self.SUB_NEXTTHINK to reach dest from
+self.SUB_ORIGIN traveling at speed
+===============
+*/
+void SUB_CalcMoveDone (void)
+{
+       // After moving, set origin to exact final destination
+
+       SUB_SETORIGIN (self, self.finaldest);
+       self.SUB_VELOCITY = '0 0 0';
+       self.SUB_NEXTTHINK = -1;
+       if (self.think1)
+               self.think1 ();
+}
+
+.float platmovetype_turn;
+void SUB_CalcMove_controller_think (void)
+{
+       entity oldself;
+       float traveltime;
+       float phasepos;
+       float nexttick;
+       vector delta;
+       vector delta2;
+       vector veloc;
+       vector angloc;
+       vector nextpos;
+       delta = self.destvec;
+       delta2 = self.destvec2;
+       if(time < self.animstate_endtime)
+       {
+               nexttick = time + PHYS_INPUT_FRAMETIME;
+
+               traveltime = self.animstate_endtime - self.animstate_starttime;
+               phasepos = (nexttick - self.animstate_starttime) / traveltime; // range: [0, 1]
+               phasepos = cubic_speedfunc(self.platmovetype_start, self.platmovetype_end, phasepos);
+               nextpos = self.origin + (delta * phasepos) + (delta2 * phasepos * phasepos);
+               // derivative: delta + 2 * delta2 * phasepos (e.g. for angle positioning)
+
+               if(self.owner.platmovetype_turn)
+               {
+                       vector destangle;
+                       destangle = delta + 2 * delta2 * phasepos;
+                       destangle = vectoangles(destangle);
+                       destangle_x = -destangle_x; // flip up / down orientation
+
+                       // take the shortest distance for the angles
+                       SUB_ANGLES(self.owner)_x -= 360 * floor((SUB_ANGLES(self.owner)_x - destangle_x) / 360 + 0.5);
+                       SUB_ANGLES(self.owner)_y -= 360 * floor((SUB_ANGLES(self.owner)_y - destangle_y) / 360 + 0.5);
+                       SUB_ANGLES(self.owner)_z -= 360 * floor((SUB_ANGLES(self.owner)_z - destangle_z) / 360 + 0.5);
+                       angloc = destangle - SUB_ANGLES(self.owner);
+                       angloc = angloc * (1 / PHYS_INPUT_FRAMETIME); // so it arrives for the next frame
+                       self.owner.SUB_AVELOCITY = angloc;
+               }
+               if(nexttick < self.animstate_endtime)
+                       veloc = nextpos - self.owner.SUB_ORIGIN;
+               else
+                       veloc = self.finaldest - self.owner.SUB_ORIGIN;
+               veloc = veloc * (1 / PHYS_INPUT_FRAMETIME); // so it arrives for the next frame
+
+               self.owner.SUB_VELOCITY = veloc;
+               self.nextthink = nexttick;
+       }
+       else
+       {
+               // derivative: delta + 2 * delta2 (e.g. for angle positioning)
+               oldself = self;
+               self.owner.SUB_THINK = self.think1;
+               self = self.owner;
+               remove(oldself);
+               self.SUB_THINK();
+       }
+}
+
+void SUB_CalcMove_controller_setbezier (entity controller, vector org, vector control, vector destin)
+{
+       // 0 * (1-t) * (1-t) + 2 * control * t * (1-t) + destin * t * t
+       // 2 * control * t - 2 * control * t * t + destin * t * t
+       // 2 * control * t + (destin - 2 * control) * t * t
+
+       setorigin(controller, org);
+       control -= org;
+       destin -= org;
+
+       controller.destvec = 2 * control; // control point
+       controller.destvec2 = destin - 2 * control; // quadratic part required to reach end point
+       // also: initial d/dphasepos origin = 2 * control, final speed = 2 * (destin - control)
+}
+
+void SUB_CalcMove_controller_setlinear (entity controller, vector org, vector destin)
+{
+       // 0 * (1-t) * (1-t) + 2 * control * t * (1-t) + destin * t * t
+       // 2 * control * t - 2 * control * t * t + destin * t * t
+       // 2 * control * t + (destin - 2 * control) * t * t
+
+       setorigin(controller, org);
+       destin -= org;
+
+       controller.destvec = destin; // end point
+       controller.destvec2 = '0 0 0';
+}
+
+float TSPEED_TIME = -1;
+float TSPEED_LINEAR = 0;
+float TSPEED_START = 1;
+float TSPEED_END = 2;
+// TODO average too?
+
+void SUB_CalcMove_Bezier (vector tcontrol, vector tdest, float tspeedtype, float tspeed, void() func)
+{
+       float   traveltime;
+       entity controller;
+
+       if (!tspeed)
+               objerror ("No speed is defined!");
+
+       self.think1 = func;
+       self.finaldest = tdest;
+       self.SUB_THINK = SUB_CalcMoveDone;
+
+       switch(tspeedtype)
+       {
+               default:
+               case TSPEED_START:
+                       traveltime = 2 * vlen(tcontrol - self.SUB_ORIGIN) / tspeed;
+                       break;
+               case TSPEED_END:
+                       traveltime = 2 * vlen(tcontrol - tdest)       / tspeed;
+                       break;
+               case TSPEED_LINEAR:
+                       traveltime = vlen(tdest - self.SUB_ORIGIN)        / tspeed;
+                       break;
+               case TSPEED_TIME:
+                       traveltime = tspeed;
+                       break;
+       }
+
+       if (traveltime < 0.1) // useless anim
+       {
+               self.SUB_VELOCITY = '0 0 0';
+               self.SUB_NEXTTHINK = self.SUB_LTIME + 0.1;
+               return;
+       }
+
+       controller = spawn();
+       controller.classname = "SUB_CalcMove_controller";
+       controller.owner = self;
+       controller.platmovetype = self.platmovetype;
+       controller.platmovetype_start = self.platmovetype_start;
+       controller.platmovetype_end = self.platmovetype_end;
+       SUB_CalcMove_controller_setbezier(controller, self.SUB_ORIGIN, tcontrol, tdest);
+       controller.finaldest = (tdest + '0 0 0.125'); // where do we want to end? Offset to overshoot a bit.
+       controller.animstate_starttime = time;
+       controller.animstate_endtime = time + traveltime;
+       controller.think = SUB_CalcMove_controller_think;
+       controller.think1 = self.SUB_THINK;
+
+       // the thinking is now done by the controller
+       self.SUB_THINK = SUB_NullThink; // for PushMove
+       self.SUB_NEXTTHINK = self.SUB_LTIME + traveltime;
+
+       // invoke controller
+       self = controller;
+       self.think();
+       self = self.owner;
+}
+
+void SUB_CalcMove (vector tdest, float tspeedtype, float tspeed, void() func)
+{
+       vector  delta;
+       float   traveltime;
+
+       if (!tspeed)
+               objerror ("No speed is defined!");
+
+       self.think1 = func;
+       self.finaldest = tdest;
+       self.SUB_THINK = SUB_CalcMoveDone;
+
+       if (tdest == self.SUB_ORIGIN)
+       {
+               self.SUB_VELOCITY = '0 0 0';
+               self.SUB_NEXTTHINK = self.SUB_LTIME + 0.1;
+               return;
+       }
+
+       delta = tdest - self.SUB_ORIGIN;
+
+       switch(tspeedtype)
+       {
+               default:
+               case TSPEED_START:
+               case TSPEED_END:
+               case TSPEED_LINEAR:
+                       traveltime = vlen (delta) / tspeed;
+                       break;
+               case TSPEED_TIME:
+                       traveltime = tspeed;
+                       break;
+       }
+
+       // Very short animations don't really show off the effect
+       // of controlled animation, so let's just use linear movement.
+       // Alternatively entities can choose to specify non-controlled movement.
+        // The only currently implemented alternative movement is linear (value 1)
+       if (traveltime < 0.15 || (self.platmovetype_start == 1 && self.platmovetype_end == 1)) // is this correct?
+       {
+               self.SUB_VELOCITY = delta * (1/traveltime);     // QuakeC doesn't allow vector/float division
+               self.SUB_NEXTTHINK = self.SUB_LTIME + traveltime;
+               return;
+       }
+
+       // now just run like a bezier curve...
+       SUB_CalcMove_Bezier((self.SUB_ORIGIN + tdest) * 0.5, tdest, tspeedtype, tspeed, func);
+}
+
+void SUB_CalcMoveEnt (entity ent, vector tdest, float tspeedtype, float tspeed, void() func)
+{
+       entity  oldself;
+
+       oldself = self;
+       self = ent;
+
+       SUB_CalcMove (tdest, tspeedtype, tspeed, func);
+
+       self = oldself;
+}
+
+/*
+=============
+SUB_CalcAngleMove
+
+calculate self.SUB_AVELOCITY and self.SUB_NEXTTHINK to reach destangle from
+self.angles rotating
+
+The calling function should make sure self.SUB_THINK is valid
+===============
+*/
+void SUB_CalcAngleMoveDone (void)
+{
+       // After rotating, set angle to exact final angle
+       self.angles = self.finalangle;
+       self.SUB_AVELOCITY = '0 0 0';
+       self.SUB_NEXTTHINK = -1;
+       if (self.think1)
+               self.think1 ();
+}
+
+// FIXME: I fixed this function only for rotation around the main axes
+void SUB_CalcAngleMove (vector destangle, float tspeedtype, float tspeed, void() func)
+{
+       vector  delta;
+       float   traveltime;
+
+       if (!tspeed)
+               objerror ("No speed is defined!");
+
+       // take the shortest distance for the angles
+       self.angles_x -= 360 * floor((self.angles_x - destangle_x) / 360 + 0.5);
+       self.angles_y -= 360 * floor((self.angles_y - destangle_y) / 360 + 0.5);
+       self.angles_z -= 360 * floor((self.angles_z - destangle_z) / 360 + 0.5);
+       delta = destangle - self.angles;
+
+       switch(tspeedtype)
+       {
+               default:
+               case TSPEED_START:
+               case TSPEED_END:
+               case TSPEED_LINEAR:
+                       traveltime = vlen (delta) / tspeed;
+                       break;
+               case TSPEED_TIME:
+                       traveltime = tspeed;
+                       break;
+       }
+
+       self.think1 = func;
+       self.finalangle = destangle;
+       self.SUB_THINK = SUB_CalcAngleMoveDone;
+
+       if (traveltime < 0.1)
+       {
+               self.SUB_AVELOCITY = '0 0 0';
+               self.SUB_NEXTTHINK = self.SUB_LTIME + 0.1;
+               return;
+       }
+
+       self.SUB_AVELOCITY = delta * (1 / traveltime);
+       self.SUB_NEXTTHINK = self.SUB_LTIME + traveltime;
+}
+
+void SUB_CalcAngleMoveEnt (entity ent, vector destangle, float tspeedtype, float tspeed, void() func)
+{
+       entity  oldself;
+
+       oldself = self;
+       self = ent;
+
+       SUB_CalcAngleMove (destangle, tspeedtype, tspeed, func);
+
+       self = oldself;
+}
diff --git a/qcsrc/common/triggers/subs.qh b/qcsrc/common/triggers/subs.qh
new file mode 100644 (file)
index 0000000..ea8ef30
--- /dev/null
@@ -0,0 +1,108 @@
+#ifndef SUBS_H
+#define SUBS_H
+
+#ifdef SVQC
+
+       #define SUB_ANGLES(s)           (s).angles
+       #define SUB_VELOCITY            velocity
+       #define SUB_AVELOCITY           avelocity
+       #define SUB_ORIGIN                      origin
+       #define SUB_SETORIGIN(s,v)      setorigin((s), (v))
+       #define SUB_NEXTTHINK           nextthink
+       #define SUB_THINK                       think
+       #define SUB_LTIME                       ltime
+       #define SUB_FLAGS                       flags
+
+#elif defined(CSQC)
+
+       void _Movetype_LinkEdict(float touch_triggers);
+
+       #define SUB_ANGLES(s)   (s).move_angles
+       #define SUB_VELOCITY    move_velocity
+       #define SUB_AVELOCITY   move_avelocity
+       #define SUB_ORIGIN              move_origin
+       #define SUB_NEXTTHINK   move_nextthink
+       #define SUB_THINK               move_think
+       #define SUB_LTIME               move_ltime
+       #define SUB_FLAGS               move_flags
+
+       void SUB_SETORIGIN(entity s, vector v)
+       {
+               s.move_origin = v;
+               entity oldself = self;
+               self = s;
+               _Movetype_LinkEdict(true);
+               self = oldself;
+       }
+
+#endif
+
+void SUB_Remove();
+void SUB_SetFade (entity ent, float when, float fading_time);
+void SUB_VanishOrRemove (entity ent);
+
+.vector                finaldest, finalangle;          //plat.qc stuff
+.void()                think1;
+.float state;
+.float         t_length, t_width;
+
+.vector destvec;
+.vector destvec2;
+
+// player animation state
+.float animstate_startframe;
+.float animstate_numframes;
+.float animstate_framerate;
+.float animstate_starttime;
+.float animstate_endtime;
+.float animstate_override;
+.float animstate_looping;
+
+.float delay;
+.float wait;
+.float lip;
+.float speed;
+.float sounds;
+.string  platmovetype;
+.float platmovetype_start, platmovetype_end;
+
+entity activator;
+
+.string killtarget;
+
+.vector        pos1, pos2;
+.vector        mangle;
+
+.string target2;
+.string target3;
+.string target4;
+.string curvetarget;
+.float target_random;
+.float trigger_reverse;
+
+// Keys player is holding
+.float itemkeys;
+// message delay for func_door locked by keys and key locks
+// this field is used on player entities
+.float key_door_messagetime;
+
+.vector dest1, dest2;
+
+#ifdef CSQC
+// this stuff is defined in the server side engine VM, so we must define it separately here
+.float takedamage;
+const float DAMAGE_NO  = 0;
+const float DAMAGE_YES = 1;
+const float DAMAGE_AIM = 2;
+
+float  STATE_TOP               = 0;
+float  STATE_BOTTOM    = 1;
+float  STATE_UP                = 2;
+float  STATE_DOWN              = 3;
+
+.string                noise, noise1, noise2, noise3;  // contains names of wavs to play
+
+.float         max_health;             // players maximum health is stored here
+#endif
+
+#endif
diff --git a/qcsrc/common/triggers/target/changelevel.qc b/qcsrc/common/triggers/target/changelevel.qc
new file mode 100644 (file)
index 0000000..1ec8cc9
--- /dev/null
@@ -0,0 +1,18 @@
+#ifdef SVQC
+.string chmap, gametype;
+void spawnfunc_target_changelevel_use()
+{
+       if(self.gametype != "")
+               MapInfo_SwitchGameType(MapInfo_Type_FromString(self.gametype));
+
+       if (self.chmap == "")
+               localcmd("endmatch\n");
+       else
+               localcmd(strcat("changelevel ", self.chmap, "\n"));
+}
+
+void spawnfunc_target_changelevel()
+{
+       self.use = spawnfunc_target_changelevel_use;
+}
+#endif
diff --git a/qcsrc/common/triggers/target/include.qc b/qcsrc/common/triggers/target/include.qc
new file mode 100644 (file)
index 0000000..c53ea6d
--- /dev/null
@@ -0,0 +1,8 @@
+#include "include.qh"
+
+#include "changelevel.qc"
+#include "location.qc"
+#include "music.qc"
+#include "spawn.qc"
+#include "speaker.qc"
+#include "voicescript.qc"
diff --git a/qcsrc/common/triggers/target/include.qh b/qcsrc/common/triggers/target/include.qh
new file mode 100644 (file)
index 0000000..4e44b97
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef TRIGGERS_TARGET_INCLUDE_H
+#define TRIGGERS_TARGET_INCLUDE_H
+
+#include "music.qh"
+
+#endif
diff --git a/qcsrc/common/triggers/target/location.qc b/qcsrc/common/triggers/target/location.qc
new file mode 100644 (file)
index 0000000..1430cab
--- /dev/null
@@ -0,0 +1,14 @@
+#ifdef SVQC
+void spawnfunc_target_location()
+{
+    self.classname = "target_location";
+    // location name in netname
+    // eventually support: count, teamgame selectors, line of sight?
+}
+
+void spawnfunc_info_location()
+{
+    self.classname = "target_location";
+    self.message = self.netname;
+}
+#endif
diff --git a/qcsrc/common/triggers/target/music.qc b/qcsrc/common/triggers/target/music.qc
new file mode 100644 (file)
index 0000000..4594c90
--- /dev/null
@@ -0,0 +1,329 @@
+#if defined(CSQC)
+#elif defined(MENUQC)
+#elif defined(SVQC)
+    #include "../../../server/_all.qh"
+    #include "../../constants.qh"
+    #include "../../../server/constants.qh"
+    #include "../../../server/defs.qh"
+#endif
+
+#ifdef SVQC
+
+// values:
+//   volume
+//   noise
+//   targetname
+//   lifetime
+//   fade_time
+//   fade_rate
+// when triggered, the music is overridden for activator until lifetime (or forever, if lifetime is 0)
+// when targetname is not set, THIS ONE is default
+void target_music_sendto(float to, float is)
+{
+       WriteByte(to, SVC_TEMPENTITY);
+       WriteByte(to, TE_CSQC_TARGET_MUSIC);
+       WriteShort(to, num_for_edict(self));
+       WriteByte(to, self.volume * 255.0 * is);
+       WriteByte(to, self.fade_time * 16.0);
+       WriteByte(to, self.fade_rate * 16.0);
+       WriteByte(to, self.lifetime);
+       WriteString(to, self.noise);
+}
+void target_music_reset()
+{
+       if(self.targetname == "")
+               target_music_sendto(MSG_ALL, 1);
+}
+void target_music_use()
+{
+       if(!activator)
+               return;
+       if(IS_REAL_CLIENT(activator))
+       {
+               msg_entity = activator;
+               target_music_sendto(MSG_ONE, 1);
+       }
+       entity head;
+       FOR_EACH_SPEC(head) if(head.enemy == activator) { msg_entity = head; target_music_sendto(MSG_ONE, 1); }
+}
+void spawnfunc_target_music()
+{
+       self.use = target_music_use;
+       self.reset = target_music_reset;
+       if(!self.volume)
+               self.volume = 1;
+       if(self.targetname == "")
+               target_music_sendto(MSG_INIT, 1);
+       else
+               target_music_sendto(MSG_INIT, 0);
+}
+void TargetMusic_RestoreGame()
+{
+       for(self = world; (self = find(self, classname, "target_music")); )
+       {
+               if(self.targetname == "")
+                       target_music_sendto(MSG_INIT, 1);
+               else
+                       target_music_sendto(MSG_INIT, 0);
+       }
+}
+// values:
+//   volume
+//   noise
+//   targetname
+//   fade_time
+// spawnflags:
+//   1 = START_OFF
+// when triggered, it is disabled/enabled for everyone
+float trigger_music_SendEntity(entity to, float sf)
+{
+       WriteByte(MSG_ENTITY, ENT_CLIENT_TRIGGER_MUSIC);
+       sf &= ~0x80;
+       if(self.cnt)
+               sf |= 0x80;
+       WriteByte(MSG_ENTITY, sf);
+       if(sf & 4)
+       {
+               WriteCoord(MSG_ENTITY, self.origin.x);
+               WriteCoord(MSG_ENTITY, self.origin.y);
+               WriteCoord(MSG_ENTITY, self.origin.z);
+       }
+       if(sf & 1)
+       {
+               if(self.model != "null")
+               {
+                       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);
+               }
+               else
+               {
+                       WriteShort(MSG_ENTITY, 0);
+                       WriteCoord(MSG_ENTITY, self.maxs.x);
+                       WriteCoord(MSG_ENTITY, self.maxs.y);
+                       WriteCoord(MSG_ENTITY, self.maxs.z);
+               }
+               WriteByte(MSG_ENTITY, self.volume * 255.0);
+               WriteByte(MSG_ENTITY, self.fade_time * 16.0);
+               WriteByte(MSG_ENTITY, self.fade_rate * 16.0);
+               WriteString(MSG_ENTITY, self.noise);
+       }
+       return 1;
+}
+void trigger_music_reset()
+{
+       self.cnt = !(self.spawnflags & 1);
+       self.SendFlags |= 0x80;
+}
+void trigger_music_use()
+{
+       self.cnt = !self.cnt;
+       self.SendFlags |= 0x80;
+}
+void spawnfunc_trigger_music()
+{
+       if(self.model != "")
+               setmodel(self, self.model);
+       if(!self.volume)
+               self.volume = 1;
+       if(!self.modelindex)
+       {
+               setorigin(self, self.origin + self.mins);
+               setsize(self, '0 0 0', self.maxs - self.mins);
+       }
+       trigger_music_reset();
+
+       self.use = trigger_music_use;
+       self.reset = trigger_music_reset;
+
+       Net_LinkEntity(self, false, 0, trigger_music_SendEntity);
+}
+#elif defined(CSQC)
+
+void TargetMusic_Advance()
+{
+       // run AFTER all the thinks!
+       entity best, e;
+       float vol, vol0;
+       best = music_default;
+       if(music_target && time < music_target.lifetime)
+               best = music_target;
+       if(music_trigger)
+               best = music_trigger;
+       for(e = world; (e = findfloat(e, enttype, ENT_CLIENT_TRIGGER_MUSIC)); ) if(e.noise)
+       {
+               vol0 = e.lastvol;
+               if(getsoundtime(e, CH_BGM_SINGLE) < 0)
+               {
+                       vol0 = -1;
+               }
+               if(e == best)
+               {
+                       // increase volume
+                       if(e.fade_time > 0)
+                               e.state = bound(0, e.state + frametime / e.fade_time, 1);
+                       else
+                               e.state = 1;
+               }
+               else
+               {
+                       // decrease volume
+                       if(e.fade_rate > 0)
+                               e.state = bound(0, e.state - frametime / e.fade_rate, 1);
+                       else
+                               e.state = 0;
+               }
+               vol = e.state * e.volume * autocvar_bgmvolume;
+               if(vol != vol0)
+               {
+                       if(vol0 < 0)
+                               sound(e, CH_BGM_SINGLE, e.noise, vol, ATTEN_NONE); // restart
+                       else
+                               sound(e, CH_BGM_SINGLE, "", vol, ATTEN_NONE);
+                       e.lastvol = vol;
+               }
+       }
+       music_trigger = world;
+
+       if(best)
+               bgmtime = getsoundtime(best, CH_BGM_SINGLE);
+       else
+               bgmtime = gettime(GETTIME_CDTRACK);
+}
+
+void Net_TargetMusic()
+{
+       int id = ReadShort();
+       float vol = ReadByte() / 255.0;
+       float fai = ReadByte() / 16.0;
+       float fao = ReadByte() / 16.0;
+       float tim = ReadByte();
+       string noi = ReadString();
+
+       entity e;
+       for(e = world; (e = findfloat(e, enttype, ENT_CLIENT_TRIGGER_MUSIC)); )
+       {
+               if(e.count == id)
+                       break;
+       }
+       if(!e)
+       {
+               e = spawn();
+               e.enttype = ENT_CLIENT_TRIGGER_MUSIC;
+               e.count = id;
+       }
+       if(e.noise != noi)
+       {
+               if(e.noise)
+                       strunzone(e.noise);
+               e.noise = strzone(noi);
+               precache_sound(e.noise);
+               sound(e, CH_BGM_SINGLE, e.noise, 0, ATTEN_NONE);
+               if(getsoundtime(e, CH_BGM_SINGLE) < 0)
+               {
+                       dprintf("Cannot initialize sound %s\n", e.noise);
+                       strunzone(e.noise);
+                       e.noise = string_null;
+               }
+       }
+       e.volume = vol;
+       e.fade_time = fai;
+       e.fade_rate = fao;
+       if(vol > 0)
+       {
+               if(tim == 0)
+               {
+                       music_default = e;
+                       if(!music_disabled)
+                       {
+                               e.state = 2;
+                               cvar_settemp("music_playlist_index", "-1"); // don't use playlists
+                               localcmd("cd stop\n"); // just in case
+                               music_disabled = 1;
+                       }
+               }
+               else
+               {
+                       music_target = e;
+                       e.lifetime = time + tim;
+               }
+       }
+}
+
+void Ent_TriggerMusic_Think()
+{
+       if(WarpZoneLib_BoxTouchesBrush(view_origin, view_origin, self, world))
+       {
+               music_trigger = self;
+       }
+       self.nextthink = time;
+}
+
+void Ent_TriggerMusic_Remove()
+{
+       if(self.noise)
+               strunzone(self.noise);
+       self.noise = string_null;
+}
+
+void Ent_ReadTriggerMusic()
+{
+       int f = ReadByte();
+       if(f & 4)
+       {
+               self.origin_x = ReadCoord();
+               self.origin_y = ReadCoord();
+               self.origin_z = ReadCoord();
+       }
+       if(f & 1)
+       {
+               self.modelindex = ReadShort();
+               if(self.modelindex)
+               {
+                       self.mins_x = ReadCoord();
+                       self.mins_y = ReadCoord();
+                       self.mins_z = ReadCoord();
+                       self.maxs_x = ReadCoord();
+                       self.maxs_y = ReadCoord();
+                       self.maxs_z = ReadCoord();
+               }
+               else
+               {
+                       self.mins    = '0 0 0';
+                       self.maxs_x = ReadCoord();
+                       self.maxs_y = ReadCoord();
+                       self.maxs_z = ReadCoord();
+               }
+
+               self.volume = ReadByte() / 255.0;
+               self.fade_time = ReadByte() / 16.0;
+               self.fade_rate = ReadByte() / 16.0;
+               string s = self.noise;
+               if(self.noise)
+                       strunzone(self.noise);
+               self.noise = strzone(ReadString());
+               if(self.noise != s)
+               {
+                       precache_sound(self.noise);
+                       sound(self, CH_BGM_SINGLE, self.noise, 0, ATTEN_NONE);
+                       if(getsoundtime(self, CH_BGM_SINGLE) < 0)
+                       {
+                               dprintf("Cannot initialize sound %s\n", self.noise);
+                               strunzone(self.noise);
+                               self.noise = string_null;
+                       }
+               }
+       }
+
+       setorigin(self, self.origin);
+       setsize(self, self.mins, self.maxs);
+       self.cnt = 1;
+       self.think = Ent_TriggerMusic_Think;
+       self.nextthink = time;
+}
+
+#endif
diff --git a/qcsrc/common/triggers/target/music.qh b/qcsrc/common/triggers/target/music.qh
new file mode 100644 (file)
index 0000000..712d412
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef TARGET_MUSIC_H
+#define TARGET_MUSIC_H
+
+.float lifetime;
+
+#ifdef CSQC
+float music_disabled;
+entity music_default;
+entity music_target;
+entity music_trigger;
+// FIXME also control bgmvolume here, to not require a target_music for the default track.
+
+entityclass(TargetMusic);
+class(TargetMusic) .int state;
+class(TargetMusic) .float lastvol;
+
+void TargetMusic_Advance();
+
+void Net_TargetMusic();
+
+void Ent_TriggerMusic_Think();
+
+void Ent_TriggerMusic_Remove();
+
+void Ent_ReadTriggerMusic();
+#endif
+
+#endif
diff --git a/qcsrc/common/triggers/target/spawn.qc b/qcsrc/common/triggers/target/spawn.qc
new file mode 100644 (file)
index 0000000..f5c54b5
--- /dev/null
@@ -0,0 +1,349 @@
+#if defined(CSQC)
+#elif defined(MENUQC)
+#elif defined(SVQC)
+       #include "../../../server/_all.qh"
+    #include "../../util.qh"
+    #include "../../../server/defs.qh"
+#endif
+
+#ifdef SVQC
+
+// spawner entity
+// "classname" "target_spawn"
+// "message" "fieldname value fieldname value ..."
+// "spawnflags"
+//   1 = call the spawn function
+//   2 = trigger on map load
+
+float target_spawn_initialized;
+.void() target_spawn_spawnfunc;
+float target_spawn_spawnfunc_field;
+.entity target_spawn_activator;
+.float target_spawn_id;
+float target_spawn_count;
+
+void target_spawn_helper_setmodel()
+{
+       setmodel(self, self.model);
+}
+
+void target_spawn_helper_setsize()
+{
+       setsize(self, self.mins, self.maxs);
+}
+
+void target_spawn_edit_entity(entity e, string msg, entity kt, entity t2, entity t3, entity t4, entity act)
+{
+       float i, n, valuefieldpos;
+       string key, value, valuefield, valueoffset, valueoffsetrandom;
+       entity valueent;
+       vector data, data2;
+       entity oldself;
+       entity oldactivator;
+
+       n = tokenize_console(msg);
+
+       for(i = 0; i < n-1; i += 2)
+       {
+               key = argv(i);
+               value = argv(i+1);
+               if(key == "$")
+               {
+                       data.x = -1;
+                       data.y = FIELD_STRING;
+               }
+               else
+               {
+                       data = stov(db_get(TemporaryDB, strcat("/target_spawn/field/", key)));
+                       if(data.y == 0) // undefined field, i.e., invalid type
+                       {
+                               print("target_spawn: invalid/unknown entity key ", key, " specified, ignored!\n");
+                               continue;
+                       }
+               }
+               if(substring(value, 0, 1) == "$")
+               {
+                       value = substring(value, 1, strlen(value) - 1);
+                       if(substring(value, 0, 1) == "$")
+                       {
+                               // deferred replacement
+                               // do nothing
+                               // useful for creating target_spawns with this!
+                       }
+                       else
+                       {
+                               // replace me!
+                               valuefieldpos = strstrofs(value, "+", 0);
+                               valueoffset = "";
+                               if(valuefieldpos != -1)
+                               {
+                                       valueoffset = substring(value, valuefieldpos + 1, strlen(value) - valuefieldpos - 1);
+                                       value = substring(value, 0, valuefieldpos);
+                               }
+
+                               valuefieldpos = strstrofs(valueoffset, "+", 0);
+                               valueoffsetrandom = "";
+                               if(valuefieldpos != -1)
+                               {
+                                       valueoffsetrandom = substring(valueoffset, valuefieldpos + 1, strlen(valueoffset) - valuefieldpos - 1);
+                                       valueoffset = substring(valueoffset, 0, valuefieldpos);
+                               }
+
+                               valuefieldpos = strstrofs(value, ".", 0);
+                               valuefield = "";
+                               if(valuefieldpos != -1)
+                               {
+                                       valuefield = substring(value, valuefieldpos + 1, strlen(value) - valuefieldpos - 1);
+                                       value = substring(value, 0, valuefieldpos);
+                               }
+
+                               if(value == "self")
+                               {
+                                       valueent = self;
+                                       value = "";
+                               }
+                               else if(value == "activator")
+                               {
+                                       valueent = act;
+                                       value = "";
+                               }
+                               else if(value == "other")
+                               {
+                                       valueent = other;
+                                       value = "";
+                               }
+                               else if(value == "pusher")
+                               {
+                                       if(time < act.pushltime)
+                                               valueent = act.pusher;
+                                       else
+                                               valueent = world;
+                                       value = "";
+                               }
+                               else if(value == "target")
+                               {
+                                       valueent = e;
+                                       value = "";
+                               }
+                               else if(value == "killtarget")
+                               {
+                                       valueent = kt;
+                                       value = "";
+                               }
+                               else if(value == "target2")
+                               {
+                                       valueent = t2;
+                                       value = "";
+                               }
+                               else if(value == "target3")
+                               {
+                                       valueent = t3;
+                                       value = "";
+                               }
+                               else if(value == "target4")
+                               {
+                                       valueent = t4;
+                                       value = "";
+                               }
+                               else if(value == "time")
+                               {
+                                       valueent = world;
+                                       value = ftos(time);
+                               }
+                               else
+                               {
+                                       print("target_spawn: invalid/unknown variable replacement ", value, " specified, ignored!\n");
+                                       continue;
+                               }
+
+                               if(valuefield == "")
+                               {
+                                       if(value == "")
+                                               value = ftos(num_for_edict(valueent));
+                               }
+                               else
+                               {
+                                       if(value != "")
+                                       {
+                                               print("target_spawn: try to get a field of a non-entity, ignored!\n");
+                                               continue;
+                                       }
+                                       data2 = stov(db_get(TemporaryDB, strcat("/target_spawn/field/", valuefield)));
+                                       if(data2_y == 0) // undefined field, i.e., invalid type
+                                       {
+                                               print("target_spawn: invalid/unknown entity key replacement ", valuefield, " specified, ignored!\n");
+                                               continue;
+                                       }
+                                       value = getentityfieldstring(data2_x, valueent);
+                               }
+
+                               if(valueoffset != "")
+                               {
+                                       switch(data.y)
+                                       {
+                                               case FIELD_STRING:
+                                                       value = strcat(value, valueoffset);
+                                                       break;
+                                               case FIELD_FLOAT:
+                                                       value = ftos(stof(value) + stof(valueoffset));
+                                                       break;
+                                               case FIELD_VECTOR:
+                                                       value = vtos(stov(value) + stov(valueoffset));
+                                                       break;
+                                               default:
+                                                       print("target_spawn: only string, float and vector fields can do calculations, calculation ignored!\n");
+                                                       break;
+                                       }
+                               }
+
+                               if(valueoffsetrandom != "")
+                               {
+                                       switch(data.y)
+                                       {
+                                               case FIELD_FLOAT:
+                                                       value = ftos(stof(value) + random() * stof(valueoffsetrandom));
+                                                       break;
+                                               case FIELD_VECTOR:
+                                                       data2 = stov(valueoffsetrandom);
+                                                       value = vtos(stov(value) + random() * data2_x * '1 0 0' + random() * data2_y * '0 1 0' + random() * data2_z * '0 0 1');
+                                                       break;
+                                               default:
+                                                       print("target_spawn: only float and vector fields can do random calculations, calculation ignored!\n");
+                                                       break;
+                                       }
+                               }
+                       }
+               }
+               if(key == "$")
+               {
+                       if(substring(value, 0, 1) == "_")
+                               value = strcat("target_spawn_helper", value);
+                       putentityfieldstring(target_spawn_spawnfunc_field, e, value);
+
+                       oldself = self;
+                       oldactivator = activator;
+
+                       self = e;
+                       activator = act;
+
+                       self.target_spawn_spawnfunc();
+
+                       self = oldself;
+                       activator = oldactivator;
+
+                       // We called an external function, so we have to re-tokenize msg.
+                       n = tokenize_console(msg);
+               }
+               else
+               {
+                       if(data.y == FIELD_VECTOR)
+                               value = strreplace("'", "", value); // why?!?
+                       putentityfieldstring(data.x, e, value);
+               }
+       }
+}
+
+void target_spawn_useon(entity e)
+{
+       self.target_spawn_activator = activator;
+       target_spawn_edit_entity(
+               e,
+               self.message,
+               find(world, targetname, self.killtarget),
+               find(world, targetname, self.target2),
+               find(world, targetname, self.target3),
+               find(world, targetname, self.target4),
+               activator
+       );
+}
+
+float target_spawn_cancreate()
+{
+       float c;
+       entity e;
+
+       c = self.count;
+       if(c == 0) // no limit?
+               return 1;
+
+       ++c; // increase count to not include MYSELF
+       for(e = world; (e = findfloat(e, target_spawn_id, self.target_spawn_id)); --c)
+               ;
+
+       // if c now is 0, we have AT LEAST the given count (maybe more), so don't spawn any more
+       if(c == 0)
+               return 0;
+       return 1;
+}
+
+void target_spawn_use()
+{
+       entity e;
+
+       if(self.target == "")
+       {
+               // spawn new entity
+               if(!target_spawn_cancreate())
+                       return;
+               e = spawn();
+               target_spawn_useon(e);
+               e.target_spawn_id = self.target_spawn_id;
+       }
+       else if(self.target == "*activator")
+       {
+               // edit entity
+               if(activator)
+                       target_spawn_useon(activator);
+       }
+       else
+       {
+               // edit entity
+               for(e = world; (e = find(e, targetname, self.target)); )
+                       target_spawn_useon(e);
+       }
+}
+
+void target_spawn_spawnfirst()
+{
+       activator = self.target_spawn_activator;
+       if(self.spawnflags & 2)
+               target_spawn_use();
+}
+
+void initialize_field_db()
+{
+       if(!target_spawn_initialized)
+       {
+               float n, i;
+               string fn;
+               vector prev, next;
+               float ft;
+
+               n = numentityfields();
+               for(i = 0; i < n; ++i)
+               {
+                       fn = entityfieldname(i);
+                       ft = entityfieldtype(i);
+                       next = i * '1 0 0' + ft * '0 1 0' + '0 0 1';
+                       prev = stov(db_get(TemporaryDB, strcat("/target_spawn/field/", fn)));
+                       if(prev.y == 0)
+                       {
+                               db_put(TemporaryDB, strcat("/target_spawn/field/", fn), vtos(next));
+                               if(fn == "target_spawn_spawnfunc")
+                                       target_spawn_spawnfunc_field = i;
+                       }
+               }
+
+               target_spawn_initialized = 1;
+       }
+}
+
+void spawnfunc_target_spawn()
+{
+       initialize_field_db();
+       self.use = target_spawn_use;
+       self.message = strzone(strreplace("'", "\"", self.message));
+       self.target_spawn_id = ++target_spawn_count;
+       InitializeEntity(self, target_spawn_spawnfirst, INITPRIO_LAST);
+}
+#endif
diff --git a/qcsrc/common/triggers/target/speaker.qc b/qcsrc/common/triggers/target/speaker.qc
new file mode 100644 (file)
index 0000000..7be8b91
--- /dev/null
@@ -0,0 +1,133 @@
+#ifdef SVQC
+// TODO add a way to do looped sounds with sound(); then complete this entity
+void target_speaker_use_off();
+void target_speaker_use_activator()
+{
+       if (!IS_REAL_CLIENT(activator))
+               return;
+       string snd;
+       if(substring(self.noise, 0, 1) == "*")
+       {
+               var .string sample;
+               sample = GetVoiceMessageSampleField(substring(self.noise, 1, -1));
+               if(GetPlayerSoundSampleField_notFound)
+                       snd = "misc/null.wav";
+               else if(activator.sample == "")
+                       snd = "misc/null.wav";
+               else
+               {
+                       tokenize_console(activator.sample);
+                       float n;
+                       n = stof(argv(1));
+                       if(n > 0)
+                               snd = strcat(argv(0), ftos(floor(random() * n + 1)), ".wav"); // randomization
+                       else
+                               snd = strcat(argv(0), ".wav"); // randomization
+               }
+       }
+       else
+               snd = self.noise;
+       msg_entity = activator;
+       soundto(MSG_ONE, self, CH_TRIGGER, snd, VOL_BASE * self.volume, self.atten);
+}
+void target_speaker_use_on()
+{
+       string snd;
+       if(substring(self.noise, 0, 1) == "*")
+       {
+               var .string sample;
+               sample = GetVoiceMessageSampleField(substring(self.noise, 1, -1));
+               if(GetPlayerSoundSampleField_notFound)
+                       snd = "misc/null.wav";
+               else if(activator.sample == "")
+                       snd = "misc/null.wav";
+               else
+               {
+                       tokenize_console(activator.sample);
+                       float n;
+                       n = stof(argv(1));
+                       if(n > 0)
+                               snd = strcat(argv(0), ftos(floor(random() * n + 1)), ".wav"); // randomization
+                       else
+                               snd = strcat(argv(0), ".wav"); // randomization
+               }
+       }
+       else
+               snd = self.noise;
+       sound(self, CH_TRIGGER_SINGLE, snd, VOL_BASE * self.volume, self.atten);
+       if(self.spawnflags & 3)
+               self.use = target_speaker_use_off;
+}
+void target_speaker_use_off()
+{
+       sound(self, CH_TRIGGER_SINGLE, "misc/null.wav", VOL_BASE * self.volume, self.atten);
+       self.use = target_speaker_use_on;
+}
+void target_speaker_reset()
+{
+       if(self.spawnflags & 1) // LOOPED_ON
+       {
+               if(self.use == target_speaker_use_on)
+                       target_speaker_use_on();
+       }
+       else if(self.spawnflags & 2)
+       {
+               if(self.use == target_speaker_use_off)
+                       target_speaker_use_off();
+       }
+}
+
+void spawnfunc_target_speaker()
+{
+       // TODO: "*" prefix to sound file name
+       // TODO: wait and random (just, HOW? random is not a field)
+       if(self.noise)
+               precache_sound (self.noise);
+
+       if(!self.atten && !(self.spawnflags & 4))
+       {
+               IFTARGETED
+                       self.atten = ATTEN_NORM;
+               else
+                       self.atten = ATTEN_STATIC;
+       }
+       else if(self.atten < 0)
+               self.atten = 0;
+
+       if(!self.volume)
+               self.volume = 1;
+
+       IFTARGETED
+       {
+               if(self.spawnflags & 8) // ACTIVATOR
+                       self.use = target_speaker_use_activator;
+               else if(self.spawnflags & 1) // LOOPED_ON
+               {
+                       target_speaker_use_on();
+                       self.reset = target_speaker_reset;
+               }
+               else if(self.spawnflags & 2) // LOOPED_OFF
+               {
+                       self.use = target_speaker_use_on;
+                       self.reset = target_speaker_reset;
+               }
+               else
+                       self.use = target_speaker_use_on;
+       }
+       else if(self.spawnflags & 1) // LOOPED_ON
+       {
+               ambientsound (self.origin, self.noise, VOL_BASE * self.volume, self.atten);
+               remove(self);
+       }
+       else if(self.spawnflags & 2) // LOOPED_OFF
+       {
+               objerror("This sound entity can never be activated");
+       }
+       else
+       {
+               // Quake/Nexuiz fallback
+               ambientsound (self.origin, self.noise, VOL_BASE * self.volume, self.atten);
+               remove(self);
+       }
+}
+#endif
diff --git a/qcsrc/common/triggers/target/voicescript.qc b/qcsrc/common/triggers/target/voicescript.qc
new file mode 100644 (file)
index 0000000..c173d80
--- /dev/null
@@ -0,0 +1,101 @@
+#ifdef SVQC
+.entity voicescript; // attached voice script
+.float voicescript_index; // index of next voice, or -1 to use the randomized ones
+.float voicescript_nextthink; // time to play next voice
+.float voicescript_voiceend; // time when this voice ends
+
+void target_voicescript_clear(entity pl)
+{
+       pl.voicescript = world;
+}
+
+void target_voicescript_use()
+{
+       if(activator.voicescript != self)
+       {
+               activator.voicescript = self;
+               activator.voicescript_index = 0;
+               activator.voicescript_nextthink = time + self.delay;
+       }
+}
+
+void target_voicescript_next(entity pl)
+{
+       entity vs;
+       float i, n, dt;
+
+       vs = pl.voicescript;
+       if(!vs)
+               return;
+       if(vs.message == "")
+               return;
+       if (!IS_PLAYER(pl))
+               return;
+       if(gameover)
+               return;
+
+       if(time >= pl.voicescript_voiceend)
+       {
+               if(time >= pl.voicescript_nextthink)
+               {
+                       // get the next voice...
+                       n = tokenize_console(vs.message);
+
+                       if(pl.voicescript_index < vs.cnt)
+                               i = pl.voicescript_index * 2;
+                       else if(n > vs.cnt * 2)
+                               i = ((pl.voicescript_index - vs.cnt) % ((n - vs.cnt * 2 - 1) / 2)) * 2 + vs.cnt * 2 + 1;
+                       else
+                               i = -1;
+
+                       if(i >= 0)
+                       {
+                               play2(pl, strcat(vs.netname, "/", argv(i), ".wav"));
+                               dt = stof(argv(i + 1));
+                               if(dt >= 0)
+                               {
+                                       pl.voicescript_voiceend = time + dt;
+                                       pl.voicescript_nextthink = pl.voicescript_voiceend + vs.wait * (0.5 + random());
+                               }
+                               else
+                               {
+                                       pl.voicescript_voiceend = time - dt;
+                                       pl.voicescript_nextthink = pl.voicescript_voiceend;
+                               }
+
+                               pl.voicescript_index += 1;
+                       }
+                       else
+                       {
+                               pl.voicescript = world; // stop trying then
+                       }
+               }
+       }
+}
+
+void spawnfunc_target_voicescript()
+{
+       // netname: directory of the sound files
+       // message: list of "sound file" duration "sound file" duration, a *, and again a list
+       //          foo1 4.1 foo2 4.0 foo3 -3.1 * fool1 1.1 fool2 7.1 fool3 9.1 fool4 3.7
+       //          Here, a - in front of the duration means that no delay is to be
+       //          added after this message
+       // wait: average time between messages
+       // delay: initial delay before the first message
+
+       float i, n;
+       self.use = target_voicescript_use;
+
+       n = tokenize_console(self.message);
+       self.cnt = n / 2;
+       for(i = 0; i+1 < n; i += 2)
+       {
+               if(argv(i) == "*")
+               {
+                       self.cnt = i / 2;
+                       ++i;
+               }
+               precache_sound(strcat(self.netname, "/", argv(i), ".wav"));
+       }
+}
+#endif
diff --git a/qcsrc/common/triggers/teleporters.qc b/qcsrc/common/triggers/teleporters.qc
new file mode 100644 (file)
index 0000000..a5d89f5
--- /dev/null
@@ -0,0 +1,253 @@
+#include "teleporters.qh"
+
+#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 "../constants.qh"
+       #include "../triggers/subs.qh"
+    #include "../util.qh"
+    #include "../../server/weapons/csqcprojectile.qh"
+    #include "../../server/autocvars.qh"
+    #include "../../server/constants.qh"
+    #include "../../server/defs.qh"
+    #include "../deathtypes.qh"
+    #include "../../server/tturrets/include/turrets_early.qh"
+    #include "../../server/vehicles/all.qh"
+    #include "../mapinfo.qh"
+    #include "../../server/anticheat.qh"
+#endif
+
+#ifdef SVQC
+
+float check_tdeath(entity player, vector org, vector telefragmin, vector telefragmax)
+{
+       if (IS_PLAYER(player) && player.health >= 1)
+       {
+               TDEATHLOOP(org)
+               {
+                       if (!(teamplay && autocvar_g_telefrags_teamplay && head.team == player.team))
+                               if(IS_PLAYER(head))
+                                       if(head.health >= 1)
+                                               return 1;
+               }
+       }
+       return 0;
+}
+
+void tdeath(entity player, entity teleporter, entity telefragger, vector telefragmin, vector telefragmax)
+{
+       TDEATHLOOP(player.origin)
+       {
+               if (IS_PLAYER(player) && player.health >= 1)
+               {
+                       if (!(teamplay && autocvar_g_telefrags_teamplay && head.team == player.team))
+                       {
+                               if(IS_PLAYER(head))
+                                       if(head.health >= 1)
+                                               ++tdeath_hit;
+                               Damage (head, teleporter, telefragger, 10000, DEATH_TELEFRAG, head.origin, '0 0 0');
+                       }
+               }
+               else // dead bodies and monsters gib themselves instead of telefragging
+                       Damage (telefragger, teleporter, telefragger, 10000, DEATH_TELEFRAG, telefragger.origin, '0 0 0');
+       }
+}
+
+void spawn_tdeath(vector v0, entity e, vector v)
+{
+       tdeath(e, e, e, '0 0 0', '0 0 0');
+}
+
+void TeleportPlayer(entity teleporter, entity player, vector to, vector to_angles, vector to_velocity, vector telefragmin, vector telefragmax, float tflags)
+{
+       entity telefragger;
+       vector from;
+
+       if(teleporter.owner)
+               telefragger = teleporter.owner;
+       else
+               telefragger = player;
+
+       makevectors (to_angles);
+
+       if(player.teleportable == TELEPORT_NORMAL) // don't play sounds or show particles for anything that isn't a player, maybe change later to block only observers
+       {
+               if(self.pushltime < time) // only show one teleport effect per teleporter per 0.2 seconds, for better fps
+               {
+                       if(tflags & TELEPORT_FLAG_SOUND)
+                               sound (player, CH_TRIGGER, "misc/teleport.wav", VOL_BASE, ATTEN_NORM);
+                       if(tflags & TELEPORT_FLAG_PARTICLES)
+                       {
+                               pointparticles(particleeffectnum("teleport"), player.origin, '0 0 0', 1);
+                               pointparticles(particleeffectnum("teleport"), to + v_forward * 32, '0 0 0', 1);
+                       }
+                       self.pushltime = time + 0.2;
+               }
+       }
+
+       // Relocate the player
+       // assuming to allows PL_MIN to PL_MAX box and some more
+       from = player.origin;
+       setorigin (player, to);
+       player.oldorigin = to; // don't undo the teleport by unsticking
+       player.angles = to_angles;
+       player.fixangle = true;
+       player.velocity = to_velocity;
+       BITXOR_ASSIGN(player.effects, EF_TELEPORT_BIT);
+
+       makevectors(player.angles);
+       Reset_ArcBeam(player, v_forward);
+       UpdateCSQCProjectileAfterTeleport(player);
+
+       if(IS_PLAYER(player))
+       {
+               if(tflags & TELEPORT_FLAG_TDEATH)
+                       if(player.takedamage && player.deadflag == DEAD_NO && !g_race && !g_cts && (autocvar_g_telefrags || (tflags & TELEPORT_FLAG_FORCE_TDEATH)))
+                               tdeath(player, teleporter, telefragger, telefragmin, telefragmax);
+
+               // player no longer is on ground
+               player.flags &= ~FL_ONGROUND;
+
+               // reset tracking of oldvelocity for impact damage (sudden velocity changes)
+               player.oldvelocity = player.velocity;
+
+               // reset tracking of who pushed you into a hazard (for kill credit)
+               if(teleporter.owner)
+               {
+                       player.pusher = teleporter.owner;
+                       player.pushltime = time + autocvar_g_maxpushtime;
+                       player.istypefrag = player.BUTTON_CHAT;
+               }
+               else
+               {
+                       player.pushltime = 0;
+                       player.istypefrag = 0;
+               }
+
+               player.lastteleporttime = time;
+       }
+}
+
+entity Simple_TeleportPlayer(entity teleporter, entity player)
+{
+       vector locout;
+       entity e;
+       float p;
+
+       // Find the output teleporter
+       if(teleporter.enemy)
+       {
+               e = teleporter.enemy;
+       }
+       else
+       {
+               RandomSelection_Init();
+               for(e = world; (e = find(e, targetname, teleporter.target)); )
+               {
+                       p = 1;
+                       if(autocvar_g_telefrags_avoid)
+                       {
+                               locout = e.origin + '0 0 1' * (1 - player.mins.z - 24);
+                               if(check_tdeath(player, locout, '0 0 0', '0 0 0'))
+                                       p = 0;
+                       }
+                       RandomSelection_Add(e, 0, string_null, (e.cnt ? e.cnt : 1), p);
+               }
+               e = RandomSelection_chosen_ent;
+       }
+
+       if(!e) { sprint(player, "Teleport destination vanished. Sorry... please complain to the mapper.\n"); }
+
+       makevectors(e.mangle);
+
+       if(e.speed)
+               if(vlen(player.velocity) > e.speed)
+                       player.velocity = normalize(player.velocity) * max(0, e.speed);
+
+       if(autocvar_g_teleport_maxspeed)
+               if(vlen(player.velocity) > autocvar_g_teleport_maxspeed)
+                       player.velocity = normalize(player.velocity) * max(0, autocvar_g_teleport_maxspeed);
+
+       locout = e.origin + '0 0 1' * (1 - player.mins.z - 24);
+       TeleportPlayer(teleporter, player, locout, e.mangle, v_forward * vlen(player.velocity), '0 0 0', '0 0 0', TELEPORT_FLAGS_TELEPORTER);
+
+       return e;
+}
+
+void teleport_findtarget (void)
+{
+       entity e;
+       float n;
+
+       n = 0;
+       for(e = world; (e = find(e, targetname, self.target)); )
+       {
+               ++n;
+               if(e.movetype == MOVETYPE_NONE)
+                       waypoint_spawnforteleporter(self, e.origin, 0);
+               if(e.classname != "info_teleport_destination")
+                       print("^3MAPPER ERROR: teleporter does target an invalid teleport destination entity. Angles will not work.\n");
+       }
+
+       if(n == 0)
+       {
+               // no dest!
+               objerror ("Teleporter with nonexistant target");
+               return;
+       }
+       else if(n == 1)
+       {
+               // exactly one dest - bots love that
+               self.enemy = find(e, targetname, self.target);
+       }
+       else
+       {
+               // have to use random selection every single time
+               self.enemy = world;
+       }
+
+       // now enable touch
+       self.touch = Teleport_Touch;
+}
+
+entity Teleport_Find(vector mi, vector ma)
+{
+       entity e;
+       for(e = world; (e = find(e, classname, "trigger_teleport")); )
+               if(WarpZoneLib_BoxTouchesBrush(mi, ma, e, world))
+                       return e;
+       return world;
+}
+
+void WarpZone_PostTeleportPlayer_Callback(entity pl)
+{
+       makevectors(pl.angles);
+       Reset_ArcBeam(pl, v_forward);
+       UpdateCSQCProjectileAfterTeleport(pl);
+       {
+               entity oldself = self;
+               self = pl;
+               anticheat_fixangle();
+               self = oldself;
+       }
+       // "disown" projectiles after teleport
+       if(pl.owner)
+       if(pl.owner == pl.realowner)
+       {
+               if(!(pl.flags & FL_PROJECTILE))
+                       print("A non-projectile got through a warpzone and its owner cleared. It's a ", pl.classname, ".\n");
+               pl.owner = world;
+       }
+       if(IS_PLAYER(pl))
+       {
+               // reset tracking of oldvelocity for impact damage (sudden velocity changes)
+               pl.oldvelocity = pl.velocity;
+               // reset teleport time tracking too (or multijump can cause insane speeds)
+               pl.lastteleporttime = time;
+       }
+}
+#endif
diff --git a/qcsrc/common/triggers/teleporters.qh b/qcsrc/common/triggers/teleporters.qh
new file mode 100644 (file)
index 0000000..bdd24dd
--- /dev/null
@@ -0,0 +1,68 @@
+#ifndef T_TELEPORTERS_H
+#define T_TELEPORTERS_H
+
+#ifdef SVQC
+
+void trigger_teleport_use();
+
+#define TDEATHLOOP(o) \
+       entity head; \
+       vector deathmin; \
+       vector deathmax; \
+       float deathradius; \
+       deathmin = (o) + player.mins; \
+       deathmax = (o) + player.maxs; \
+       if(telefragmin != telefragmax) \
+       { \
+               if(deathmin.x > telefragmin.x) deathmin.x = telefragmin.x; \
+               if(deathmin.y > telefragmin.y) deathmin.y = telefragmin.y; \
+               if(deathmin.z > telefragmin.z) deathmin.z = telefragmin.z; \
+               if(deathmax.x < telefragmax.x) deathmax.x = telefragmax.x; \
+               if(deathmax.y < telefragmax.y) deathmax.y = telefragmax.y; \
+               if(deathmax.z < telefragmax.z) deathmax.z = telefragmax.z; \
+       } \
+       deathradius = max(vlen(deathmin), vlen(deathmax)); \
+       for(head = findradius(o, deathradius); head; head = head.chain) \
+               if(head != player) \
+                       if(head.takedamage) \
+                               if(boxesoverlap(deathmin, deathmax, head.absmin, head.absmax))
+
+
+float check_tdeath(entity player, vector org, vector telefragmin, vector telefragmax);
+float tdeath_hit;
+void tdeath(entity player, entity teleporter, entity telefragger, vector telefragmin, vector telefragmax);
+
+void spawn_tdeath(vector v0, entity e, vector v);
+
+.entity pusher;
+const float TELEPORT_FLAG_SOUND = 1;
+const float TELEPORT_FLAG_PARTICLES = 2;
+const float TELEPORT_FLAG_TDEATH = 4;
+const float TELEPORT_FLAG_FORCE_TDEATH = 8;
+
+#define TELEPORT_FLAGS_WARPZONE   0
+#define TELEPORT_FLAGS_PORTAL     (TELEPORT_FLAG_SOUND | TELEPORT_FLAG_PARTICLES | TELEPORT_FLAG_TDEATH | TELEPORT_FLAG_FORCE_TDEATH)
+#define TELEPORT_FLAGS_TELEPORTER (TELEPORT_FLAG_SOUND | TELEPORT_FLAG_PARTICLES | TELEPORT_FLAG_TDEATH)
+
+// types for .teleportable entity setting
+const float TELEPORT_NORMAL = 1; // play sounds/effects etc
+const float TELEPORT_SIMPLE = 2; // only do teleport, nothing special
+
+void Reset_ArcBeam(entity player, vector forward);
+void TeleportPlayer(entity teleporter, entity player, vector to, vector to_angles, vector to_velocity, vector telefragmin, vector telefragmax, float tflags);
+
+entity Simple_TeleportPlayer(entity teleporter, entity player);
+
+void Teleport_Touch (void);
+
+void teleport_findtarget (void);
+
+entity Teleport_Find(vector mi, vector ma);
+
+entity teleport_first;
+.entity teleport_next;
+
+void WarpZone_PostTeleportPlayer_Callback(entity pl);
+#endif
+
+#endif
diff --git a/qcsrc/common/triggers/trigger/counter.qc b/qcsrc/common/triggers/trigger/counter.qc
new file mode 100644 (file)
index 0000000..bf1d9b2
--- /dev/null
@@ -0,0 +1,49 @@
+#ifdef SVQC
+void counter_use()
+{
+       self.count -= 1;
+       if (self.count < 0)
+               return;
+
+       if (self.count == 0)
+       {
+               if(IS_PLAYER(activator) && (self.spawnflags & SPAWNFLAG_NOMESSAGE) == 0)
+                       Send_Notification(NOTIF_ONE, activator, MSG_CENTER, CENTER_SEQUENCE_COMPLETED);
+
+               self.enemy = activator;
+               multi_trigger ();
+       }
+       else
+       {
+               if(IS_PLAYER(activator) && (self.spawnflags & SPAWNFLAG_NOMESSAGE) == 0)
+               if(self.count >= 4)
+                       Send_Notification(NOTIF_ONE, activator, MSG_CENTER, CENTER_SEQUENCE_COUNTER);
+               else
+                       Send_Notification(NOTIF_ONE, activator, MSG_CENTER, CENTER_SEQUENCE_COUNTER_FEWMORE, self.count);
+       }
+}
+
+void counter_reset()
+{
+       self.count = self.cnt;
+       multi_reset();
+}
+
+/*QUAKED spawnfunc_trigger_counter (.5 .5 .5) ? nomessage
+Acts as an intermediary for an action that takes multiple inputs.
+
+If nomessage is not set, t will print "1 more.. " etc when triggered and "sequence complete" when finished.
+
+After the counter has been triggered "count" times (default 2), it will fire all of it's targets and remove itself.
+*/
+void spawnfunc_trigger_counter()
+{
+       self.wait = -1;
+       if (!self.count)
+               self.count = 2;
+       self.cnt = self.count;
+
+       self.use = counter_use;
+       self.reset = counter_reset;
+}
+#endif
diff --git a/qcsrc/common/triggers/trigger/delay.qc b/qcsrc/common/triggers/trigger/delay.qc
new file mode 100644 (file)
index 0000000..b01efe3
--- /dev/null
@@ -0,0 +1,22 @@
+#ifdef SVQC
+void delay_use()
+{
+    self.think = SUB_UseTargets;
+   self.nextthink = self.wait;
+}
+
+void delay_reset()
+{
+       self.think = func_null;
+       self.nextthink = 0;
+}
+
+void spawnfunc_trigger_delay()
+{
+    if(!self.wait)
+        self.wait = 1;
+
+    self.use = delay_use;
+    self.reset = delay_reset;
+}
+#endif
diff --git a/qcsrc/common/triggers/trigger/disablerelay.qc b/qcsrc/common/triggers/trigger/disablerelay.qc
new file mode 100644 (file)
index 0000000..cd5fdff
--- /dev/null
@@ -0,0 +1,31 @@
+#ifdef SVQC
+void trigger_disablerelay_use()
+{
+       entity e;
+
+       float a, b;
+       a = b = 0;
+
+       for(e = world; (e = find(e, targetname, self.target)); )
+       {
+               if(e.use == SUB_UseTargets)
+               {
+                       e.use = SUB_DontUseTargets;
+                       ++a;
+               }
+               else if(e.use == SUB_DontUseTargets)
+               {
+                       e.use = SUB_UseTargets;
+                       ++b;
+               }
+       }
+
+       if((!a) == (!b))
+               print("Invalid use of trigger_disablerelay: ", ftos(a), " relays were on, ", ftos(b), " relays were off!\n");
+}
+
+void spawnfunc_trigger_disablerelay()
+{
+       self.use = trigger_disablerelay_use;
+}
+#endif
diff --git a/qcsrc/common/triggers/trigger/flipflop.qc b/qcsrc/common/triggers/trigger/flipflop.qc
new file mode 100644 (file)
index 0000000..12d8a59
--- /dev/null
@@ -0,0 +1,19 @@
+#ifdef SVQC
+/*QUAKED spawnfunc_trigger_flipflop (.5 .5 .5) (-8 -8 -8) (8 8 8) START_ENABLED
+"Flip-flop" trigger gate... lets only every second trigger event through
+*/
+void flipflop_use()
+{
+    self.state = !self.state;
+    if(self.state)
+        SUB_UseTargets();
+}
+
+void spawnfunc_trigger_flipflop()
+{
+    if(self.spawnflags & 1)
+        self.state = 1;
+    self.use = flipflop_use;
+    self.reset = spawnfunc_trigger_flipflop; // perfect resetter
+}
+#endif
diff --git a/qcsrc/common/triggers/trigger/gamestart.qc b/qcsrc/common/triggers/trigger/gamestart.qc
new file mode 100644 (file)
index 0000000..3ad419d
--- /dev/null
@@ -0,0 +1,22 @@
+#ifdef SVQC
+void gamestart_use()
+{
+       activator = self;
+       SUB_UseTargets();
+       remove(self);
+}
+
+void spawnfunc_trigger_gamestart()
+{
+       self.use = gamestart_use;
+       self.reset2 = spawnfunc_trigger_gamestart;
+
+       if(self.wait)
+       {
+               self.think = self.use;
+               self.nextthink = game_starttime + self.wait;
+       }
+       else
+               InitializeEntity(self, gamestart_use, INITPRIO_FINDTARGET);
+}
+#endif
diff --git a/qcsrc/common/triggers/trigger/gravity.qc b/qcsrc/common/triggers/trigger/gravity.qc
new file mode 100644 (file)
index 0000000..a709a1f
--- /dev/null
@@ -0,0 +1,106 @@
+#ifdef SVQC
+.entity trigger_gravity_check;
+void trigger_gravity_remove(entity own)
+{
+       if(own.trigger_gravity_check.owner == own)
+       {
+               UpdateCSQCProjectile(own);
+               own.gravity = own.trigger_gravity_check.gravity;
+               remove(own.trigger_gravity_check);
+       }
+       else
+               backtrace("Removing a trigger_gravity_check with no valid owner");
+       own.trigger_gravity_check = world;
+}
+void trigger_gravity_check_think()
+{
+       // This spawns when a player enters the gravity zone and checks if he left.
+       // Each frame, self.count is set to 2 by trigger_gravity_touch() and decreased by 1 here.
+       // It the player has left the gravity trigger, this will be allowed to reach 0 and indicate that.
+       if(self.count <= 0)
+       {
+               if(self.owner.trigger_gravity_check == self)
+                       trigger_gravity_remove(self.owner);
+               else
+                       remove(self);
+               return;
+       }
+       else
+       {
+               self.count -= 1;
+               self.nextthink = time;
+       }
+}
+
+void trigger_gravity_use()
+{
+       self.state = !self.state;
+}
+
+void trigger_gravity_touch()
+{
+       float g;
+
+       if(self.state != true)
+               return;
+
+       EXACTTRIGGER_TOUCH;
+
+       g = self.gravity;
+
+       if (!(self.spawnflags & 1))
+       {
+               if(other.trigger_gravity_check)
+               {
+                       if(self == other.trigger_gravity_check.enemy)
+                       {
+                               // same?
+                               other.trigger_gravity_check.count = 2; // gravity one more frame...
+                               return;
+                       }
+
+                       // compare prio
+                       if(self.cnt > other.trigger_gravity_check.enemy.cnt)
+                               trigger_gravity_remove(other);
+                       else
+                               return;
+               }
+               other.trigger_gravity_check = spawn();
+               other.trigger_gravity_check.enemy = self;
+               other.trigger_gravity_check.owner = other;
+               other.trigger_gravity_check.gravity = other.gravity;
+               other.trigger_gravity_check.think = trigger_gravity_check_think;
+               other.trigger_gravity_check.nextthink = time;
+               other.trigger_gravity_check.count = 2;
+               if(other.gravity)
+                       g *= other.gravity;
+       }
+
+       if (other.gravity != g)
+       {
+               other.gravity = g;
+               if(self.noise != "")
+                       sound (other, CH_TRIGGER, self.noise, VOL_BASE, ATTEN_NORM);
+               UpdateCSQCProjectile(self.owner);
+       }
+}
+
+void spawnfunc_trigger_gravity()
+{
+       if(self.gravity == 1)
+               return;
+
+       EXACTTRIGGER_INIT;
+       self.touch = trigger_gravity_touch;
+       if(self.noise != "")
+               precache_sound(self.noise);
+
+       self.state = true;
+       IFTARGETED
+       {
+               self.use = trigger_gravity_use;
+               if(self.spawnflags & 2)
+                       self.state = false;
+       }
+}
+#endif
diff --git a/qcsrc/common/triggers/trigger/heal.qc b/qcsrc/common/triggers/trigger/heal.qc
new file mode 100644 (file)
index 0000000..6d68610
--- /dev/null
@@ -0,0 +1,42 @@
+#ifdef SVQC
+.float triggerhealtime;
+void trigger_heal_touch()
+{
+       if (self.active != ACTIVE_ACTIVE)
+               return;
+
+       // only do the EXACTTRIGGER_TOUCH checks when really needed (saves some cpu)
+       if (other.iscreature)
+       {
+               if (other.takedamage)
+               if (!other.deadflag)
+               if (other.triggerhealtime < time)
+               {
+                       EXACTTRIGGER_TOUCH;
+                       other.triggerhealtime = time + 1;
+
+                       if (other.health < self.max_health)
+                       {
+                               other.health = min(other.health + self.health, self.max_health);
+                               other.pauserothealth_finished = max(other.pauserothealth_finished, time + autocvar_g_balance_pause_health_rot);
+                               sound (other, CH_TRIGGER, self.noise, VOL_BASE, ATTEN_NORM);
+                       }
+               }
+       }
+}
+
+void spawnfunc_trigger_heal()
+{
+       self.active = ACTIVE_ACTIVE;
+
+       EXACTTRIGGER_INIT;
+       self.touch = trigger_heal_touch;
+       if (!self.health)
+               self.health = 10;
+       if (!self.max_health)
+               self.max_health = 200; //Max health topoff for field
+       if(self.noise == "")
+               self.noise = "misc/mediumhealth.wav";
+       precache_sound(self.noise);
+}
+#endif
diff --git a/qcsrc/common/triggers/trigger/hurt.qc b/qcsrc/common/triggers/trigger/hurt.qc
new file mode 100644 (file)
index 0000000..3a15a77
--- /dev/null
@@ -0,0 +1,92 @@
+#ifdef SVQC
+void trigger_hurt_use()
+{
+       if(IS_PLAYER(activator))
+               self.enemy = activator;
+       else
+               self.enemy = world; // let's just destroy it, if taking over is too much work
+}
+
+.float triggerhurttime;
+void trigger_hurt_touch()
+{
+       if (self.active != ACTIVE_ACTIVE)
+               return;
+
+       if(self.team)
+               if(((self.spawnflags & 4) == 0) == (self.team != other.team))
+                       return;
+
+       // only do the EXACTTRIGGER_TOUCH checks when really needed (saves some cpu)
+       if (other.iscreature)
+       {
+               if (other.takedamage)
+               if (other.triggerhurttime < time)
+               {
+                       EXACTTRIGGER_TOUCH;
+                       other.triggerhurttime = time + 1;
+
+                       entity own;
+                       own = self.enemy;
+                       if (!IS_PLAYER(own))
+                       {
+                               own = self;
+                               self.enemy = world; // I still hate you all
+                       }
+
+                       Damage (other, self, own, self.dmg, DEATH_HURTTRIGGER, other.origin, '0 0 0');
+               }
+       }
+       else if(other.damagedbytriggers)
+       {
+               if(other.takedamage)
+               {
+                       EXACTTRIGGER_TOUCH;
+                       Damage(other, self, self, self.dmg, DEATH_HURTTRIGGER, other.origin, '0 0 0');
+               }
+       }
+
+       return;
+}
+
+/*QUAKED spawnfunc_trigger_hurt (.5 .5 .5) ?
+Any object touching this will be hurt
+set dmg to damage amount
+defalt dmg = 5
+*/
+.entity trigger_hurt_next;
+entity trigger_hurt_last;
+entity trigger_hurt_first;
+void spawnfunc_trigger_hurt()
+{
+       EXACTTRIGGER_INIT;
+       self.active = ACTIVE_ACTIVE;
+       self.touch = trigger_hurt_touch;
+       self.use = trigger_hurt_use;
+       self.enemy = world; // I hate you all
+       if (!self.dmg)
+               self.dmg = 1000;
+       if (self.message == "")
+               self.message = "was in the wrong place";
+       if (self.message2 == "")
+               self.message2 = "was thrown into a world of hurt by";
+       // self.message = "someone like %s always gets wrongplaced";
+
+       if(!trigger_hurt_first)
+               trigger_hurt_first = self;
+       if(trigger_hurt_last)
+               trigger_hurt_last.trigger_hurt_next = self;
+       trigger_hurt_last = self;
+}
+
+float tracebox_hits_trigger_hurt(vector start, vector mi, vector ma, vector end)
+{
+       entity th;
+
+       for(th = trigger_hurt_first; th; th = th.trigger_hurt_next)
+               if(tracebox_hits_box(start, mi, ma, end, th.absmin, th.absmax))
+                       return true;
+
+       return false;
+}
+#endif
diff --git a/qcsrc/common/triggers/trigger/impulse.qc b/qcsrc/common/triggers/trigger/impulse.qc
new file mode 100644 (file)
index 0000000..926268e
--- /dev/null
@@ -0,0 +1,194 @@
+// targeted (directional) mode
+void trigger_impulse_touch1()
+{
+       entity targ;
+       float pushdeltatime;
+       float str;
+
+       if (self.active != ACTIVE_ACTIVE)
+               return;
+
+       if (!isPushable(other))
+               return;
+
+       EXACTTRIGGER_TOUCH;
+
+       targ = find(world, targetname, self.target);
+       if(!targ)
+       {
+               objerror("trigger_force without a (valid) .target!\n");
+               remove(self);
+               return;
+       }
+
+       str = min(self.radius, vlen(self.origin - other.origin));
+
+       if(self.falloff == 1)
+               str = (str / self.radius) * self.strength;
+       else if(self.falloff == 2)
+               str = (1 - (str / self.radius)) * self.strength;
+       else
+               str = self.strength;
+
+       pushdeltatime = time - other.lastpushtime;
+       if (pushdeltatime > 0.15) pushdeltatime = 0;
+       other.lastpushtime = time;
+       if(!pushdeltatime) return;
+
+       other.velocity = other.velocity + normalize(targ.origin - self.origin) * str * pushdeltatime;
+       other.flags &= ~FL_ONGROUND;
+#ifdef SVQC
+       UpdateCSQCProjectile(other);
+#endif
+}
+
+// Directionless (accelerator/decelerator) mode
+void trigger_impulse_touch2()
+{
+       float pushdeltatime;
+
+       if (self.active != ACTIVE_ACTIVE)
+               return;
+
+       if (!isPushable(other))
+               return;
+
+       EXACTTRIGGER_TOUCH;
+
+       pushdeltatime = time - other.lastpushtime;
+       if (pushdeltatime > 0.15) pushdeltatime = 0;
+       other.lastpushtime = time;
+       if(!pushdeltatime) return;
+
+       // div0: ticrate independent, 1 = identity (not 20)
+       other.velocity = other.velocity * pow(self.strength, pushdeltatime);
+#ifdef SVQC
+       UpdateCSQCProjectile(other);
+#endif
+}
+
+// Spherical (gravity/repulsor) mode
+void trigger_impulse_touch3()
+{
+       float pushdeltatime;
+       float str;
+
+       if (self.active != ACTIVE_ACTIVE)
+               return;
+
+       if (!isPushable(other))
+               return;
+
+       EXACTTRIGGER_TOUCH;
+
+       pushdeltatime = time - other.lastpushtime;
+       if (pushdeltatime > 0.15) pushdeltatime = 0;
+       other.lastpushtime = time;
+       if(!pushdeltatime) return;
+
+       setsize(self, '-1 -1 -1' * self.radius,'1 1 1' * self.radius);
+
+       str = min(self.radius, vlen(self.origin - other.origin));
+
+       if(self.falloff == 1)
+               str = (1 - str / self.radius) * self.strength; // 1 in the inside
+       else if(self.falloff == 2)
+               str = (str / self.radius) * self.strength; // 0 in the inside
+       else
+               str = self.strength;
+
+       other.velocity = other.velocity + normalize(other.origin - self.origin) * str * pushdeltatime;
+#ifdef SVQC
+       UpdateCSQCProjectile(other);
+#endif
+}
+
+/*QUAKED spawnfunc_trigger_impulse (.5 .5 .5) ?
+-------- KEYS --------
+target : If this is set, this points to the spawnfunc_target_position to which the player will get pushed.
+                If not, this trigger acts like a damper/accelerator field.
+
+strength : This is how mutch force to add in the direction of .target each second
+                  when .target is set. If not, this is hoe mutch to slow down/accelerate
+                  someting cought inside this trigger. (1=no change, 0,5 half speed rougthly each tic, 2 = doubble)
+
+radius   : If set, act as a spherical device rather then a liniar one.
+
+falloff : 0 = none, 1 = liniar, 2 = inverted liniar
+
+-------- NOTES --------
+Use a brush textured with common/origin in the trigger entity to determine the origin of the force
+in directional and sperical mode. For damper/accelerator mode this is not nessesary (and has no effect).
+*/
+#ifdef SVQC
+bool trigger_impulse_send(entity to, int sf)
+{
+       WriteByte(MSG_ENTITY, ENT_CLIENT_TRIGGER_IMPULSE);
+
+       WriteCoord(MSG_ENTITY, self.radius);
+       WriteCoord(MSG_ENTITY, self.strength);
+       WriteByte(MSG_ENTITY, self.falloff);
+       WriteByte(MSG_ENTITY, self.active);
+
+       trigger_common_write(true);
+
+       return true;
+}
+
+void trigger_impulse_link()
+{
+       //Net_LinkEntity(self, 0, false, trigger_impulse_send);
+}
+
+void spawnfunc_trigger_impulse()
+{
+       self.active = ACTIVE_ACTIVE;
+
+       EXACTTRIGGER_INIT;
+       if(self.radius)
+       {
+               if(!self.strength) self.strength = 2000 * autocvar_g_triggerimpulse_radial_multiplier;
+               setorigin(self, self.origin);
+               setsize(self, '-1 -1 -1' * self.radius,'1 1 1' * self.radius);
+               self.touch = trigger_impulse_touch3;
+       }
+       else
+       {
+               if(self.target)
+               {
+                       if(!self.strength) self.strength = 950 * autocvar_g_triggerimpulse_directional_multiplier;
+                       self.touch = trigger_impulse_touch1;
+               }
+               else
+               {
+                       if(!self.strength) self.strength = 0.9;
+                       self.strength = pow(self.strength, autocvar_g_triggerimpulse_accel_power) * autocvar_g_triggerimpulse_accel_multiplier;
+                       self.touch = trigger_impulse_touch2;
+               }
+       }
+
+       trigger_impulse_link();
+}
+#elif defined(CSQC)
+void ent_trigger_impulse()
+{
+       self.radius = ReadCoord();
+       self.strength = ReadCoord();
+       self.falloff = ReadByte();
+       self.active = ReadByte();
+
+       trigger_common_read(true);
+
+
+       self.classname = "trigger_impulse";
+       self.solid = SOLID_TRIGGER;
+       self.entremove = trigger_remove_generic;
+       self.draw = trigger_draw_generic;
+       self.drawmask = MASK_NORMAL;
+       self.move_time = time;
+
+       if(self.radius) { self.trigger_touch = trigger_impulse_touch3; }
+       else if(self.target) { self.trigger_touch = trigger_impulse_touch1; }
+       else { self.trigger_touch = trigger_impulse_touch2; }
+}
+#endif
diff --git a/qcsrc/common/triggers/trigger/impulse.qh b/qcsrc/common/triggers/trigger/impulse.qh
new file mode 100644 (file)
index 0000000..a4c248d
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef TRIGGER_IMPULSE_H
+#define TRIGGER_IMPULSE_H
+
+// tZorks trigger impulse / gravity
+.float radius;
+.float falloff;
+.float strength;
+.float lastpushtime;
+
+#ifdef CSQC
+void ent_trigger_impulse();
+#endif
+
+#endif
diff --git a/qcsrc/common/triggers/trigger/include.qc b/qcsrc/common/triggers/trigger/include.qc
new file mode 100644 (file)
index 0000000..1498634
--- /dev/null
@@ -0,0 +1,24 @@
+#include "include.qh"
+
+#include "counter.qc"
+#include "delay.qc"
+#include "disablerelay.qc"
+#include "flipflop.qc"
+#include "gamestart.qc"
+#include "gravity.qc"
+#include "heal.qc"
+#include "hurt.qc"
+#include "impulse.qc"
+#include "jumppads.qc"
+#include "keylock.qc"
+#include "magicear.qc"
+#include "monoflop.qc"
+#include "multi.qc"
+#include "multivibrator.qc"
+#include "relay.qc"
+#include "relay_activators.qc"
+#include "relay_if.qc"
+#include "relay_teamcheck.qc"
+#include "secret.qc"
+#include "swamp.qc"
+#include "teleport.qc"
diff --git a/qcsrc/common/triggers/trigger/include.qh b/qcsrc/common/triggers/trigger/include.qh
new file mode 100644 (file)
index 0000000..1601143
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef TRIGGERS_TRIGGER_INCLUDE_H
+#define TRIGGERS_TRIGGER_INCLUDE_H
+
+#include "multi.qh"
+#include "jumppads.qh"
+#include "secret.qh"
+#include "swamp.qh"
+#include "keylock.qh"
+#include "impulse.qh"
+
+#endif
diff --git a/qcsrc/common/triggers/trigger/jumppads.qc b/qcsrc/common/triggers/trigger/jumppads.qc
new file mode 100644 (file)
index 0000000..6c6675e
--- /dev/null
@@ -0,0 +1,475 @@
+// TODO: split target_push and put it in the target folder
+#ifdef SVQC
+#include "../../../server/_all.qh"
+#include "jumppads.qh"
+#include "../../movetypes/movetypes.qh"
+
+void trigger_push_use()
+{
+       if(teamplay)
+       {
+               self.team = activator.team;
+               self.SendFlags |= 2;
+       }
+}
+#endif
+
+/*
+       trigger_push_calculatevelocity
+
+       Arguments:
+         org - origin of the object which is to be pushed
+         tgt - target entity (can be either a point or a model entity; if it is
+               the latter, its midpoint is used)
+         ht  - jump height, measured from the higher one of org and tgt's midpoint
+
+       Returns: velocity for the jump
+       the global trigger_push_calculatevelocity_flighttime is set to the total
+       jump time
+ */
+
+vector trigger_push_calculatevelocity(vector org, entity tgt, float ht)
+{
+       float grav, sdist, zdist, vs, vz, jumpheight;
+       vector sdir, torg;
+
+       torg = tgt.origin + (tgt.mins + tgt.maxs) * 0.5;
+
+       grav = PHYS_GRAVITY;
+       if(PHYS_ENTGRAVITY(other))
+               grav *= PHYS_ENTGRAVITY(other);
+
+       zdist = torg.z - org.z;
+       sdist = vlen(torg - org - zdist * '0 0 1');
+       sdir = normalize(torg - org - zdist * '0 0 1');
+
+       // how high do we need to push the player?
+       jumpheight = fabs(ht);
+       if(zdist > 0)
+               jumpheight = jumpheight + zdist;
+
+       /*
+               STOP.
+
+               You will not understand the following equations anyway...
+               But here is what I did to get them.
+
+               I used the functions
+
+                 s(t) = t * vs
+                 z(t) = t * vz - 1/2 grav t^2
+
+               and solved for:
+
+                 s(ti) = sdist
+                 z(ti) = zdist
+                 max(z, ti) = jumpheight
+
+               From these three equations, you will find the three parameters vs, vz
+               and ti.
+        */
+
+       // push him so high...
+       vz = sqrt(fabs(2 * grav * jumpheight)); // NOTE: sqrt(positive)!
+
+       // we start with downwards velocity only if it's a downjump and the jump apex should be outside the jump!
+       if(ht < 0)
+               if(zdist < 0)
+                       vz = -vz;
+
+       vector solution;
+       solution = solve_quadratic(0.5 * grav, -vz, zdist); // equation "z(ti) = zdist"
+       // ALWAYS solvable because jumpheight >= zdist
+       if(!solution.z)
+               solution_y = solution.x; // just in case it is not solvable due to roundoff errors, assume two equal solutions at their center (this is mainly for the usual case with ht == 0)
+       if(zdist == 0)
+               solution_x = solution.y; // solution_x is 0 in this case, so don't use it, but rather use solution_y (which will be sqrt(0.5 * jumpheight / grav), actually)
+
+       if(zdist < 0)
+       {
+               // down-jump
+               if(ht < 0)
+               {
+                       // almost straight line type
+                       // jump apex is before the jump
+                       // we must take the larger one
+                       trigger_push_calculatevelocity_flighttime = solution.y;
+               }
+               else
+               {
+                       // regular jump
+                       // jump apex is during the jump
+                       // we must take the larger one too
+                       trigger_push_calculatevelocity_flighttime = solution.y;
+               }
+       }
+       else
+       {
+               // up-jump
+               if(ht < 0)
+               {
+                       // almost straight line type
+                       // jump apex is after the jump
+                       // we must take the smaller one
+                       trigger_push_calculatevelocity_flighttime = solution.x;
+               }
+               else
+               {
+                       // regular jump
+                       // jump apex is during the jump
+                       // we must take the larger one
+                       trigger_push_calculatevelocity_flighttime = solution.y;
+               }
+       }
+       vs = sdist / trigger_push_calculatevelocity_flighttime;
+
+       // finally calculate the velocity
+       return sdir * vs + '0 0 1' * vz;
+}
+
+void trigger_push_touch()
+{
+       if (self.active == ACTIVE_NOT)
+               return;
+
+#ifdef SVQC
+       if (!isPushable(other))
+               return;
+#endif
+
+       if(self.team)
+               if(((self.spawnflags & 4) == 0) == (DIFF_TEAM(self, other)))
+                       return;
+
+       EXACTTRIGGER_TOUCH;
+
+       if(self.enemy)
+       {
+               other.velocity = trigger_push_calculatevelocity(other.origin, self.enemy, self.height);
+               other.move_velocity = other.velocity;
+       }
+       else if(self.target)
+       {
+               entity e;
+               RandomSelection_Init();
+               for(e = world; (e = find(e, targetname, self.target)); )
+               {
+                       if(e.cnt)
+                               RandomSelection_Add(e, 0, string_null, e.cnt, 1);
+                       else
+                               RandomSelection_Add(e, 0, string_null, 1, 1);
+               }
+               other.velocity = trigger_push_calculatevelocity(other.origin, RandomSelection_chosen_ent, self.height);
+               other.move_velocity = other.velocity;
+       }
+       else
+       {
+               other.velocity = self.movedir;
+               other.move_velocity = other.velocity;
+       }
+
+       UNSET_ONGROUND(other);
+
+       other.move_flags &= ~FL_ONGROUND;
+
+#ifdef SVQC
+       if (IS_PLAYER(other))
+       {
+               // reset tracking of oldvelocity for impact damage (sudden velocity changes)
+               other.oldvelocity = other.velocity;
+
+               if(self.pushltime < time)  // prevent "snorring" sound when a player hits the jumppad more than once
+               {
+                       // flash when activated
+                       pointparticles(particleeffectnum("jumppad_activate"), other.origin, other.velocity, 1);
+                       sound (other, CH_TRIGGER, self.noise, VOL_BASE, ATTEN_NORM);
+                       self.pushltime = time + 0.2;
+               }
+               if(IS_REAL_CLIENT(other) || IS_BOT_CLIENT(other))
+               {
+                       bool found = false;
+                       for(int i = 0; i < other.jumppadcount && i < NUM_JUMPPADSUSED; ++i)
+                               if(other.(jumppadsused[i]) == self)
+                                       found = true;
+                       if(!found)
+                       {
+                               other.(jumppadsused[other.jumppadcount % NUM_JUMPPADSUSED]) = self;
+                               other.jumppadcount = other.jumppadcount + 1;
+                       }
+
+                       if(IS_REAL_CLIENT(other))
+                       {
+                               if(self.message)
+                                       centerprint(other, self.message);
+                       }
+                       else
+                               other.lastteleporttime = time;
+
+                       if (other.deadflag == DEAD_NO)
+                               animdecide_setaction(other, ANIMACTION_JUMP, true);
+               }
+               else
+                       other.jumppadcount = true;
+
+               // reset tracking of who pushed you into a hazard (for kill credit)
+               other.pushltime = 0;
+               other.istypefrag = 0;
+       }
+
+       if(self.enemy.target)
+       {
+               entity oldself;
+               oldself = self;
+               activator = other;
+               self = self.enemy;
+               SUB_UseTargets();
+               self = oldself;
+       }
+
+       if (other.flags & FL_PROJECTILE)
+       {
+               other.angles = vectoangles (other.velocity);
+               switch(other.movetype)
+               {
+                       case MOVETYPE_FLY:
+                               other.movetype = MOVETYPE_TOSS;
+                               other.gravity = 1;
+                               break;
+                       case MOVETYPE_BOUNCEMISSILE:
+                               other.movetype = MOVETYPE_BOUNCE;
+                               other.gravity = 1;
+                               break;
+               }
+               UpdateCSQCProjectile(other);
+       }
+
+       if (self.spawnflags & PUSH_ONCE)
+       {
+               self.touch = func_null;
+               self.think = SUB_Remove;
+               self.nextthink = time;
+       }
+#endif
+}
+
+#ifdef SVQC
+void trigger_push_link();
+void trigger_push_updatelink();
+#endif
+void trigger_push_findtarget()
+{
+       entity t;
+       vector org;
+
+       // first calculate a typical start point for the jump
+       org = (self.absmin + self.absmax) * 0.5;
+       org_z = self.absmax.z - PL_MIN.z;
+
+       if (self.target)
+       {
+               float n = 0;
+               for(t = world; (t = find(t, targetname, self.target)); )
+               {
+                       ++n;
+#ifdef SVQC
+                       entity e = spawn();
+                       setorigin(e, org);
+                       setsize(e, PL_MIN, PL_MAX);
+                       e.velocity = trigger_push_calculatevelocity(org, t, self.height);
+                       tracetoss(e, e);
+                       if(e.movetype == MOVETYPE_NONE)
+                               waypoint_spawnforteleporter(self, trace_endpos, vlen(trace_endpos - org) / vlen(e.velocity));
+                       remove(e);
+#endif
+               }
+
+               if(!n)
+               {
+                       // no dest!
+#ifdef SVQC
+                       objerror ("Jumppad with nonexistant target");
+#endif
+                       return;
+               }
+               else if(n == 1)
+               {
+                       // exactly one dest - bots love that
+                       self.enemy = find(world, targetname, self.target);
+               }
+               else
+               {
+                       // have to use random selection every single time
+                       self.enemy = world;
+               }
+       }
+#ifdef SVQC
+       else
+       {
+               entity e = spawn();
+               setorigin(e, org);
+               setsize(e, PL_MIN, PL_MAX);
+               e.velocity = self.movedir;
+               tracetoss(e, e);
+               waypoint_spawnforteleporter(self, trace_endpos, vlen(trace_endpos - org) / vlen(e.velocity));
+               remove(e);
+       }
+
+       trigger_push_link();
+       defer(0.1, trigger_push_updatelink);
+#endif
+}
+
+#ifdef SVQC
+float trigger_push_send(entity to, float sf)
+{
+       WriteByte(MSG_ENTITY, ENT_CLIENT_TRIGGER_PUSH);
+       WriteByte(MSG_ENTITY, sf);
+
+       if(sf & 1)
+       {
+               WriteByte(MSG_ENTITY, self.team);
+               WriteInt24_t(MSG_ENTITY, self.spawnflags);
+               WriteByte(MSG_ENTITY, self.active);
+               WriteByte(MSG_ENTITY, self.height);
+
+               trigger_common_write(true);
+       }
+
+       if(sf & 2)
+       {
+               WriteByte(MSG_ENTITY, self.team);
+               WriteByte(MSG_ENTITY, self.active);
+       }
+
+       return true;
+}
+
+void trigger_push_updatelink()
+{
+       self.SendFlags |= 1;
+}
+
+void trigger_push_link()
+{
+       //Net_LinkEntity(self, false, 0, trigger_push_send);
+}
+#endif
+#ifdef SVQC
+/*
+ * ENTITY PARAMETERS:
+ *
+ *   target:  target of jump
+ *   height:  the absolute value is the height of the highest point of the jump
+ *            trajectory above the higher one of the player and the target.
+ *            the sign indicates whether the highest point is INSIDE (positive)
+ *            or OUTSIDE (negative) of the jump trajectory. General rule: use
+ *            positive values for targets mounted on the floor, and use negative
+ *            values to target a point on the ceiling.
+ *   movedir: if target is not set, this * speed * 10 is the velocity to be reached.
+ */
+void spawnfunc_trigger_push()
+{
+       SetMovedir ();
+
+       EXACTTRIGGER_INIT;
+
+       self.active = ACTIVE_ACTIVE;
+       self.use = trigger_push_use;
+       self.touch = trigger_push_touch;
+
+       // normal push setup
+       if (!self.speed)
+               self.speed = 1000;
+       self.movedir = self.movedir * self.speed * 10;
+
+       if (!self.noise)
+               self.noise = "misc/jumppad.wav";
+       precache_sound (self.noise);
+
+       // this must be called to spawn the teleport waypoints for bots
+       InitializeEntity(self, trigger_push_findtarget, INITPRIO_FINDTARGET);
+}
+
+
+float target_push_send(entity to, float sf)
+{
+       WriteByte(MSG_ENTITY, ENT_CLIENT_TARGET_PUSH);
+
+       WriteByte(MSG_ENTITY, self.cnt);
+       WriteString(MSG_ENTITY, self.targetname);
+       WriteCoord(MSG_ENTITY, self.origin_x);
+       WriteCoord(MSG_ENTITY, self.origin_y);
+       WriteCoord(MSG_ENTITY, self.origin_z);
+
+       return true;
+}
+
+void target_push_link()
+{
+       Net_LinkEntity(self, false, 0, target_push_send);
+       self.SendFlags |= 1; // update
+}
+
+void spawnfunc_target_push() { target_push_link(); }
+void spawnfunc_info_notnull() { target_push_link(); }
+void spawnfunc_target_position() { target_push_link(); }
+
+#endif
+
+#ifdef CSQC
+
+void ent_trigger_push()
+{
+       float sf = ReadByte();
+
+       if(sf & 1)
+       {
+               self.classname = "jumppad";
+               int mytm = ReadByte(); if(mytm) { self.team = mytm - 1; }
+               self.spawnflags = ReadInt24_t();
+               self.active = ReadByte();
+               self.height = ReadByte();
+
+               trigger_common_read(true);
+
+               self.entremove = trigger_remove_generic;
+               self.solid = SOLID_TRIGGER;
+               self.draw = trigger_draw_generic;
+               self.trigger_touch = trigger_push_touch;
+               self.drawmask = MASK_NORMAL;
+               self.move_time = time;
+               trigger_push_findtarget();
+       }
+
+       if(sf & 2)
+       {
+               self.team = ReadByte();
+               self.active = ReadByte();
+       }
+}
+
+void target_push_remove()
+{
+       if(self.classname)
+               strunzone(self.classname);
+       self.classname = string_null;
+
+       if(self.targetname)
+               strunzone(self.targetname);
+       self.targetname = string_null;
+}
+
+void ent_target_push()
+{
+       self.classname = "push_target";
+       self.cnt = ReadByte();
+       self.targetname = strzone(ReadString());
+       self.origin_x = ReadCoord();
+       self.origin_y = ReadCoord();
+       self.origin_z = ReadCoord();
+       setorigin(self, self.origin);
+
+       self.drawmask = MASK_NORMAL;
+       self.entremove = target_push_remove;
+}
+#endif
diff --git a/qcsrc/common/triggers/trigger/jumppads.qh b/qcsrc/common/triggers/trigger/jumppads.qh
new file mode 100644 (file)
index 0000000..bb0f475
--- /dev/null
@@ -0,0 +1,68 @@
+#ifndef T_JUMPPADS_H
+#define T_JUMPPADS_H
+
+const float PUSH_ONCE          = 1;
+const float PUSH_SILENT                = 2;
+
+.float pushltime;
+.float istypefrag;
+.float height;
+
+const int NUM_JUMPPADSUSED = 3;
+.float jumppadcount;
+.entity jumppadsused[NUM_JUMPPADSUSED];
+
+float trigger_push_calculatevelocity_flighttime;
+
+#ifdef SVQC
+void() SUB_UseTargets;
+void trigger_push_use();
+#endif
+
+#ifdef CSQC
+void ent_trigger_push();
+
+void ent_target_push();
+#endif
+
+/*
+       trigger_push_calculatevelocity
+
+       Arguments:
+         org - origin of the object which is to be pushed
+         tgt - target entity (can be either a point or a model entity; if it is
+               the latter, its midpoint is used)
+         ht  - jump height, measured from the higher one of org and tgt's midpoint
+
+       Returns: velocity for the jump
+       the global trigger_push_calculatevelocity_flighttime is set to the total
+       jump time
+ */
+
+vector trigger_push_calculatevelocity(vector org, entity tgt, float ht);
+
+void trigger_push_touch();
+
+.vector dest;
+void trigger_push_findtarget();
+
+/*
+ * ENTITY PARAMETERS:
+ *
+ *   target:  target of jump
+ *   height:  the absolute value is the height of the highest point of the jump
+ *            trajectory above the higher one of the player and the target.
+ *            the sign indicates whether the highest point is INSIDE (positive)
+ *            or OUTSIDE (negative) of the jump trajectory. General rule: use
+ *            positive values for targets mounted on the floor, and use negative
+ *            values to target a point on the ceiling.
+ *   movedir: if target is not set, this * speed * 10 is the velocity to be reached.
+ */
+#ifdef SVQC
+void spawnfunc_trigger_push();
+
+void spawnfunc_target_push();
+void spawnfunc_info_notnull();
+void spawnfunc_target_position();
+#endif
+#endif
diff --git a/qcsrc/common/triggers/trigger/keylock.qc b/qcsrc/common/triggers/trigger/keylock.qc
new file mode 100644 (file)
index 0000000..ec27d4b
--- /dev/null
@@ -0,0 +1,212 @@
+/**
+ * trigger given targets
+ */
+void trigger_keylock_trigger(string s)
+{
+       entity stemp = self;
+       entity otemp = other;
+       entity atemp = activator;
+
+       entity t;
+       for(t = world; (t = find(t, targetname, s)); )
+               if(t.use)
+               {
+                       self = t;
+                       other = stemp;
+                       activator = atemp;
+                       self.use();
+               }
+
+       self = stemp;
+       other = otemp;
+       activator = atemp;
+}
+
+/**
+ * kill killtarget of trigger keylock.
+ */
+void trigger_keylock_kill(string s)
+{
+       entity t;
+       for(t = world; (t = find(t, targetname, s)); )
+               remove(t);
+}
+
+void trigger_keylock_touch()
+{
+       bool key_used = false;
+       bool started_delay = false;
+
+       // only player may trigger the lock
+       if(!IS_PLAYER(other))
+               return;
+
+       // check silver key
+       if(self.itemkeys)
+               key_used = item_keys_usekey(self, other);
+
+       activator = other;
+
+       if(self.itemkeys)
+       {
+#ifdef SVQC
+               // at least one of the keys is missing
+               if(key_used)
+               {
+                       // one or more keys were given, but others are still missing!
+                       play2(other, self.noise1);
+                       Send_Notification(NOTIF_ONE, other, MSG_CENTER, CENTER_DOOR_LOCKED_ALSONEED, item_keys_keylist(self.itemkeys));
+                       other.key_door_messagetime = time + 2;
+               }
+               else if(other.key_door_messagetime <= time)
+               {
+                       // no keys were given
+                       play2(other, self.noise2);
+                       Send_Notification(NOTIF_ONE, other, MSG_CENTER, CENTER_DOOR_LOCKED_NEED, item_keys_keylist(self.itemkeys));
+                       other.key_door_messagetime = time + 2;
+               }
+#endif
+
+               // trigger target2
+               if(self.delay <= time || started_delay == true)
+               if(self.target2)
+               {
+                       trigger_keylock_trigger(self.target2);
+                       started_delay = true;
+                       self.delay = time + self.wait;
+               }
+       }
+       else
+       {
+#ifdef SVQC
+               // all keys were given!
+               play2(other, self.noise);
+               centerprint(other, self.message);
+#endif
+
+               if(self.target)
+                       trigger_keylock_trigger(self.target);
+
+               if(self.killtarget)
+                       trigger_keylock_kill(self.killtarget);
+
+               remove(self);
+       }
+
+}
+
+#ifdef SVQC
+bool trigger_keylock_send(entity to, int sf)
+{
+       WriteByte(MSG_ENTITY, ENT_CLIENT_KEYLOCK);
+
+       WriteInt24_t(MSG_ENTITY, self.itemkeys);
+       WriteByte(MSG_ENTITY, self.height);
+
+       trigger_common_write(true);
+
+       return true;
+}
+
+void trigger_keylock_link()
+{
+       // uncomment to network keylocks
+       //Net_LinkEntity(self, false, 0, trigger_keylock_send);
+}
+
+/*QUAKED trigger_keylock (.0 .5 .8) ?
+Keylock trigger.  Must target other entities.
+This trigger will trigger target entities when all required keys are provided.
+-------- KEYS --------
+itemkeys: A bit field with key IDs that are needed to open this lock.
+sounds: 1 to play misc/secret.wav, 2 to play misc/talk.wav, 3 to play misc/trigger1.wav (3 is default)
+target: trigger all entities with this targetname when triggered and all keys have been given to it, then remove this trigger
+target2: trigger all entities with this targetname when triggered without giving it all the required keys.
+killtarget: remove all entities with this targetname when triggered with all the needed keys.
+message: print this message to the player who activated the trigger when all needed keys have been given.
+message2: print this message to the player who activated the trigger when not all of the needed keys have been given.
+noise: sound to play when lock gets unlocked (default: see sounds)
+noise1: sound to play when only some of the needed key were used but not all (default: misc/decreasevalue.wav)
+noise2: sound to play when a key is missing (default: misc/talk.wav)
+wait: prevent triggering again for this amount of time (default: 5) - applies to target2, target3, target4.
+---------NOTES----------
+If spawned without any key specified in itemkeys, this trigger will display an error and remove itself.
+message2 and noise2 will be resent to the player every 2 seconds while he is in the trigger zone.
+*/
+void spawnfunc_trigger_keylock(void)
+{
+       if(!self.itemkeys) { remove(self); return; }
+
+       // set unlocked message
+       if(self.message == "")
+               self.message = "Unlocked!";
+
+       // set default unlock noise
+       if(self.noise == "")
+       {
+               if(self.sounds == 1)
+                       self.noise = "misc/secret.wav";
+               else if(self.sounds == 2)
+                       self.noise = "misc/talk.wav";
+               else //if (self.sounds == 3) {
+                       self.noise = "misc/trigger1.wav";
+       }
+
+       // set default use key sound
+       if(self.noise1 == "")
+               self.noise1 = "misc/decreasevalue.wav";
+
+       // set closed sourd
+       if(self.noise2 == "")
+               self.noise2 = "misc/talk.wav";
+
+       // delay between triggering message2 and trigger2
+       if(!self.wait) { self.wait = 5; }
+
+       // precache sounds
+       precache_sound(self.noise);
+       precache_sound(self.noise1);
+       precache_sound(self.noise2);
+
+       EXACTTRIGGER_INIT;
+
+       self.touch = trigger_keylock_touch;
+
+       trigger_keylock_link();
+}
+#elif defined(CSQC)
+void keylock_remove()
+{
+       if(self.target) { strunzone(self.target); }
+       self.target = string_null;
+
+       if(self.target2) { strunzone(self.target2); }
+       self.target2 = string_null;
+
+       if(self.target3) { strunzone(self.target3); }
+       self.target3 = string_null;
+
+       if(self.target4) { strunzone(self.target4); }
+       self.target4 = string_null;
+
+       if(self.killtarget) { strunzone(self.killtarget); }
+       self.killtarget = string_null;
+
+       if(self.targetname) { strunzone(self.targetname); }
+       self.targetname = string_null;
+}
+
+void ent_keylock()
+{
+       self.itemkeys = ReadInt24_t();
+       self.height = ReadByte();
+
+       trigger_common_read(true);
+
+       self.classname = "trigger_keylock";
+       self.drawmask = MASK_NORMAL;
+       self.draw = trigger_draw_generic;
+       self.trigger_touch = trigger_keylock_touch;
+       self.entremove = keylock_remove;
+}
+#endif
diff --git a/qcsrc/common/triggers/trigger/keylock.qh b/qcsrc/common/triggers/trigger/keylock.qh
new file mode 100644 (file)
index 0000000..b21145d
--- /dev/null
@@ -0,0 +1,20 @@
+#ifdef CSQC
+void ent_keylock();
+bool item_keys_usekey(entity l, entity p)
+{
+       float valid = l.itemkeys & p.itemkeys;
+
+       if (!valid) {
+               // other has none of the needed keys
+               return false;
+       } else if (l.itemkeys == valid) {
+               // ALL needed keys were given
+               l.itemkeys = 0;
+               return true;
+       } else {
+               // only some of the needed keys were given
+               l.itemkeys &= ~valid;
+               return true;
+       }
+}
+#endif
diff --git a/qcsrc/common/triggers/trigger/magicear.qc b/qcsrc/common/triggers/trigger/magicear.qc
new file mode 100644 (file)
index 0000000..f14b75c
--- /dev/null
@@ -0,0 +1,204 @@
+#ifdef SVQC
+float magicear_matched;
+float W_Tuba_HasPlayed(entity pl, string melody, float instrument, float ignorepitch, float mintempo, float maxtempo);
+string trigger_magicear_processmessage(entity ear, entity source, float teamsay, entity privatesay, string msgin)
+{
+       float domatch, dotrigger, matchstart, l;
+       string s, msg;
+       entity oldself;
+       string savemessage;
+
+       magicear_matched = false;
+
+       dotrigger = ((IS_PLAYER(source)) && (source.deadflag == DEAD_NO) && ((ear.radius == 0) || (vlen(source.origin - ear.origin) <= ear.radius)));
+       domatch = ((ear.spawnflags & 32) || dotrigger);
+
+       if (!domatch)
+               return msgin;
+
+       if (!msgin)
+       {
+               // we are in TUBA mode!
+               if (!(ear.spawnflags & 256))
+                       return msgin;
+
+               if(!W_Tuba_HasPlayed(source, ear.message, ear.movedir_x, !(ear.spawnflags & 512), ear.movedir_y, ear.movedir_z))
+                       return msgin;
+
+               magicear_matched = true;
+
+               if(dotrigger)
+               {
+                       oldself = self;
+                       activator = source;
+                       self = ear;
+                       savemessage = self.message;
+                       self.message = string_null;
+                       SUB_UseTargets();
+                       self.message = savemessage;
+                       self = oldself;
+               }
+
+               if(ear.netname != "")
+                       return ear.netname;
+
+               return msgin;
+       }
+
+       if(ear.spawnflags & 256) // ENOTUBA
+               return msgin;
+
+       if(privatesay)
+       {
+               if(ear.spawnflags & 4)
+                       return msgin;
+       }
+       else
+       {
+               if(!teamsay)
+                       if(ear.spawnflags & 1)
+                               return msgin;
+               if(teamsay > 0)
+                       if(ear.spawnflags & 2)
+                               return msgin;
+               if(teamsay < 0)
+                       if(ear.spawnflags & 8)
+                               return msgin;
+       }
+
+       matchstart = -1;
+       l = strlen(ear.message);
+
+       if(ear.spawnflags & 128)
+               msg = msgin;
+       else
+               msg = strdecolorize(msgin);
+
+       if(substring(ear.message, 0, 1) == "*")
+       {
+               if(substring(ear.message, -1, 1) == "*")
+               {
+                       // two wildcards
+                       // as we need multi-replacement here...
+                       s = substring(ear.message, 1, -2);
+                       l -= 2;
+                       if(strstrofs(msg, s, 0) >= 0)
+                               matchstart = -2; // we use strreplace on s
+               }
+               else
+               {
+                       // match at start
+                       s = substring(ear.message, 1, -1);
+                       l -= 1;
+                       if(substring(msg, -l, l) == s)
+                               matchstart = strlen(msg) - l;
+               }
+       }
+       else
+       {
+               if(substring(ear.message, -1, 1) == "*")
+               {
+                       // match at end
+                       s = substring(ear.message, 0, -2);
+                       l -= 1;
+                       if(substring(msg, 0, l) == s)
+                               matchstart = 0;
+               }
+               else
+               {
+                       // full match
+                       s = ear.message;
+                       if(msg == ear.message)
+                               matchstart = 0;
+               }
+       }
+
+       if(matchstart == -1) // no match
+               return msgin;
+
+       magicear_matched = true;
+
+       if(dotrigger)
+       {
+               oldself = self;
+               activator = source;
+               self = ear;
+               savemessage = self.message;
+               self.message = string_null;
+               SUB_UseTargets();
+               self.message = savemessage;
+               self = oldself;
+       }
+
+       if(ear.spawnflags & 16)
+       {
+               return ear.netname;
+       }
+       else if(ear.netname != "")
+       {
+               if(matchstart < 0)
+                       return strreplace(s, ear.netname, msg);
+               else
+                       return strcat(
+                               substring(msg, 0, matchstart),
+                               ear.netname,
+                               substring(msg, matchstart + l, -1)
+                       );
+       }
+       else
+               return msgin;
+}
+
+entity magicears;
+string trigger_magicear_processmessage_forallears(entity source, float teamsay, entity privatesay, string msgin)
+{
+       entity ear;
+       string msgout;
+       for(ear = magicears; ear; ear = ear.enemy)
+       {
+               msgout = trigger_magicear_processmessage(ear, source, teamsay, privatesay, msgin);
+               if(!(ear.spawnflags & 64))
+               if(magicear_matched)
+                       return msgout;
+               msgin = msgout;
+       }
+       return msgin;
+}
+
+void spawnfunc_trigger_magicear()
+{
+       self.enemy = magicears;
+       magicears = self;
+
+       // actually handled in "say" processing
+       // spawnflags:
+       //    1 = ignore say
+       //    2 = ignore teamsay
+       //    4 = ignore tell
+       //    8 = ignore tell to unknown player
+       //   16 = let netname replace the whole message (otherwise, netname is a word replacement if set)
+       //   32 = perform the replacement even if outside the radius or dead
+       //   64 = continue replacing/triggering even if this one matched
+       //  128 = don't decolorize message before matching
+       //  256 = message is a tuba note sequence (pitch.duration pitch.duration ...)
+       //  512 = tuba notes must be exact right pitch, no transposing
+       // message: either
+       //   *pattern*
+       // or
+       //   *pattern
+       // or
+       //   pattern*
+       // or
+       //   pattern
+       // netname:
+       //   if set, replacement for the matched text
+       // radius:
+       //   "hearing distance"
+       // target:
+       //   what to trigger
+       // movedir:
+       //   for spawnflags 256, defines 'instrument+1 mintempo maxtempo' (zero component doesn't matter)
+
+       self.movedir_x -= 1; // map to tuba instrument numbers
+}
+#endif
diff --git a/qcsrc/common/triggers/trigger/monoflop.qc b/qcsrc/common/triggers/trigger/monoflop.qc
new file mode 100644 (file)
index 0000000..45ce761
--- /dev/null
@@ -0,0 +1,49 @@
+#ifdef SVQC
+/*QUAKED spawnfunc_trigger_monoflop (.5 .5 .5) (-8 -8 -8) (8 8 8)
+"Mono-flop" trigger gate... turns one trigger event into one "on" and one "off" event, separated by a delay of "wait"
+*/
+void monoflop_use()
+{
+       self.nextthink = time + self.wait;
+       self.enemy = activator;
+       if(self.state)
+               return;
+       self.state = 1;
+       SUB_UseTargets();
+}
+void monoflop_fixed_use()
+{
+       if(self.state)
+               return;
+       self.nextthink = time + self.wait;
+       self.state = 1;
+       self.enemy = activator;
+       SUB_UseTargets();
+}
+
+void monoflop_think()
+{
+       self.state = 0;
+       activator = self.enemy;
+       SUB_UseTargets();
+}
+
+void monoflop_reset()
+{
+       self.state = 0;
+       self.nextthink = 0;
+}
+
+void spawnfunc_trigger_monoflop()
+{
+       if(!self.wait)
+               self.wait = 1;
+       if(self.spawnflags & 1)
+               self.use = monoflop_fixed_use;
+       else
+               self.use = monoflop_use;
+       self.think = monoflop_think;
+       self.state = 0;
+       self.reset = monoflop_reset;
+}
+#endif
diff --git a/qcsrc/common/triggers/trigger/multi.qc b/qcsrc/common/triggers/trigger/multi.qc
new file mode 100644 (file)
index 0000000..b852587
--- /dev/null
@@ -0,0 +1,204 @@
+// NOTE: also contains trigger_once at bottom
+
+#ifdef SVQC
+// the wait time has passed, so set back up for another activation
+void multi_wait()
+{
+       if (self.max_health)
+       {
+               self.health = self.max_health;
+               self.takedamage = DAMAGE_YES;
+               self.solid = SOLID_BBOX;
+       }
+}
+
+
+// the trigger was just touched/killed/used
+// self.enemy should be set to the activator so it can be held through a delay
+// so wait for the delay time before firing
+void multi_trigger()
+{
+       if (self.nextthink > time)
+       {
+               return;         // allready been triggered
+       }
+
+       if (self.classname == "trigger_secret")
+       {
+               if (!IS_PLAYER(self.enemy))
+                       return;
+               found_secrets = found_secrets + 1;
+               WriteByte (MSG_ALL, SVC_FOUNDSECRET);
+       }
+
+       if (self.noise)
+               sound (self.enemy, CH_TRIGGER, self.noise, VOL_BASE, ATTEN_NORM);
+
+// don't trigger again until reset
+       self.takedamage = DAMAGE_NO;
+
+       activator = self.enemy;
+       other = self.goalentity;
+       SUB_UseTargets();
+
+       if (self.wait > 0)
+       {
+               self.think = multi_wait;
+               self.nextthink = time + self.wait;
+       }
+       else if (self.wait == 0)
+       {
+               multi_wait(); // waiting finished
+       }
+       else
+       {       // we can't just remove (self) here, because this is a touch function
+               // called wheil C code is looping through area links...
+               self.touch = func_null;
+       }
+}
+
+void multi_use()
+{
+       self.goalentity = other;
+       self.enemy = activator;
+       multi_trigger();
+}
+
+void multi_touch()
+{
+       if(!(self.spawnflags & 2))
+       if(!other.iscreature)
+                       return;
+
+       if(self.team)
+               if(((self.spawnflags & 4) == 0) == (self.team != other.team))
+                       return;
+
+// if the trigger has an angles field, check player's facing direction
+       if (self.movedir != '0 0 0')
+       {
+               makevectors (other.angles);
+               if (v_forward * self.movedir < 0)
+                       return;         // not facing the right way
+       }
+
+       EXACTTRIGGER_TOUCH;
+
+       self.enemy = other;
+       self.goalentity = other;
+       multi_trigger ();
+}
+
+void multi_eventdamage (entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
+{
+       if (!self.takedamage)
+               return;
+       if(self.spawnflags & DOOR_NOSPLASH)
+               if(!(DEATH_ISSPECIAL(deathtype)) && (deathtype & HITTYPE_SPLASH))
+                       return;
+       self.health = self.health - damage;
+       if (self.health <= 0)
+       {
+               self.enemy = attacker;
+               self.goalentity = inflictor;
+               multi_trigger();
+       }
+}
+
+void multi_reset()
+{
+       if ( !(self.spawnflags & SPAWNFLAG_NOTOUCH) )
+               self.touch = multi_touch;
+       if (self.max_health)
+       {
+               self.health = self.max_health;
+               self.takedamage = DAMAGE_YES;
+               self.solid = SOLID_BBOX;
+       }
+       self.think = func_null;
+       self.nextthink = 0;
+       self.team = self.team_saved;
+}
+
+/*QUAKED spawnfunc_trigger_multiple (.5 .5 .5) ? notouch
+Variable sized repeatable trigger.  Must be targeted at one or more entities.  If "health" is set, the trigger must be killed to activate each time.
+If "delay" is set, the trigger waits some time after activating before firing.
+"wait" : Seconds between triggerings. (.2 default)
+If notouch is set, the trigger is only fired by other entities, not by touching.
+NOTOUCH has been obsoleted by spawnfunc_trigger_relay!
+sounds
+1)     secret
+2)     beep beep
+3)     large switch
+4)
+set "message" to text string
+*/
+void spawnfunc_trigger_multiple()
+{
+       self.reset = multi_reset;
+       if (self.sounds == 1)
+       {
+               precache_sound ("misc/secret.wav");
+               self.noise = "misc/secret.wav";
+       }
+       else if (self.sounds == 2)
+       {
+               precache_sound ("misc/talk.wav");
+               self.noise = "misc/talk.wav";
+       }
+       else if (self.sounds == 3)
+       {
+               precache_sound ("misc/trigger1.wav");
+               self.noise = "misc/trigger1.wav";
+       }
+
+       if (!self.wait)
+               self.wait = 0.2;
+       else if(self.wait < -1)
+               self.wait = 0;
+       self.use = multi_use;
+
+       EXACTTRIGGER_INIT;
+
+       self.team_saved = self.team;
+
+       if (self.health)
+       {
+               if (self.spawnflags & SPAWNFLAG_NOTOUCH)
+                       objerror ("health and notouch don't make sense\n");
+               self.max_health = self.health;
+               self.event_damage = multi_eventdamage;
+               self.takedamage = DAMAGE_YES;
+               self.solid = SOLID_BBOX;
+               setorigin (self, self.origin);  // make sure it links into the world
+       }
+       else
+       {
+               if ( !(self.spawnflags & SPAWNFLAG_NOTOUCH) )
+               {
+                       self.touch = multi_touch;
+                       setorigin (self, self.origin);  // make sure it links into the world
+               }
+       }
+}
+
+
+/*QUAKED spawnfunc_trigger_once (.5 .5 .5) ? notouch
+Variable sized trigger. Triggers once, then removes itself.  You must set the key "target" to the name of another object in the level that has a matching
+"targetname".  If "health" is set, the trigger must be killed to activate.
+If notouch is set, the trigger is only fired by other entities, not by touching.
+if "killtarget" is set, any objects that have a matching "target" will be removed when the trigger is fired.
+if "angle" is set, the trigger will only fire when someone is facing the direction of the angle.  Use "360" for an angle of 0.
+sounds
+1)     secret
+2)     beep beep
+3)     large switch
+4)
+set "message" to text string
+*/
+void spawnfunc_trigger_once()
+{
+       self.wait = -1;
+       spawnfunc_trigger_multiple();
+}
+#endif
diff --git a/qcsrc/common/triggers/trigger/multi.qh b/qcsrc/common/triggers/trigger/multi.qh
new file mode 100644 (file)
index 0000000..df14a51
--- /dev/null
@@ -0,0 +1,6 @@
+#ifdef SVQC
+void multi_trigger();
+void multi_reset();
+
+void spawnfunc_trigger_once();
+#endif
diff --git a/qcsrc/common/triggers/trigger/multivibrator.qc b/qcsrc/common/triggers/trigger/multivibrator.qc
new file mode 100644 (file)
index 0000000..02a258e
--- /dev/null
@@ -0,0 +1,73 @@
+#ifdef SVQC
+void multivibrator_send()
+{
+       float newstate;
+       float cyclestart;
+
+       cyclestart = floor((time + self.phase) / (self.wait + self.respawntime)) * (self.wait + self.respawntime) - self.phase;
+
+       newstate = (time < cyclestart + self.wait);
+
+       activator = self;
+       if(self.state != newstate)
+               SUB_UseTargets();
+       self.state = newstate;
+
+       if(self.state)
+               self.nextthink = cyclestart + self.wait + 0.01;
+       else
+               self.nextthink = cyclestart + self.wait + self.respawntime + 0.01;
+}
+
+void multivibrator_toggle()
+{
+       if(self.nextthink == 0)
+       {
+               multivibrator_send();
+       }
+       else
+       {
+               if(self.state)
+               {
+                       SUB_UseTargets();
+                       self.state = 0;
+               }
+               self.nextthink = 0;
+       }
+}
+
+void multivibrator_reset()
+{
+       if(!(self.spawnflags & 1))
+               self.nextthink = 0; // wait for a trigger event
+       else
+               self.nextthink = max(1, time);
+}
+
+/*QUAKED trigger_multivibrator (.5 .5 .5) (-8 -8 -8) (8 8 8) START_ON
+"Multivibrator" trigger gate... repeatedly sends trigger events. When triggered, turns on or off.
+-------- KEYS --------
+target: trigger all entities with this targetname when it goes off
+targetname: name that identifies this entity so it can be triggered; when off, it always uses the OFF state
+phase: offset of the timing
+wait: "on" cycle time (default: 1)
+respawntime: "off" cycle time (default: same as wait)
+-------- SPAWNFLAGS --------
+START_ON: assume it is already turned on (when targeted)
+*/
+void spawnfunc_trigger_multivibrator()
+{
+       if(!self.wait)
+               self.wait = 1;
+       if(!self.respawntime)
+               self.respawntime = self.wait;
+
+       self.state = 0;
+       self.use = multivibrator_toggle;
+       self.think = multivibrator_send;
+       self.nextthink = max(1, time);
+
+       IFTARGETED
+               multivibrator_reset();
+}
+#endif
diff --git a/qcsrc/common/triggers/trigger/relay.qc b/qcsrc/common/triggers/trigger/relay.qc
new file mode 100644 (file)
index 0000000..e037028
--- /dev/null
@@ -0,0 +1,10 @@
+#ifdef SVQC
+/*QUAKED spawnfunc_trigger_relay (.5 .5 .5) (-8 -8 -8) (8 8 8)
+This fixed size trigger cannot be touched, it can only be fired by other events.  It can contain killtargets, targets, delays, and messages.
+*/
+void spawnfunc_trigger_relay()
+{
+       self.use = SUB_UseTargets;
+       self.reset = spawnfunc_trigger_relay; // this spawnfunc resets fully
+}
+#endif
diff --git a/qcsrc/common/triggers/trigger/relay_activators.qc b/qcsrc/common/triggers/trigger/relay_activators.qc
new file mode 100644 (file)
index 0000000..83c0103
--- /dev/null
@@ -0,0 +1,45 @@
+#ifdef SVQC
+void relay_activators_use()
+{
+       entity trg, os;
+
+       os = self;
+
+       for(trg = world; (trg = find(trg, targetname, os.target)); )
+       {
+               self = trg;
+               if (trg.setactive)
+                       trg.setactive(os.cnt);
+               else
+               {
+                       //bprint("Not using setactive\n");
+                       if(os.cnt == ACTIVE_TOGGLE)
+                               if(trg.active == ACTIVE_ACTIVE)
+                                       trg.active = ACTIVE_NOT;
+                               else
+                                       trg.active = ACTIVE_ACTIVE;
+                       else
+                               trg.active = os.cnt;
+               }
+       }
+       self = os;
+}
+
+void spawnfunc_relay_activate()
+{
+       self.cnt = ACTIVE_ACTIVE;
+       self.use = relay_activators_use;
+}
+
+void spawnfunc_relay_deactivate()
+{
+       self.cnt = ACTIVE_NOT;
+       self.use = relay_activators_use;
+}
+
+void spawnfunc_relay_activatetoggle()
+{
+       self.cnt = ACTIVE_TOGGLE;
+       self.use = relay_activators_use;
+}
+#endif
diff --git a/qcsrc/common/triggers/trigger/relay_if.qc b/qcsrc/common/triggers/trigger/relay_if.qc
new file mode 100644 (file)
index 0000000..ade56c1
--- /dev/null
@@ -0,0 +1,20 @@
+#ifdef SVQC
+void trigger_relay_if_use()
+{
+       float n;
+       n = self.count;
+
+       // TODO make this generic AND faster than nextent()ing through all, if somehow possible
+       n = (cvar_string(self.netname) == cvar_string(self.message));
+       if(self.spawnflags & 1)
+               n = !n;
+
+       if(n)
+               SUB_UseTargets();
+}
+
+void spawnfunc_trigger_relay_if()
+{
+       self.use = trigger_relay_if_use;
+}
+#endif
diff --git a/qcsrc/common/triggers/trigger/relay_teamcheck.qc b/qcsrc/common/triggers/trigger/relay_teamcheck.qc
new file mode 100644 (file)
index 0000000..8a77cef
--- /dev/null
@@ -0,0 +1,35 @@
+#ifdef SVQC
+void trigger_relay_teamcheck_use()
+{
+       if(activator.team)
+       {
+               if(self.spawnflags & 2)
+               {
+                       if(DIFF_TEAM(activator, self))
+                               SUB_UseTargets();
+               }
+               else
+               {
+                       if(SAME_TEAM(activator, self))
+                               SUB_UseTargets();
+               }
+       }
+       else
+       {
+               if(self.spawnflags & 1)
+                       SUB_UseTargets();
+       }
+}
+
+void trigger_relay_teamcheck_reset()
+{
+       self.team = self.team_saved;
+}
+
+void spawnfunc_trigger_relay_teamcheck()
+{
+       self.team_saved = self.team;
+       self.use = trigger_relay_teamcheck_use;
+       self.reset = trigger_relay_teamcheck_reset;
+}
+#endif
diff --git a/qcsrc/common/triggers/trigger/secret.qc b/qcsrc/common/triggers/trigger/secret.qc
new file mode 100644 (file)
index 0000000..b93ab03
--- /dev/null
@@ -0,0 +1,85 @@
+#if defined(CSQC)
+#elif defined(MENUQC)
+#elif defined(SVQC)
+       #include "../../../server/_all.qh"
+    #include "../../util.qh"
+    #include "../../../server/defs.qh"
+    #include "secret.qh"
+#endif
+
+#ifdef SVQC
+
+void secrets_setstatus() {
+       self.stat_secrets_total = secrets_total;
+       self.stat_secrets_found = secrets_found;
+}
+
+/**
+ * A secret has been found (maybe :P)
+ */
+void trigger_secret_touch() {
+       // only a player can trigger this
+       if (!IS_PLAYER(other))
+               return;
+
+       // update secrets found counter
+       secrets_found += 1;
+       //print("Secret found: ", ftos(secret_counter.cnt), "/");
+       //print(ftos(secret_counter.count), "\n");
+
+       // centerprint message (multi_touch() doesn't always call centerprint())
+       centerprint(other, self.message);
+       self.message = "";
+
+       // handle normal trigger features
+       multi_touch();
+       remove(self);
+}
+
+/*QUAKED trigger_secret (.5 .5 .5) ?
+Variable sized secret trigger. Can be targeted at one or more entities.
+Basically, it's a trigger_once (with restrictions, see notes) that additionally updates the number of secrets found.
+-------- KEYS --------
+sounds: 1 to play misc/secret.wav, 2 to play misc/talk.wav, 3 to play misc/trigger1.wav (default: 1)
+noise: path to sound file, if you want to play something else
+target: trigger all entities with this targetname when triggered
+message: print this message to the player who activated the trigger instead of the standard 'You found a secret!'
+killtarget: remove all entities with this targetname when triggered
+-------- NOTES --------
+You should create a common/trigger textured brush covering the entrance to a secret room/area.
+Trigger secret can only be trigger by a player's touch and can not be a target itself.
+*/
+void spawnfunc_trigger_secret() {
+       // FIXME: should it be disabled in most modes?
+
+       // update secrets count
+       secrets_total += 1;
+
+       // add default message
+       if (self.message == "")
+               self.message = "You found a secret!";
+
+       // set default sound
+       if (self.noise == "")
+       if (!self.sounds)
+               self.sounds = 1; // misc/secret.wav
+
+       // this entity can't be a target itself!!!!
+       self.targetname = "";
+
+       // you can't just shoot a room to find it, can you?
+       self.health = 0;
+
+       // a secret can not be delayed
+       self.delay = 0;
+
+       // convert this trigger to trigger_once
+       self.classname = "trigger_once";
+       spawnfunc_trigger_once();
+
+       // take over the touch() function, so we can mark secret as found
+       self.touch = trigger_secret_touch;
+       // ignore triggering;
+       self.use = func_null;
+}
+#endif
diff --git a/qcsrc/common/triggers/trigger/secret.qh b/qcsrc/common/triggers/trigger/secret.qh
new file mode 100644 (file)
index 0000000..c09da6b
--- /dev/null
@@ -0,0 +1,24 @@
+#ifndef SECRET_H
+#define SECRET_H
+#ifdef SVQC
+
+/**
+ * Total number of secrets on the map.
+ */
+float secrets_total;
+
+/**
+ * Total numbe of secrets found on the map.
+ */
+float secrets_found;
+
+
+.float stat_secrets_total;
+.float stat_secrets_found;
+
+/**
+ * update secrets status.
+ */
+void secrets_setstatus();
+#endif
+#endif
diff --git a/qcsrc/common/triggers/trigger/swamp.qc b/qcsrc/common/triggers/trigger/swamp.qc
new file mode 100644 (file)
index 0000000..b99332b
--- /dev/null
@@ -0,0 +1,154 @@
+#if defined(CSQC)
+#elif defined(MENUQC)
+#elif defined(SVQC)
+       #include "../../../server/_all.qh"
+    #include "../../../warpzonelib/util_server.qh"
+    #include "../../weapons/all.qh"
+    #include "../../../server/defs.qh"
+    #include "../../deathtypes.qh"
+#endif
+
+/*
+*              t_swamp.c
+*              Adds spawnfunc_trigger_swamp and suppoart routines for xonotic 1.2.1+
+*              Author tZork (Jakob MG)
+*              jakob@games43.se
+*              2005 11 29
+*/
+
+.float swamp_interval; //Hurt players in swamp with this interval
+.float swamp_slowdown; //Players in swamp get slowd down by this mutch 0-1 is slowdown 1-~ is speedup (!?)
+.entity swampslug;
+
+#ifdef SVQC
+void spawnfunc_trigger_swamp(void);
+#endif
+void swamp_touch(void);
+void swampslug_think();
+
+
+/*
+* Uses a entity calld swampslug to handle players in the swamp
+* It works like this: When the plyer enters teh swamp the spawnfunc_trigger_swamp
+* attaches a new "swampslug" to the player. As long as the plyer is inside
+* the swamp the swamp gives the slug new health. But the slug slowly kills itself
+* so when the player goes outside the swamp, it dies and releases the player from the
+* swamps curses (dmg/slowdown)
+*
+* I do it this way becuz there is no "untouch" event.
+*/
+void swampslug_think(void)
+{
+       //Slowly kill the slug
+       self.health = self.health - 1;
+
+       //Slug dead? then remove curses.
+       if(self.health <= 0)
+       {
+               self.owner.in_swamp = 0;
+               remove(self);
+               //centerprint(self.owner,"Killing slug...\n");
+               return;
+       }
+
+       // Slug still alive, so we are still in the swamp
+       // Or we have exited it very recently.
+       // Do the damage and renew the timer.
+#ifdef SVQC
+       Damage (self.owner, self, self, self.dmg, DEATH_SWAMP, other.origin, '0 0 0');
+#endif
+
+       self.nextthink = time + self.swamp_interval;
+}
+
+void swamp_touch(void)
+{
+       // If whatever thats touching the swamp is not a player
+       // or if its a dead player, just dont care abt it.
+       if(!IS_PLAYER(other) || PHYS_DEAD(other))
+               return;
+
+       EXACTTRIGGER_TOUCH;
+
+       // Chech if player alredy got a swampslug.
+       if(other.in_swamp != 1)
+       {
+               // If not attach one.
+               //centerprint(other,"Entering swamp!\n");
+               other.swampslug = spawn();
+               other.swampslug.health = 2;
+               other.swampslug.think = swampslug_think;
+               other.swampslug.nextthink = time;
+               other.swampslug.owner = other;
+               other.swampslug.dmg = self.dmg;
+               other.swampslug.swamp_interval = self.swamp_interval;
+               other.swamp_slowdown = self.swamp_slowdown;
+               other.in_swamp = 1;
+               return;
+       }
+
+       //other.in_swamp = 1;
+
+       //Revitalize players swampslug
+       other.swampslug.health = 2;
+}
+
+#ifdef SVQC
+float swamp_send(entity to, float sf)
+{
+       WriteByte(MSG_ENTITY, ENT_CLIENT_LADDER);
+
+       WriteByte(MSG_ENTITY, self.dmg); // can probably get away with using a single byte here
+       WriteByte(MSG_ENTITY, self.swamp_slowdown);
+       WriteByte(MSG_ENTITY, self.swamp_interval);
+
+       trigger_common_write(false);
+
+       return true;
+}
+
+void swamp_link()
+{
+       Net_LinkEntity(self, false, 0, func_ladder_send);
+}
+
+/*QUAKED spawnfunc_trigger_swamp (.5 .5 .5) ?
+Players gettin into the swamp will
+get slowd down and damaged
+*/
+void spawnfunc_trigger_swamp(void)
+{
+       // Init stuff
+       EXACTTRIGGER_INIT;
+       self.touch = swamp_touch;
+
+       // Setup default keys, if missing
+       if(self.dmg <= 0)
+               self.dmg = 5;
+       if(self.swamp_interval <= 0)
+               self.swamp_interval = 1;
+       if(self.swamp_slowdown <= 0)
+               self.swamp_slowdown = 0.5;
+
+       swamp_link();
+}
+
+#elif defined(CSQC)
+
+void ent_swamp()
+{
+       self.dmg = ReadByte();
+       self.swamp_slowdown = ReadByte();
+       self.swamp_interval = ReadByte();
+
+       trigger_common_read(false);
+
+       self.classname = "trigger_swamp";
+       self.solid = SOLID_TRIGGER;
+       self.draw = trigger_draw_generic;
+       self.trigger_touch = swamp_touch;
+       self.drawmask = MASK_NORMAL;
+       self.move_time = time;
+       self.entremove = trigger_remove_generic;
+}
+#endif
diff --git a/qcsrc/common/triggers/trigger/swamp.qh b/qcsrc/common/triggers/trigger/swamp.qh
new file mode 100644 (file)
index 0000000..86b1431
--- /dev/null
@@ -0,0 +1,15 @@
+#ifndef TRIGGER_SWAMP_H
+#define TRIGGER_SWAMP_H
+
+.float swamp_interval; //Hurt players in swamp with this interval
+.float swamp_slowdown; //Players in swamp get slowd down by this mutch 0-1 is slowdown 1-~ is speedup (!?)
+.entity swampslug;
+
+.float in_swamp;              // bool
+.entity swampslug;            // Uses this to release from swamp ("untouch" fix)
+
+#ifdef CSQC
+void ent_swamp();
+#endif
+
+#endif
diff --git a/qcsrc/common/triggers/trigger/teleport.qc b/qcsrc/common/triggers/trigger/teleport.qc
new file mode 100644 (file)
index 0000000..5ff5fcf
--- /dev/null
@@ -0,0 +1,77 @@
+#ifdef SVQC
+void trigger_teleport_use()
+{
+       if(teamplay)
+               self.team = activator.team;
+#ifdef SVQC
+       self.SendFlags |= SF_TRIGGER_UPDATE;
+#endif
+}
+
+void Teleport_Touch (void)
+{
+       entity oldself;
+       string s;
+
+       if (self.active != ACTIVE_ACTIVE)
+               return;
+
+       if (!other.teleportable)
+               return;
+
+       if(other.vehicle)
+       if(!other.vehicle.teleportable)
+               return;
+
+       if(other.turrcaps_flags & TFL_TURRCAPS_ISTURRET)
+               return;
+
+       if(other.deadflag != DEAD_NO)
+               return;
+
+       if(self.team)
+               if(((self.spawnflags & 4) == 0) == (self.team != other.team))
+                       return;
+
+       EXACTTRIGGER_TOUCH;
+
+       if(IS_PLAYER(other))
+               RemoveGrapplingHook(other);
+
+       entity e;
+       e = Simple_TeleportPlayer(self, other);
+
+       activator = other;
+       s = self.target; self.target = string_null;
+       SUB_UseTargets();
+       if (!self.target) self.target = s;
+
+       oldself = self;
+       self = e;
+       SUB_UseTargets();
+       self = oldself;
+}
+
+void spawnfunc_trigger_teleport()
+{
+       self.angles = '0 0 0';
+
+       EXACTTRIGGER_INIT;
+
+       self.active = ACTIVE_ACTIVE;
+
+       self.use = trigger_teleport_use;
+
+       // this must be called to spawn the teleport waypoints for bots
+       InitializeEntity(self, teleport_findtarget, INITPRIO_FINDTARGET);
+
+       if (self.target == "")
+       {
+               objerror ("Teleporter with no target");
+               return;
+       }
+
+       self.teleport_next = teleport_first;
+       teleport_first = self;
+}
+#endif
diff --git a/qcsrc/common/triggers/triggers.qc b/qcsrc/common/triggers/triggers.qc
new file mode 100644 (file)
index 0000000..1e7715a
--- /dev/null
@@ -0,0 +1,277 @@
+void SUB_DontUseTargets() { }
+
+void() SUB_UseTargets;
+
+void DelayThink()
+{
+       activator = self.enemy;
+       SUB_UseTargets ();
+       remove(self);
+}
+
+void FixSize(entity e)
+{
+       e.mins_x = rint(e.mins_x);
+       e.mins_y = rint(e.mins_y);
+       e.mins_z = rint(e.mins_z);
+
+       e.maxs_x = rint(e.maxs_x);
+       e.maxs_y = rint(e.maxs_y);
+       e.maxs_z = rint(e.maxs_z);
+}
+
+#ifdef SVQC
+void trigger_common_write(bool withtarget)
+{
+       WriteByte(MSG_ENTITY, self.warpzone_isboxy);
+       WriteByte(MSG_ENTITY, self.scale);
+
+       if(withtarget)
+       {
+               WriteString(MSG_ENTITY, self.target);
+               WriteString(MSG_ENTITY, self.target2);
+               WriteString(MSG_ENTITY, self.target3);
+               WriteString(MSG_ENTITY, self.target4);
+               WriteString(MSG_ENTITY, self.targetname);
+               WriteString(MSG_ENTITY, self.killtarget);
+       }
+
+       WriteCoord(MSG_ENTITY, self.origin_x);
+       WriteCoord(MSG_ENTITY, self.origin_y);
+       WriteCoord(MSG_ENTITY, self.origin_z);
+
+       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);
+
+       WriteCoord(MSG_ENTITY, self.movedir_x);
+       WriteCoord(MSG_ENTITY, self.movedir_y);
+       WriteCoord(MSG_ENTITY, self.movedir_z);
+
+       WriteCoord(MSG_ENTITY, self.angles_x);
+       WriteCoord(MSG_ENTITY, self.angles_y);
+       WriteCoord(MSG_ENTITY, self.angles_z);
+}
+
+#elif defined(CSQC)
+
+void trigger_common_read(bool withtarget)
+{
+       self.warpzone_isboxy = ReadByte();
+       self.scale = ReadByte();
+
+       if(withtarget)
+       {
+               self.target = strzone(ReadString());
+               self.target2 = strzone(ReadString());
+               self.target3 = strzone(ReadString());
+               self.target4 = strzone(ReadString());
+               self.targetname = strzone(ReadString());
+               self.killtarget = strzone(ReadString());
+       }
+
+       self.origin_x = ReadCoord();
+       self.origin_y = ReadCoord();
+       self.origin_z = ReadCoord();
+       setorigin(self, self.origin);
+
+       self.mins_x = ReadCoord();
+       self.mins_y = ReadCoord();
+       self.mins_z = ReadCoord();
+       self.maxs_x = ReadCoord();
+       self.maxs_y = ReadCoord();
+       self.maxs_z = ReadCoord();
+       setsize(self, self.mins, self.maxs);
+
+       self.movedir_x = ReadCoord();
+       self.movedir_y = ReadCoord();
+       self.movedir_z = ReadCoord();
+
+       self.angles_x = ReadCoord();
+       self.angles_y = ReadCoord();
+       self.angles_z = ReadCoord();
+}
+
+void trigger_remove_generic()
+{
+       if(self.target) { strunzone(self.target); }
+       self.target = string_null;
+
+       if(self.target2) { strunzone(self.target2); }
+       self.target2 = string_null;
+
+       if(self.target3) { strunzone(self.target3); }
+       self.target3 = string_null;
+
+       if(self.target4) { strunzone(self.target4); }
+       self.target4 = string_null;
+
+       if(self.targetname) { strunzone(self.targetname); }
+       self.target = string_null;
+
+       if(self.killtarget) { strunzone(self.killtarget); }
+       self.killtarget = string_null;
+}
+#endif
+
+/*
+==============================
+SUB_UseTargets
+
+the global "activator" should be set to the entity that initiated the firing.
+
+If self.delay is set, a DelayedUse entity will be created that will actually
+do the SUB_UseTargets after that many seconds have passed.
+
+Centerprints any self.message to the activator.
+
+Removes all entities with a targetname that match self.killtarget,
+and removes them, so some events can remove other triggers.
+
+Search for (string)targetname in all entities that
+match (string)self.target and call their .use function
+
+==============================
+*/
+void SUB_UseTargets()
+{
+       entity t, stemp, otemp, act;
+       string s;
+       float i;
+
+//
+// check for a delay
+//
+       if (self.delay)
+       {
+       // create a temp object to fire at a later time
+               t = spawn();
+               t.classname = "DelayedUse";
+               t.nextthink = time + self.delay;
+               t.think = DelayThink;
+               t.enemy = activator;
+               t.message = self.message;
+               t.killtarget = self.killtarget;
+               t.target = self.target;
+               t.target2 = self.target2;
+               t.target3 = self.target3;
+               t.target4 = self.target4;
+               return;
+       }
+
+
+//
+// print the message
+//
+#ifdef SVQC
+       if(self)
+       if(IS_PLAYER(activator) && self.message != "")
+       if(IS_REAL_CLIENT(activator))
+       {
+               centerprint(activator, self.message);
+               if (self.noise == "")
+                       play2(activator, "misc/talk.wav");
+       }
+
+//
+// kill the killtagets
+//
+       s = self.killtarget;
+       if (s != "")
+       {
+               for(t = world; (t = find(t, targetname, s)); )
+                       remove(t);
+       }
+#endif
+
+//
+// fire targets
+//
+       act = activator;
+       stemp = self;
+       otemp = other;
+
+       if(stemp.target_random)
+               RandomSelection_Init();
+
+       for(i = 0; i < 4; ++i)
+       {
+               switch(i)
+               {
+                       default:
+                       case 0: s = stemp.target; break;
+                       case 1: s = stemp.target2; break;
+                       case 2: s = stemp.target3; break;
+                       case 3: s = stemp.target4; break;
+               }
+               if (s != "")
+               {
+                       // Flag to set func_clientwall state
+                       // 1 == deactivate, 2 == activate, 0 == do nothing
+                       float aw_flag = self.antiwall_flag;
+                       for(t = world; (t = find(t, targetname, s)); )
+                       if(t.use)
+                       {
+                               if(stemp.target_random)
+                               {
+                                       RandomSelection_Add(t, 0, string_null, 1, 0);
+                               }
+                               else
+                               {
+                                       if (t.classname == "func_clientwall" || t.classname == "func_clientillusionary")
+                                               t.antiwall_flag = aw_flag;
+                                       self = t;
+                                       other = stemp;
+                                       activator = act;
+                                       self.use();
+                               }
+                       }
+               }
+       }
+
+       if(stemp.target_random && RandomSelection_chosen_ent)
+       {
+               self = RandomSelection_chosen_ent;
+               other = stemp;
+               activator = act;
+               self.use();
+       }
+
+       activator = act;
+       self = stemp;
+       other = otemp;
+}
+
+#ifdef CSQC
+void trigger_touch_generic(void() touchfunc)
+{
+       entity e;
+       for(e = findradius((self.absmin + self.absmax) * 0.5, vlen(self.absmax - self.absmin) * 0.5 + 1); e; e = e.chain)
+       if(e.isplayermodel || e.classname == "csqcprojectile")
+       {
+               vector emin = e.absmin, emax = e.absmax;
+               if(self.solid == SOLID_BSP)
+               {
+                       emin -= '1 1 1';
+                       emax += '1 1 1';
+               }
+               if(boxesoverlap(emin, emax, self.absmin, self.absmax)) // quick
+               if(WarpZoneLib_BoxTouchesBrush(emin, emax, self, e)) // accurate
+               {
+                       other = e;
+                       touchfunc();
+               }
+       }
+}
+void trigger_draw_generic()
+{
+       float dt = time - self.move_time;
+       self.move_time = time;
+       if(dt <= 0) { return; }
+
+       if(self.trigger_touch) { trigger_touch_generic(self.trigger_touch); }
+}
+#endif
diff --git a/qcsrc/common/triggers/triggers.qh b/qcsrc/common/triggers/triggers.qh
new file mode 100644 (file)
index 0000000..474f797
--- /dev/null
@@ -0,0 +1,52 @@
+#ifndef TRIGGERS_H
+#define TRIGGERS_H
+
+const float SF_TRIGGER_INIT = 1;
+const float SF_TRIGGER_UPDATE = 2;
+const float SF_TRIGGER_RESET = 4;
+
+const float    SPAWNFLAG_NOMESSAGE = 1;
+const float    SPAWNFLAG_NOTOUCH = 1;
+
+.void() trigger_touch;
+
+.float antiwall_flag; // Variable to define what to do with func_clientwall
+// 0 == do nothing, 1 == deactivate, 2 == activate
+
+.float height;
+
+.float nottargeted;
+#define IFTARGETED if(!self.nottargeted && self.targetname != "")
+
+.float lip;
+
+// used elsewhere (will fix)
+#ifdef SVQC
+void trigger_common_write(bool withtarget);
+
+string trigger_magicear_processmessage_forallears(entity source, float teamsay, entity privatesay, string msgin);
+
+void target_voicescript_next(entity pl);
+void target_voicescript_clear(entity pl);
+#endif
+
+.float volume, atten;
+
+.vector dest;
+
+#ifdef CSQC
+void trigger_common_read(bool withtarget);
+void trigger_remove_generic();
+
+.float active;
+.string target;
+.string targetname;
+
+const int ACTIVE_NOT           = 0;
+const int ACTIVE_ACTIVE        = 1;
+const int ACTIVE_IDLE          = 2;
+const int ACTIVE_BUSY          = 2;
+const int ACTIVE_TOGGLE                = 3;
+#endif
+
+#endif
index ed4ebcf0615d26dfa52ea907ea96a190b5f6a6f5..9d60ae0a9ae2797bfdaedea9632237e81554f564 100644 (file)
     #define int float
 
     #define stoi(s) stof(s)
-    #define itos(s) ftos(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
 
 #ifndef QCC_SUPPORT_BOOL
     const int false = 0;
 #endif
 
+#ifndef QCC_SUPPORT_ENTITYCLASS
+    #define entityclass(name) typedef entity name
+    #define class(name)
+    #define new(class) spawn()
+#else
+    #define entityclass(name) entityclass name {}
+    #define class(name) [[class(name)]]
+    #define new(class) ((class) spawn())
+#endif
+
 // Transitional aliases
 [[deprecated("use true")]] [[alias("true")]] const bool TRUE;
 [[deprecated("use false")]] [[alias("false")]] const bool FALSE;
 
+#ifdef GMQCC
+    #define OVERLOAD(F, ...) F##_##__VA_COUNT__(__VA_ARGS__)
+#else
+    #define OVERLOAD_(F,_9,_8,_7,_6,_5,_4,_3,_2,_1,n,...) F##_##n
+    #define OVERLOAD(F, ...) OVERLOAD_(F,__VA_ARGS__,9,8,7,6,5,4,3,2,1)(__VA_ARGS__)
+#endif
+
+#define LAMBDA(...) { __VA_ARGS__ ; }
+
+#define MAP(f, ...) 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; }
+
+#define BIT(n) (1 << (n))
+#ifndef BRANCHLESS_BITSET
+    #define BITSET(var, mask, flag) (flag ? (var) | (mask) : (var) &~ (mask))
+#else
+    #define BITSET(var, mask, flag) ((var) ^ (-(flag) ^ (var)) & (mask))
+#endif
+
 #endif
index 49d707f077be45adc59a7867322022ed9be41d96..5479698acadb11d2fb1080d446e5926ce82a33d1 100644 (file)
@@ -184,26 +184,26 @@ void depthfirst(entity start, .entity up, .entity downleft, .entity right, void(
        entity e;
        e = start;
        funcPre(pass, e);
-       while(e.downleft)
+       while (e.(downleft))
        {
-               e = e.downleft;
+               e = e.(downleft);
                funcPre(pass, e);
        }
        funcPost(pass, e);
        while(e != start)
        {
-               if(e.right)
+               if (e.(right))
                {
-                       e = e.right;
+                       e = e.(right);
                        funcPre(pass, e);
-                       while(e.downleft)
+                       while (e.(downleft))
                        {
-                               e = e.downleft;
+                               e = e.(downleft);
                                funcPre(pass, e);
                        }
                }
                else
-                       e = e.up;
+                       e = e.(up);
                funcPost(pass, e);
        }
 }
@@ -1843,7 +1843,7 @@ void RandomSelection_Add(entity e, float f, string s, float weight, float priori
 }
 
 #ifndef MENUQC
-vector healtharmor_maxdamage(float h, float a, float armorblock, float deathtype)
+vector healtharmor_maxdamage(float h, float a, float armorblock, int deathtype)
 {
        // NOTE: we'll always choose the SMALLER value...
        float healthdamage, armordamage, armorideal;
@@ -1867,7 +1867,7 @@ vector healtharmor_maxdamage(float h, float a, float armorblock, float deathtype
        return v;
 }
 
-vector healtharmor_applydamage(float a, float armorblock, float deathtype, float damage)
+vector healtharmor_applydamage(float a, float armorblock, int deathtype, float damage)
 {
        vector v;
        if (deathtype == DEATH_DROWN)  // Why should armor help here...
@@ -2294,7 +2294,7 @@ float xdecode(string s)
        return ((a * 22 + b) * 22 + c) * 22 + d;
 }
 
-float lowestbit(int f)
+int lowestbit(int f)
 {
        f &= ~(f * 2);
        f &= ~(f * 4);
@@ -2539,11 +2539,11 @@ void FindConnectedComponent(entity e, .entity fld, findNextEntityNearFunction_t
 
        // start with a 1-element queue
        queue_start = queue_end = e;
-       queue_end.fld = world;
+       queue_end.(fld) = world;
        queue_end.FindConnectedComponent_processing = 1;
 
        // for each queued item:
-       for (; queue_start; queue_start = queue_start.fld)
+       for (; queue_start; queue_start = queue_start.(fld))
        {
                // find all neighbors of queue_start
                entity t;
@@ -2554,23 +2554,23 @@ void FindConnectedComponent(entity e, .entity fld, findNextEntityNearFunction_t
                        if(iscon(t, queue_start, pass))
                        {
                                // it is connected? ADD IT. It will look for neighbors soon too.
-                               queue_end.fld = t;
+                               queue_end.(fld) = t;
                                queue_end = t;
-                               queue_end.fld = world;
+                               queue_end.(fld) = world;
                                queue_end.FindConnectedComponent_processing = 1;
                        }
                }
        }
 
        // unmark
-       for(queue_start = e; queue_start; queue_start = queue_start.fld)
+       for (queue_start = e; queue_start; queue_start = queue_start.(fld))
                queue_start.FindConnectedComponent_processing = 0;
 }
 
 #ifdef SVQC
 vector combine_to_vector(float x, float y, float z)
 {
-       vector result; result.x = x; result.y = y; result.z = z;
+       vector result; result_x = x; result_y = y; result_z = z;
        return result;
 }
 
index b2cdf8dcaf2232be15fb675e2140d4018d686b64..2e41ce76ca796a1868b06085ff6dc197e06e7c86 100644 (file)
@@ -214,8 +214,8 @@ void RandomSelection_Init();
 void RandomSelection_Add(entity e, float f, string s, float weight, float priority);
 
 #ifndef MENUQC
-vector healtharmor_maxdamage(float h, float a, float armorblock, float deathtype); // returns vector: maxdamage, armorideal, 1 if fully armored
-vector healtharmor_applydamage(float a, float armorblock, float deathtype, float damage); // returns vector: take, save, 0
+vector healtharmor_maxdamage(float h, float a, float armorblock, int deathtype); // returns vector: maxdamage, armorideal, 1 if fully armored
+vector healtharmor_applydamage(float a, float armorblock, int deathtype, float damage); // returns vector: take, save, 0
 #endif
 
 string getcurrentmod();
@@ -296,7 +296,7 @@ float xdecode(string s);
 // Otherwise, channels 8 to 15 would be blocked for a weird QW feature.
 #define sound(e,c,s,v,a) sound7(e,c,s,v,a,0,0)
 
-float lowestbit(float f);
+int lowestbit(float f);
 
 #ifdef CSQC
 entity ReadCSQCEntity();
@@ -385,12 +385,12 @@ string autocvar_hud_colorset_background = "7"; // BG - White // neutral/unimport
 string CCR(string input);
 
 #ifndef MENUQC
-#ifdef CSQC
-#define GENTLE (autocvar_cl_gentle || autocvar_cl_gentle_messages)
-#else
-#define GENTLE autocvar_sv_gentle
-#endif
-#define normal_or_gentle(normal,gentle) (GENTLE ? ((gentle != "") ? gentle : normal) : normal)
+       #ifdef CSQC
+               #define GENTLE (autocvar_cl_gentle || autocvar_cl_gentle_messages)
+       #else
+               #define GENTLE autocvar_sv_gentle
+       #endif
+       #define normal_or_gentle(normal, gentle) (GENTLE ? ((gentle != "") ? gentle : normal) : normal)
 #endif
 
 // allow writing to also pass through to spectators (like so spectators see the same centerprints as players for example)
diff --git a/qcsrc/common/weapons/all.inc b/qcsrc/common/weapons/all.inc
new file mode 100644 (file)
index 0000000..4f4cd2b
--- /dev/null
@@ -0,0 +1,29 @@
+// ONLY EVER ADD NEW WEAPONS AT THE END. IF YOU REMOVE ONE, PUT THE LAST ONE ON
+// ITS PLACE. THIS IS TO AVOID UNNECESSARY RENUMBERING OF WEAPON IMPULSES.
+// IF YOU DISREGARD THIS NOTICE, I'LL KILL YOU WITH THE @!#%'N TUBA
+
+// core weapons
+#include "w_blaster.qc"
+#include "w_shotgun.qc"
+#include "w_machinegun.qc"
+#include "w_mortar.qc"
+#include "w_minelayer.qc"
+#include "w_electro.qc"
+#include "w_crylink.qc"
+#include "w_vortex.qc"
+#include "w_hagar.qc"
+#include "w_devastator.qc"
+
+// other weapons
+#include "w_porto.qc"
+#include "w_vaporizer.qc"
+#include "w_hook.qc"
+#include "w_hlac.qc"
+#include "w_tuba.qc"
+#include "w_rifle.qc"
+#include "w_fireball.qc"
+#include "w_seeker.qc"
+#include "w_shockwave.qc"
+#include "w_arc.qc"
+#include "w_hmg.qc"
+#include "w_rpc.qc"
diff --git a/qcsrc/common/weapons/all.qc b/qcsrc/common/weapons/all.qc
new file mode 100644 (file)
index 0000000..36f08ef
--- /dev/null
@@ -0,0 +1,375 @@
+#ifndef WEAPONS_ALL_C
+#define WEAPONS_ALL_C
+
+#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/mathlib.qh"
+       #include "../../warpzonelib/common.qh"
+       #include "../../warpzonelib/client.qh"
+       #include "../util.qh"
+       #include "../buffs.qh"
+       #include "../../client/autocvars.qh"
+       #include "../deathtypes.qh"
+       #include "../../csqcmodellib/interpolate.qh"
+       #include "../movetypes/movetypes.qh"
+       #include "../../client/main.qh"
+       #include "../../csqcmodellib/cl_model.qh"
+#elif defined(MENUQC)
+#elif defined(SVQC)
+       #include "../../dpdefs/progsdefs.qh"
+    #include "../../dpdefs/dpextensions.qh"
+    #include "../../warpzonelib/anglestransform.qh"
+    #include "../../warpzonelib/mathlib.qh"
+    #include "../../warpzonelib/common.qh"
+    #include "../../warpzonelib/util_server.qh"
+    #include "../../warpzonelib/server.qh"
+    #include "../constants.qh"
+    #include "../stats.qh"
+    #include "../teams.qh"
+    #include "../util.qh"
+    #include "../buffs.qh"
+    #include "../monsters/all.qh"
+    #include "config.qh"
+    #include "../../server/weapons/csqcprojectile.qh"
+    #include "../../server/weapons/tracing.qh"
+    #include "../../server/t_items.qh"
+    #include "../../server/autocvars.qh"
+    #include "../../server/constants.qh"
+    #include "../../server/defs.qh"
+    #include "../notifications.qh"
+    #include "../deathtypes.qh"
+    #include "../../server/mutators/mutators_include.qh"
+    #include "../mapinfo.qh"
+    #include "../../server/command/common.qh"
+    #include "../../csqcmodellib/sv_model.qh"
+    #include "../../server/portals.qh"
+    #include "../../server/g_hook.qh"
+#endif
+#ifndef MENUQC
+#include "calculations.qc"
+#endif
+#include "all.inc"
+
+// WEAPON PLUGIN SYSTEM
+entity weapon_info[WEP_MAXCOUNT];
+entity dummy_weapon_info;
+
+#if WEP_MAXCOUNT > 72
+# error Kein Weltraum links auf dem Gerät
+#endif
+
+WepSet WepSet_FromWeapon(int a) {
+       a -= WEP_FIRST;
+#if WEP_MAXCOUNT > 24
+       if(a >= 24) {
+               a -= 24;
+#if WEP_MAXCOUNT > 48
+               if(a >= 24) {
+                       a -= 24;
+                       return '0 0 1' * power2of(a);
+               }
+#endif
+               return '0 1 0' * power2of(a);
+       }
+#endif
+       return '1 0 0' * power2of(a);
+}
+#ifdef SVQC
+void WepSet_AddStat()
+{
+       addstat(STAT_WEAPONS, AS_INT, weapons_x);
+#if WEP_MAXCOUNT > 24
+       addstat(STAT_WEAPONS2, AS_INT, weapons_y);
+#if WEP_MAXCOUNT > 48
+       addstat(STAT_WEAPONS3, AS_INT, weapons_z);
+#endif
+#endif
+}
+void WriteWepSet(float dst, WepSet w)
+{
+#if WEP_MAXCOUNT > 48
+       WriteInt72_t(dst, w);
+#elif WEP_MAXCOUNT > 24
+       WriteInt48_t(dst, w);
+#else
+       WriteInt24_t(dst, w.x);
+#endif
+}
+#endif
+#ifdef CSQC
+WepSet WepSet_GetFromStat()
+{
+       WepSet w = '0 0 0';
+       w.x = getstati(STAT_WEAPONS);
+#if WEP_MAXCOUNT > 24
+       w.y = getstati(STAT_WEAPONS2);
+#if WEP_MAXCOUNT > 48
+       w.z = getstati(STAT_WEAPONS3);
+#endif
+#endif
+       return w;
+}
+WepSet ReadWepSet()
+{
+#if WEP_MAXCOUNT > 48
+       return ReadInt72_t();
+#elif WEP_MAXCOUNT > 24
+       return ReadInt48_t();
+#else
+       return ReadInt24_t() * '1 0 0';
+#endif
+}
+#endif
+
+void register_weapon(
+       int id,
+       WepSet bit,
+       bool(int) func,
+       .int ammotype,
+       int i,
+       int weapontype,
+       float pickupbasevalue,
+       vector clr,
+       string modelname,
+       string simplemdl,
+       string crosshair,
+       string wepimg,
+       string refname,
+       string wepname)
+{
+       entity e;
+       weapon_info[id - 1] = e = spawn();
+       e.classname = "weapon_info";
+       e.weapon = id;
+       e.weapons = bit;
+       e.weapon_func = func;
+       e.ammo_field = ammotype;
+       e.impulse = i;
+       e.spawnflags = weapontype;
+       e.bot_pickupbasevalue = pickupbasevalue;
+       e.wpcolor = clr;
+       e.wpmodel = strzone(strcat("wpn-", ftos(id)));
+       e.mdl = modelname;
+       e.model = strzone(strcat("models/weapons/g_", modelname, ".md3"));
+       e.w_simplemdl = strzone(simplemdl); // simpleitems weapon model/image
+       e.w_crosshair = strzone(car(crosshair));
+       string s = cdr(crosshair);
+       e.w_crosshair_size = ((s != "") ? stof(s) : 1); // so that we can scale the crosshair from code (for compat)
+       e.model2 = strzone(wepimg);
+       e.netname = refname;
+       e.message = wepname;
+
+       #ifdef CSQC
+       func(WR_INIT);
+       #endif
+}
+bool w_null(int dummy)
+{
+       return 0;
+}
+void register_weapons_done()
+{
+       dummy_weapon_info = spawn();
+       dummy_weapon_info.classname = "weapon_info";
+       dummy_weapon_info.weapon = 0; // you can recognize dummies by this
+       dummy_weapon_info.weapons = '0 0 0';
+       dummy_weapon_info.netname = "";
+       dummy_weapon_info.message = "AOL CD Thrower";
+       dummy_weapon_info.weapon_func = w_null;
+       dummy_weapon_info.wpmodel = "";
+       dummy_weapon_info.mdl = "";
+       dummy_weapon_info.model = "";
+       dummy_weapon_info.spawnflags = 0;
+       dummy_weapon_info.impulse = -1;
+       dummy_weapon_info.bot_pickupbasevalue = 0;
+       dummy_weapon_info.ammo_field = ammo_none;
+
+       dummy_weapon_info.w_crosshair = "gfx/crosshair1";
+       dummy_weapon_info.w_crosshair_size = 1;
+       dummy_weapon_info.model2 = "";
+
+       int i;
+       weaponorder_byid = "";
+       for(i = WEP_MAXCOUNT; i >= 1; --i)
+               if(weapon_info[i-1])
+                       weaponorder_byid = strcat(weaponorder_byid, " ", ftos(i));
+       weaponorder_byid = strzone(substring(weaponorder_byid, 1, strlen(weaponorder_byid) - 1));
+}
+entity get_weaponinfo(int id)
+{
+       entity w;
+       if(id < WEP_FIRST || id > WEP_LAST)
+               return dummy_weapon_info;
+       w = weapon_info[id - 1];
+       if(w)
+               return w;
+       return dummy_weapon_info;
+}
+string W_FixWeaponOrder(string order, float complete)
+{
+       return fixPriorityList(order, WEP_FIRST, WEP_LAST, 230 - WEP_FIRST, complete);
+}
+string W_NameWeaponOrder_MapFunc(string s)
+{
+       entity wi;
+       if(s == "0" || stof(s))
+       {
+               wi = get_weaponinfo(stof(s));
+               if(wi != dummy_weapon_info)
+                       return wi.netname;
+       }
+       return s;
+}
+
+string W_UndeprecateName(string s)
+{
+       switch ( s )
+       {
+               case "nex"            : return "vortex";
+               case "rocketlauncher" : return "devastator";
+               case "laser"          : return "blaster";
+               case "minstanex"      : return "vaporizer";
+               case "grenadelauncher": return "mortar";
+               case "uzi"            : return "machinegun";
+               default               : return s;
+       }
+}
+string W_NameWeaponOrder(string order)
+{
+       return mapPriorityList(order, W_NameWeaponOrder_MapFunc);
+}
+string W_NumberWeaponOrder_MapFunc(string s)
+{
+       int i;
+       if(s == "0" || stof(s))
+               return s;
+       s = W_UndeprecateName(s);
+       for(i = WEP_FIRST; i <= WEP_LAST; ++i)
+               if(s == get_weaponinfo(i).netname)
+                       return ftos(i);
+       return s;
+}
+string W_NumberWeaponOrder(string order)
+{
+       return mapPriorityList(order, W_NumberWeaponOrder_MapFunc);
+}
+
+float W_FixWeaponOrder_BuildImpulseList_buf[WEP_MAXCOUNT];
+string W_FixWeaponOrder_BuildImpulseList_order;
+void W_FixWeaponOrder_BuildImpulseList_swap(int i, int j, entity pass)
+{
+       float h;
+       h = W_FixWeaponOrder_BuildImpulseList_buf[i];
+       W_FixWeaponOrder_BuildImpulseList_buf[i] = W_FixWeaponOrder_BuildImpulseList_buf[j];
+       W_FixWeaponOrder_BuildImpulseList_buf[j] = h;
+}
+float W_FixWeaponOrder_BuildImpulseList_cmp(int i, int j, entity pass)
+{
+       entity e1, e2;
+       float d;
+       e1 = get_weaponinfo(W_FixWeaponOrder_BuildImpulseList_buf[i]);
+       e2 = get_weaponinfo(W_FixWeaponOrder_BuildImpulseList_buf[j]);
+       d = (e1.impulse + 9) % 10 - (e2.impulse + 9) % 10;
+       if(d != 0)
+               return -d; // high impulse first!
+       return
+               strstrofs(strcat(" ", W_FixWeaponOrder_BuildImpulseList_order, " "), sprintf(" %d ", W_FixWeaponOrder_BuildImpulseList_buf[i]), 0)
+               -
+               strstrofs(strcat(" ", W_FixWeaponOrder_BuildImpulseList_order, " "), sprintf(" %d ", W_FixWeaponOrder_BuildImpulseList_buf[j]), 0)
+               ; // low char index first!
+}
+string W_FixWeaponOrder_BuildImpulseList(string o)
+{
+       int i;
+       W_FixWeaponOrder_BuildImpulseList_order = o;
+       for(i = WEP_FIRST; i <= WEP_LAST; ++i)
+               W_FixWeaponOrder_BuildImpulseList_buf[i - WEP_FIRST] = i;
+       heapsort(WEP_LAST - WEP_FIRST + 1, W_FixWeaponOrder_BuildImpulseList_swap, W_FixWeaponOrder_BuildImpulseList_cmp, world);
+       o = "";
+       for(i = WEP_FIRST; i <= WEP_LAST; ++i)
+               o = strcat(o, " ", ftos(W_FixWeaponOrder_BuildImpulseList_buf[i - WEP_FIRST]));
+       W_FixWeaponOrder_BuildImpulseList_order = string_null;
+       return substring(o, 1, -1);
+}
+
+string W_FixWeaponOrder_AllowIncomplete(string order)
+{
+       return W_FixWeaponOrder(order, 0);
+}
+
+string W_FixWeaponOrder_ForceComplete(string order)
+{
+       if(order == "")
+               order = W_NumberWeaponOrder(cvar_defstring("cl_weaponpriority"));
+       return W_FixWeaponOrder(order, 1);
+}
+
+void W_RandomWeapons(entity e, float n)
+{
+       int i, j;
+       WepSet remaining;
+       WepSet result;
+       remaining = e.weapons;
+       result = '0 0 0';
+       for(i = 0; i < n; ++i)
+       {
+               RandomSelection_Init();
+               for(j = WEP_FIRST; j <= WEP_LAST; ++j)
+                       if(remaining & WepSet_FromWeapon(j))
+                               RandomSelection_Add(world, j, string_null, 1, 1);
+               result |= WepSet_FromWeapon(RandomSelection_chosen_float);
+               remaining &= ~WepSet_FromWeapon(RandomSelection_chosen_float);
+       }
+       e.weapons = result;
+}
+
+string GetAmmoPicture(.int ammotype)
+{
+       switch(ammotype)
+       {
+               case ammo_shells:  return "ammo_shells";
+               case ammo_nails:   return "ammo_bullets";
+               case ammo_rockets: return "ammo_rockets";
+               case ammo_cells:   return "ammo_cells";
+               case ammo_plasma:  return "ammo_cells";
+               case ammo_fuel:    return "ammo_fuel";
+               default: return ""; // wtf, no ammo type?
+       }
+}
+
+#ifdef CSQC
+.int GetAmmoFieldFromNum(int i)
+{
+       switch(i)
+       {
+               case 0: return ammo_shells;
+               case 1: return ammo_nails;
+               case 2: return ammo_rockets;
+               case 3: return ammo_cells;
+               case 4: return ammo_plasma;
+               case 5: return ammo_fuel;
+               default: return ammo_none;
+       }
+}
+
+int GetAmmoStat(.int ammotype)
+{
+       switch(ammotype)
+       {
+               case ammo_shells: return STAT_SHELLS;
+               case ammo_nails: return STAT_NAILS;
+               case ammo_rockets: return STAT_ROCKETS;
+               case ammo_cells: return STAT_CELLS;
+               case ammo_plasma: return STAT_PLASMA;
+               case ammo_fuel: return STAT_FUEL;
+               default: return -1;
+       }
+}
+#endif
+#endif
index b4ee1e25d9608d7d428cb22d9063413853b0da67..154f8167e91aa5c7faa2e7be866335c89d4031cf 100644 (file)
-// TODO: include once
-//#ifndef WEAPONS_ALL_H
-//#define WEAPONS_ALL_H
+#ifndef WEAPONS_ALL_H
+#define WEAPONS_ALL_H
+
+#ifndef MENUQC
+#include "calculations.qh"
+#endif
 
 #include "../util.qh"
+#ifdef SVQC
+#include "../../server/bot/aim.qh"
+#endif
+const int MAX_SHOT_DISTANCE = 32768;
+
+// weapon pickup ratings for bot logic
+const int BOT_PICKUP_RATING_LOW  =  2500;
+const int BOT_PICKUP_RATING_MID  =  5000;
+const int BOT_PICKUP_RATING_HIGH = 10000;
 
+// weapon flags
+const int WEP_TYPE_OTHER          =  0x00; // not for damaging people
+const int WEP_TYPE_SPLASH         =  0x01; // splash damage
+const int WEP_TYPE_HITSCAN        =  0x02; // hitscan
+const int WEP_TYPEMASK            =  0x0F;
+const int WEP_FLAG_CANCLIMB       =  0x10; // can be used for movement
+const int WEP_FLAG_NORMAL         =  0x20; // in "most weapons" set
+const int WEP_FLAG_HIDDEN         =  0x40; // hides from menu
+const int WEP_FLAG_RELOADABLE     =  0x80; // can has reload
+const int WEP_FLAG_SUPERWEAPON    = 0x100; // powerup timer
+const int WEP_FLAG_MUTATORBLOCKED = 0x200; // hides from impulse 99 etc. (mutators are allowed to clear this flag)
+
+// weapon requests
+const int WR_SETUP          =  1; // (SERVER) setup weapon data
+const int WR_THINK          =  2; // (SERVER) logic to run every frame
+const int WR_CHECKAMMO1     =  3; // (SERVER) checks ammo for weapon primary
+const int WR_CHECKAMMO2     =  4; // (SERVER) checks ammo for weapon second
+const int WR_AIM            =  5; // (SERVER) runs bot aiming code for this weapon
+const int WR_INIT           =  6; // (BOTH)   precaches models/sounds used by this weapon, also sets up weapon properties
+const int WR_SUICIDEMESSAGE =  7; // (SERVER) notification number for suicide message (may inspect w_deathtype for details)
+const int WR_KILLMESSAGE    =  8; // (SERVER) notification number for kill message (may inspect w_deathtype for details)
+const int WR_RELOAD         =  9; // (SERVER) handles reloading for weapon
+const int WR_RESETPLAYER    = 10; // (SERVER) clears fields that the weapon may use
+const int WR_IMPACTEFFECT   = 11; // (CLIENT) impact effect for weapon explosion
+const int WR_PLAYERDEATH    = 12; // (SERVER) called whenever a player dies
+const int WR_GONETHINK      = 13; // (SERVER) logic to run when weapon is lost
+const int WR_CONFIG         = 14; // (ALL)    dump weapon cvars to config in data directory (see: sv_cmd dumpweapons)
+const int WR_ZOOMRETICLE    = 15; // (CLIENT) weapon specific zoom reticle
+const int WR_DROP           = 16; // (SERVER) the weapon is dropped
+const int WR_PICKUP         = 17; // (SERVER) a weapon is picked up
+
+// variables:
+string weaponorder_byid;
+
+// weapon sets
+typedef vector WepSet;
+WepSet WepSet_FromWeapon(int a);
 #ifdef SVQC
-#   include "config.qh"
-#   include "../../server/bot/aim.qh"
+void WepSet_AddStat();
+void WriteWepSet(float dest, WepSet w);
+#endif
+#ifdef CSQC
+WepSet WepSet_GetFromStat();
+WepSet ReadWepSet();
+#endif
+
+// weapon name macros
+#define WEP_FIRST 1
+#define WEP_MAXCOUNT 24 // Increase as needed. Can be up to three times as much.
+int WEP_COUNT;
+int WEP_LAST;
+WepSet WEPSET_ALL;
+WepSet WEPSET_SUPERWEAPONS;
+
+// functions:
+entity get_weaponinfo(int id);
+string W_FixWeaponOrder(string order, float complete);
+string W_UndeprecateName(string s);
+string W_NameWeaponOrder(string order);
+string W_NumberWeaponOrder(string order);
+string W_FixWeaponOrder_BuildImpulseList(string o);
+string W_FixWeaponOrder_AllowIncomplete(string order);
+string W_FixWeaponOrder_ForceComplete(string order);
+void W_RandomWeapons(entity e, float n);
+
+string GetAmmoPicture(.int ammotype);
+
+#ifdef CSQC
+.int GetAmmoFieldFromNum(int i);
+int GetAmmoStat(.int ammotype);
+#endif
+
+// ammo types
+.int ammo_shells;
+.int ammo_nails;
+.int ammo_rockets;
+.int ammo_cells;
+.int ammo_plasma;
+.int ammo_fuel;
+.int ammo_none;
+
+// other useful macros
+#define WEP_ACTION(wpn,wrequest) (get_weaponinfo(wpn)).weapon_func(wrequest)
+#define WEP_AMMO(wpn) ((get_weaponinfo(WEP_##wpn)).ammo_field) // only used inside weapon files/with direct name, don't duplicate prefix
+#define WEP_NAME(wpn) ((get_weaponinfo(wpn)).message)
+
+
+// ======================
+//  Configuration Macros
+// ======================
+
+// create cvars for weapon settings
+#define WEP_ADD_CVAR_NONE(wepname,name) [[last]] float autocvar_g_balance_##wepname##_##name;
+
+#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)
+
+#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;
+
+// read cvars from weapon settings
+#define WEP_CVAR(wepname,name) autocvar_g_balance_##wepname##_##name
+#define WEP_CVAR_PRI(wepname,name) WEP_CVAR(wepname, primary_##name)
+#define WEP_CVAR_SEC(wepname,name) WEP_CVAR(wepname, secondary_##name)
+#define WEP_CVAR_BOTH(wepname,isprimary,name) ((isprimary) ? WEP_CVAR_PRI(wepname, name) : WEP_CVAR_SEC(wepname, name))
+
+// set initialization values for weapon settings
+#define WEP_SKIP_CVAR(unuseda,unusedb,unusedc,unusedd) /* skip cvars */
+#define WEP_SET_PROP(wepid,wepname,type,prop,name) get_weaponinfo(WEP_##wepid).##prop = autocvar_g_balance_##wepname##_##name;
+
+
+// =====================
+//  Weapon Registration
+// =====================
+
+bool w_null(int dummy);
+
+void register_weapon(
+       int id,
+       WepSet bit,
+       bool(int) func,
+       .int ammotype,
+       int i,
+       int weapontype,
+       float pickupbasevalue,
+       vector clr,
+       string modelname,
+       string simplemdl,
+       string crosshair,
+       string wepimg,
+       string refname,
+       string wepname);
+
+void register_weapons_done();
+
+// entity properties of weaponinfo:
+// fields which are explicitly/manually set are marked with "M", fields set automatically are marked with "A"
+.int weapon;                // M: WEP_id    // WEP_...
+.WepSet weapons;            // A: WEPSET_id // WEPSET_...
+.float(float) weapon_func;  // M: function  // w_...
+..int ammo_field;         // M: ammotype  // main ammo field
+.int impulse;               // M: impulse   // weapon impulse
+.int spawnflags;            // M: flags     // WEPSPAWNFLAG_... combined
+.float bot_pickupbasevalue; // M: rating    // bot weapon priority
+.vector wpcolor;            // M: color     // waypointsprite color
+.string wpmodel;            // A: wpn-id    // wpn- sprite name
+.string mdl;                // M: modelname // name of model (without g_ v_ or h_ prefixes)
+.string model;              // A: modelname // full path to g_ model
+.string w_simplemdl;        // M: simplemdl // simpleitems weapon model/image
+.string w_crosshair;        // M: crosshair // per-weapon crosshair: "CrosshairImage Size"
+.float w_crosshair_size;    // A: crosshair // per-weapon crosshair size (argument two of "crosshair" field)
+.string model2;             // M: wepimg    // "weaponfoobar" side view image file of weapon // WEAPONTODO: Move out of skin files, move to common files
+.string netname;            // M: refname   // reference name name
+.string message;            // M: wepname   // human readable name
+
+
+// note: the fabs call is just there to hide "if result is constant" warning
+#define REGISTER_WEAPON_2(id,bit,function,ammotype,impulse,flags,rating,color,modelname,simplemdl,crosshair,wepimg,refname,wepname) \
+       int id; \
+       WepSet bit; \
+       bool function(int); \
+       void RegisterWeapons_##id() \
+       { \
+               WEP_LAST = (id = WEP_FIRST + WEP_COUNT); \
+               bit = WepSet_FromWeapon(id); \
+               WEPSET_ALL |= bit; \
+               if((flags) & WEP_FLAG_SUPERWEAPON) \
+                       WEPSET_SUPERWEAPONS |= bit; \
+               ++WEP_COUNT; \
+               register_weapon(id,bit,function,ammotype,impulse,flags,rating,color,modelname,simplemdl,crosshair,wepimg,refname,wepname); \
+       } \
+       ACCUMULATE_FUNCTION(RegisterWeapons, RegisterWeapons_##id)
+#ifdef MENUQC
+#define REGISTER_WEAPON(id,function,ammotype,impulse,flags,rating,color,modelname,simplemdl,crosshair,wepimg,refname,wepname) \
+       REGISTER_WEAPON_2(WEP_##id,WEPSET_##id,w_null,ammotype,impulse,flags,rating,color,modelname,simplemdl,crosshair,wepimg,refname,wepname)
+#else
+#define REGISTER_WEAPON(id,function,ammotype,impulse,flags,rating,color,modelname,simplemdl,crosshair,wepimg,refname,wepname) \
+       REGISTER_WEAPON_2(WEP_##id,WEPSET_##id,function,ammotype,impulse,flags,rating,color,modelname,simplemdl,crosshair,wepimg,refname,wepname)
 #endif
 
-// ONLY EVER ADD NEW WEAPONS AT THE END. IF YOU REMOVE ONE, PUT THE LAST ONE ON
-// ITS PLACE. THIS IS TO AVOID UNNECESSARY RENUMBERING OF WEAPON IMPULSES.
-// IF YOU DISREGARD THIS NOTICE, I'LL KILL YOU WITH THE @!#%'N TUBA
-
-// core weapons
-#include "w_blaster.qc"
-#include "w_shotgun.qc"
-#include "w_machinegun.qc"
-#include "w_mortar.qc"
-#include "w_minelayer.qc"
-#include "w_electro.qc"
-#include "w_crylink.qc"
-#include "w_vortex.qc"
-#include "w_hagar.qc"
-#include "w_devastator.qc"
-
-// other weapons
-#include "w_porto.qc"
-#include "w_vaporizer.qc"
-#include "w_hook.qc"
-#include "w_hlac.qc"
-#include "w_tuba.qc"
-#include "w_rifle.qc"
-#include "w_fireball.qc"
-#include "w_seeker.qc"
-#include "w_shockwave.qc"
-#include "w_arc.qc"
-#include "w_hmg.qc"
-#include "w_rpc.qc"
-
-//#endif
+#include "all.inc"
+
+#undef WEP_ADD_CVAR_MO_PRI
+#undef WEP_ADD_CVAR_MO_SEC
+#undef WEP_ADD_CVAR_MO_BOTH
+#undef WEP_ADD_CVAR_MO_NONE
+#undef WEP_ADD_CVAR
+#undef WEP_ADD_PROP
+#undef REGISTER_WEAPON
+
+ACCUMULATE_FUNCTION(RegisterWeapons, register_weapons_done);
+#endif
index a314f036b3bb853cbc1b53251df380b6879f27e4..0448f4874a26c416f08d709a376705a20be8183f 100644 (file)
@@ -5,7 +5,7 @@
     #include "../../dpdefs/dpextensions.qh"
     #include "../util.qh"
     #include "config.qh"
-    #include "weapons.qh"
+    #include "all.qh"
 #endif
 
 // ==========================
index d8faa7be97daead90da13c9ab84dbcd7e23a89c0..79d4dc7c7ad99fea7663a8f9cc4d6289d9d74efa 100644 (file)
@@ -127,7 +127,7 @@ vector Draw_ArcBeam_callback_last_bottom; // NOTE: in same coordinate system as
 #ifdef SVQC
 void spawnfunc_weapon_arc(void) { weapon_defaultspawnfunc(WEP_ARC); }
 
-float W_Arc_Beam_Send(entity to, float sf)
+float W_Arc_Beam_Send(entity to, int sf)
 {
        WriteByte(MSG_ENTITY, ENT_CLIENT_ARC_BEAM);
 
@@ -239,6 +239,8 @@ void W_Arc_Beam_Think(void)
                ||
                self.owner.frozen
                ||
+               self.owner.vehicle
+               ||
                (WEP_CVAR(arc, overheat_max) > 0 && self.beam_heat >= WEP_CVAR(arc, overheat_max))
        )
        {
@@ -272,6 +274,7 @@ void W_Arc_Beam_Think(void)
                entity oldself = self;
                self = self.owner;
                if(!WEP_ACTION(WEP_ARC, WR_CHECKAMMO1) && !WEP_ACTION(WEP_ARC, WR_CHECKAMMO2))
+               if(!(self.items & IT_UNLIMITED_WEAPON_AMMO))
                {
                        // note: this doesn't force the switch
                        W_SwitchToOtherWeapon(self);
@@ -633,7 +636,7 @@ void Arc_Smoke()
        }
 }
 
-float W_Arc(float req)
+bool W_Arc(int req)
 {
        switch(req)
        {
@@ -1518,7 +1521,7 @@ void Ent_ReadArcBeam(float isnew)
        }
 }
 
-float W_Arc(float req)
+bool W_Arc(int req)
 {
        switch(req)
        {
index 8eaff86e35241899d5a760600f858b451e1c11f6..a776edbf4f5a383b2ae5fb136a68cc33c6f3c546 100644 (file)
@@ -147,7 +147,7 @@ void W_Blaster_Attack(
                self = oldself;
        }
 }
-float W_Blaster(float request)
+bool W_Blaster(int request)
 {
        switch(request)
        {
@@ -266,7 +266,7 @@ float W_Blaster(float request)
 }
 #endif
 #ifdef CSQC
-float W_Blaster(float request)
+bool W_Blaster(int request)
 {
        switch(request)
        {
index 21a86e7da0c33f7d901584c194b4575a450ca47e..4d4430206feab00a0f9c965bc5174782d4ce3fbd 100644 (file)
@@ -563,7 +563,7 @@ void W_Crylink_Attack2(void)
        }
 }
 
-float W_Crylink(float req)
+bool W_Crylink(int req)
 {
        float ammo_amount;
        switch(req)
@@ -689,7 +689,7 @@ float W_Crylink(float req)
 }
 #endif
 #ifdef CSQC
-float W_Crylink(float req)
+bool W_Crylink(int req)
 {
        switch(req)
        {
index 30d0da9cfabacb3b4912418e5be60d28950bb789..e9e0467e208ea0a9eed56642a412523adc4de74e 100644 (file)
@@ -103,6 +103,7 @@ void W_Devastator_Explode(void)
        if(self.realowner.weapon == WEP_DEVASTATOR)
        {
                if(self.realowner.WEP_AMMO(DEVASTATOR) < WEP_CVAR(devastator, ammo))
+               if(!(self.realowner.items & IT_UNLIMITED_WEAPON_AMMO))
                {
                        self.realowner.cnt = WEP_DEVASTATOR;
                        ATTACK_FINISHED(self.realowner) = time;
@@ -181,6 +182,7 @@ void W_Devastator_DoRemoteExplode(void)
        if(self.realowner.weapon == WEP_DEVASTATOR)
        {
                if(self.realowner.WEP_AMMO(DEVASTATOR) < WEP_CVAR(devastator, ammo))
+               if(!(self.realowner.items & IT_UNLIMITED_WEAPON_AMMO))
                {
                        self.realowner.cnt = WEP_DEVASTATOR;
                        ATTACK_FINISHED(self.realowner) = time;
@@ -317,7 +319,7 @@ void W_Devastator_Touch(void)
        W_Devastator_Explode();
 }
 
-void W_Devastator_Damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
+void W_Devastator_Damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
 {
        if(self.health <= 0)
                return;
@@ -389,7 +391,7 @@ void W_Devastator_Attack(void)
        other = missile; MUTATOR_CALLHOOK(EditProjectile);
 }
 
-float W_Devastator(float req)
+bool W_Devastator(int req)
 {
        entity rock;
        float rockfound;
@@ -653,7 +655,7 @@ float W_Devastator(float req)
 }
 #endif
 #ifdef CSQC
-float W_Devastator(float req)
+bool W_Devastator(int req)
 {
        switch(req)
        {
index 3f5e75159b5b8339490f0eb2c8aff57664e2fa65..e3b809296be709e884c8d993aff7a1730e897668 100644 (file)
@@ -300,7 +300,7 @@ void W_Electro_Orb_Touch(void)
        }
 }
 
-void W_Electro_Orb_Damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
+void W_Electro_Orb_Damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
 {
        if(self.health <= 0)
                return;
@@ -419,7 +419,7 @@ void W_Electro_CheckAttack(void)
 }
 
 .float bot_secondary_electromooth;
-float W_Electro(float req)
+bool W_Electro(int req)
 {
        float ammo_amount;
        switch(req)
@@ -569,7 +569,7 @@ float W_Electro(float req)
 }
 #endif
 #ifdef CSQC
-float W_Electro(float req)
+bool W_Electro(int req)
 {
        switch(req)
        {
index d0980091353b01615c9475f8ec9fd1caa1ee0736..7bb5ccb66c7ebf97e2c9588739eca324b74c65a9 100644 (file)
@@ -161,7 +161,7 @@ void W_Fireball_Think(void)
        self.nextthink = time + 0.1;
 }
 
-void W_Fireball_Damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
+void W_Fireball_Damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
 {
        if(self.health <= 0)
                return;
@@ -347,7 +347,7 @@ void W_Fireball_Attack2(void)
        other = proj; MUTATOR_CALLHOOK(EditProjectile);
 }
 
-float W_Fireball(float req)
+bool W_Fireball(int req)
 {
        switch(req)
        {
@@ -447,7 +447,7 @@ float W_Fireball(float req)
 }
 #endif
 #ifdef CSQC
-float W_Fireball(float req)
+bool W_Fireball(int req)
 {
        switch(req)
        {
index 1085c315afae03ef3992de648a29ad3c48344097..4c9f664989d2a77852acca35b5eb13127c60c648 100644 (file)
@@ -75,7 +75,7 @@ void W_Hagar_Explode2(void)
        remove(self);
 }
 
-void W_Hagar_Damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
+void W_Hagar_Damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
 {
        if(self.health <= 0)
                return;
@@ -299,7 +299,9 @@ void W_Hagar_Attack2_Load(void)
        loaded = self.hagar_load >= WEP_CVAR_SEC(hagar, load_max);
 
        // this is different than WR_CHECKAMMO when it comes to reloading
-       if(autocvar_g_balance_hagar_reload_ammo)
+       if(self.items & IT_UNLIMITED_WEAPON_AMMO)
+               enough_ammo = true;
+       else if(autocvar_g_balance_hagar_reload_ammo)
                enough_ammo = self.(weapon_load[WEP_HAGAR]) >= WEP_CVAR_SEC(hagar, ammo);
        else
                enough_ammo = self.WEP_AMMO(HAGAR) >= WEP_CVAR_SEC(hagar, ammo);
@@ -383,6 +385,7 @@ void W_Hagar_Attack2_Load(void)
 
        // we aren't checking ammo during an attack, so we must do it here
        if(!(WEP_ACTION(self.weapon, WR_CHECKAMMO1) + WEP_ACTION(self.weapon, WR_CHECKAMMO2)))
+       if(!(self.items & IT_UNLIMITED_WEAPON_AMMO))
        {
                // note: this doesn't force the switch
                W_SwitchToOtherWeapon(self);
@@ -390,7 +393,7 @@ void W_Hagar_Attack2_Load(void)
        }
 }
 
-float W_Hagar(float req)
+bool W_Hagar(int req)
 {
        float ammo_amount;
        switch(req)
@@ -519,7 +522,7 @@ float W_Hagar(float req)
 }
 #endif
 #ifdef CSQC
-float W_Hagar(float req)
+bool W_Hagar(int req)
 {
        switch(req)
        {
index 38f04841a727eb5b574f5333f303eb0feb1cc253..7f7d7a27b27e05cf37b205b718e22b1c1a20e849 100644 (file)
@@ -203,7 +203,7 @@ void W_HLAC_Attack2_Frame(void)
        }
 }
 
-float W_HLAC(float req)
+bool W_HLAC(int req)
 {
        float ammo_amount;
        switch(req)
@@ -282,7 +282,7 @@ float W_HLAC(float req)
 }
 #endif
 #ifdef CSQC
-float W_HLAC(float req)
+bool W_HLAC(int req)
 {
        switch(req)
        {
index 8190411cd648ebd829a1758db8762bb8fd7c1c7e..de9c983b2850f24f6777f687f50975eb43ce24d1 100644 (file)
@@ -85,7 +85,7 @@ void W_HeavyMachineGun_Attack_Auto()
        weapon_thinkf(WFRAME_FIRE1, WEP_CVAR(hmg, refire), W_HeavyMachineGun_Attack_Auto);
 }
 
-float W_HeavyMachineGun(float req)
+bool W_HeavyMachineGun(int req)
 {
        float ammo_amount;
        switch(req)
@@ -169,7 +169,7 @@ float W_HeavyMachineGun(float req)
 }
 #endif
 #ifdef CSQC
-float W_HeavyMachineGun(float req)
+bool W_HeavyMachineGun(int req)
 {
        switch(req)
        {
index 5d52dabaebba0ccc6e15f078de7a71cbb9ce0493..1c05c23d69c2ca84bf3a3a4abcc2abb884d36f34 100644 (file)
@@ -108,7 +108,7 @@ void W_Hook_Explode2(void)
        self.movetype = MOVETYPE_NONE;
 }
 
-void W_Hook_Damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
+void W_Hook_Damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
 {
        if(self.health <= 0)
                return;
@@ -173,7 +173,7 @@ void W_Hook_Attack2(void)
        other = gren; MUTATOR_CALLHOOK(EditProjectile);
 }
 
-float W_Hook(float req)
+bool W_Hook(int req)
 {
        float hooked_time_max, hooked_fuel;
 
@@ -336,7 +336,7 @@ float W_Hook(float req)
 }
 #endif
 #ifdef CSQC
-float W_Hook(float req)
+bool W_Hook(int req)
 {
        switch(req)
        {
index 14a59e39892583450992262c11cdff7dd9c92cc0..24a0db83f44534a4c7ff3cfbd453851b86796621 100644 (file)
@@ -101,7 +101,7 @@ void W_MachineGun_MuzzleFlash(void)
        self.muzzle_flash.owner = self.muzzle_flash.realowner = self;
 }
 
-void W_MachineGun_Attack(float deathtype)
+void W_MachineGun_Attack(int deathtype)
 {
        W_SetupShot(self, true, 0, "weapons/uzi_fire.wav", CH_WEAPON_A, ((self.misc_bulletcounter == 1) ? WEP_CVAR(machinegun, first_damage) : WEP_CVAR(machinegun, sustained_damage)));
        if(!autocvar_g_norecoil)
@@ -235,7 +235,7 @@ void W_MachineGun_Attack_Burst(void)
 
 }
 
-float W_MachineGun(float req)
+bool W_MachineGun(int req)
 {
        float ammo_amount;
        switch(req)
@@ -369,7 +369,7 @@ float W_MachineGun(float req)
 }
 #endif
 #ifdef CSQC
-float W_MachineGun(float req)
+bool W_MachineGun(int req)
 {
        switch(req)
        {
index 2fe0172a9435d1d195e71c8d5e7b0cb4e38d7386..d4ef9554702af9628800348dd0180e84baf6c90c 100644 (file)
@@ -194,9 +194,9 @@ void W_MineLayer_ProximityExplode(void)
        W_MineLayer_Explode();
 }
 
-float W_MineLayer_Count(entity e)
+int W_MineLayer_Count(entity e)
 {
-       float minecount = 0;
+       int minecount = 0;
        entity mine;
        for(mine = world; (mine = find(mine, classname, "mine")); ) if(mine.realowner == e)
                minecount += 1;
@@ -290,7 +290,7 @@ void W_MineLayer_Touch(void)
        }
 }
 
-void W_MineLayer_Damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
+void W_MineLayer_Damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
 {
        if(self.health <= 0)
                return;
@@ -400,7 +400,7 @@ float W_MineLayer_PlacedMines(float detonate)
        return minfound;
 }
 
-float W_MineLayer(float req)
+bool W_MineLayer(int req)
 {
        entity mine;
        float ammo_amount;
@@ -591,7 +591,7 @@ float W_MineLayer(float req)
 }
 #endif
 #ifdef CSQC
-float W_MineLayer(float req)
+bool W_MineLayer(int req)
 {
        switch(req)
        {
index 34b5e57473cbf8d6a0e8eb774d3ea78bc258b62e..c958372afb8177ba8e8bf5c205cd32abf8614836 100644 (file)
@@ -99,7 +99,7 @@ void W_Mortar_Grenade_Explode2(void)
 }
 
 
-void W_Mortar_Grenade_Damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
+void W_Mortar_Grenade_Damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
 {
        if(self.health <= 0)
                return;
@@ -319,7 +319,7 @@ void W_Mortar_Attack2(void)
 }
 
 .float bot_secondary_grenademooth;
-float W_Mortar(float req)
+bool W_Mortar(int req)
 {
        entity nade;
        float nadefound;
@@ -459,7 +459,7 @@ float W_Mortar(float req)
 }
 #endif
 #ifdef CSQC
-float W_Mortar(float req)
+bool W_Mortar(int req)
 {
        switch(req)
        {
index 0010449a025923feff26357579fc0a98fd2fe9d0..82baf07bd1fa46b16d853fa019a13bc838257969 100644 (file)
@@ -38,6 +38,8 @@ PORTO_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP)
 #endif
 #else
 #ifdef SVQC
+#include "../triggers/trigger/jumppads.qh"
+
 void spawnfunc_weapon_porto(void) { weapon_defaultspawnfunc(WEP_PORTO); }
 
 void W_Porto_Success(void)
@@ -122,7 +124,7 @@ void W_Porto_Touch(void)
        norm = trace_plane_normal;
        if(trace_ent.iscreature)
        {
-               traceline(trace_ent.origin, trace_ent.origin + '0 0 2' * PL_MIN_z, MOVE_WORLDONLY, self);
+               traceline(trace_ent.origin, trace_ent.origin + '0 0 2' * PL_MIN.z, MOVE_WORLDONLY, self);
                if(trace_fraction >= 1)
                        return;
                if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_SLICK || trace_dphitcontents & DPCONTENTS_PLAYERCLIP)
@@ -284,8 +286,8 @@ void W_Porto_Attack(float type)
        other = gren; MUTATOR_CALLHOOK(EditProjectile);
 }
 
-float w_nexball_weapon(float req); // WEAPONTODO
-float W_Porto(float req)
+bool w_nexball_weapon(int req); // WEAPONTODO
+bool W_Porto(int req)
 {
        //vector v_angle_save;
 
@@ -396,7 +398,7 @@ float W_Porto(float req)
 }
 #endif
 #ifdef CSQC
-float W_Porto(float req)
+bool W_Porto(int req)
 {
        switch(req)
        {
index f20872f7045067fb300a1c24ffd6240a0af5e773..16d6ad6f833925fb510fe37d8182b758a10ea4c8 100644 (file)
@@ -50,7 +50,7 @@ void spawnfunc_weapon_rifle(void) { weapon_defaultspawnfunc(WEP_RIFLE); }
 void spawnfunc_weapon_campingrifle(void) { spawnfunc_weapon_rifle(); }
 void spawnfunc_weapon_sniperrifle(void) { spawnfunc_weapon_rifle(); }
 
-void W_Rifle_FireBullet(float pSpread, float pDamage, float pForce, float pSolidPenetration, float pAmmo, float deathtype, float pTracer, float pShots, string pSound)
+void W_Rifle_FireBullet(float pSpread, float pDamage, float pForce, float pSolidPenetration, float pAmmo, int deathtype, float pTracer, float pShots, string pSound)
 {
        float i;
 
@@ -133,7 +133,7 @@ void W_Rifle_BulletHail(float mode, void(void) AttackFunc, float fr, float animt
 }
 
 .float bot_secondary_riflemooth;
-float W_Rifle(float req)
+bool W_Rifle(int req)
 {
        float ammo_amount;
 
@@ -264,7 +264,7 @@ float W_Rifle(float req)
 }
 #endif
 #ifdef CSQC
-float W_Rifle(float req)
+bool W_Rifle(int req)
 {
        switch(req)
        {
index 387dc32d82eb5c891bc40b3a8fbbdd6e6a70a50e..d641572c343f87c7a01c151cc61ca9ec8ef235cf 100644 (file)
@@ -65,7 +65,7 @@ void W_RocketPropelledChainsaw_Touch (void)
        W_RocketPropelledChainsaw_Explode();
 }
 
-void W_RocketPropelledChainsaw_Damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
+void W_RocketPropelledChainsaw_Damage (entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
 {
        if (self.health <= 0)
                return;
@@ -146,7 +146,7 @@ void W_RocketPropelledChainsaw_Attack (void)
        other = missile; MUTATOR_CALLHOOK(EditProjectile);
 }
 
-float W_RocketPropelledChainsaw(float req)
+bool W_RocketPropelledChainsaw(int req)
 {
        float ammo_amount = false;
        switch(req)
@@ -232,7 +232,7 @@ float W_RocketPropelledChainsaw(float req)
 #endif
 
 #ifdef CSQC
-float W_RocketPropelledChainsaw(float req)
+bool W_RocketPropelledChainsaw(int req)
 {
        switch(req)
        {
index 45a121ab40bef47b03a42f32090dcf3b6fed3c84..f338ed7ea376d43ccad3d00ca30f4e047a02894b 100644 (file)
@@ -200,7 +200,7 @@ void W_Seeker_Missile_Think(void)
 
 
 
-void W_Seeker_Missile_Damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
+void W_Seeker_Missile_Damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
 {
        if(self.health <= 0)
                return;
@@ -482,7 +482,7 @@ void W_Seeker_Tag_Explode(void)
        remove(self);
 }
 
-void W_Seeker_Tag_Damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
+void W_Seeker_Tag_Damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
 {
        if(self.health <= 0)
                return;
@@ -596,7 +596,7 @@ void W_Seeker_Fire_Tag(void)
 // Begin: Genereal weapon functions
 // ============================
 
-float W_Seeker(float req)
+bool W_Seeker(int req)
 {
        float ammo_amount;
 
@@ -725,7 +725,7 @@ float W_Seeker(float req)
 }
 #endif
 #ifdef CSQC
-float W_Seeker(float req)
+bool W_Seeker(int req)
 {
        switch(req)
        {
index 3f40c5397fcfb8d34b96f4db4e0132c8b07bc5d1..d23ce753a57d383b4c885b23cc6a48b0be12cd1f 100644 (file)
@@ -665,7 +665,7 @@ void W_Shockwave_Attack(void)
        }
 }
 
-float W_Shockwave(float req)
+bool W_Shockwave(int req)
 {
        switch(req)
        {
@@ -864,7 +864,7 @@ void Net_ReadShockwaveParticle(void)
        shockwave.sw_time = time;
 }
 
-float W_Shockwave(float req)
+bool W_Shockwave(int req)
 {
        switch(req)
        {
index 0b70b85729fe463d832bfc0b6e8edc0e5b211efe..3c40519d6330b06d7b8cdfb4719f0884c7a69828 100644 (file)
@@ -55,7 +55,7 @@ float W_Tuba_MarkClientOnlyFieldsAsUsed() {
 #ifdef SVQC
 void spawnfunc_weapon_tuba(void) { weapon_defaultspawnfunc(WEP_TUBA); }
 
-float W_Tuba_HasPlayed(entity pl, string melody, float instrument, float ignorepitch, float mintempo, float maxtempo)
+bool W_Tuba_HasPlayed(entity pl, string melody, int instrument, bool ignorepitch, float mintempo, float maxtempo)
 {
        float i, j, mmin, mmax, nolength;
        float n = tokenize_console(melody);
@@ -182,7 +182,7 @@ void W_Tuba_NoteOff(void)
        remove(self);
 }
 
-float W_Tuba_GetNote(entity pl, float hittype)
+int W_Tuba_GetNote(entity pl, int hittype)
 {
        float movestate = 5;
        if (pl.movement.x < 0)          movestate -= 3;
@@ -190,7 +190,7 @@ float W_Tuba_GetNote(entity pl, float hittype)
        if (pl.movement.y < 0)          movestate -= 1;
        else if (pl.movement.y > 0)     movestate += 1;
 
-       float note = 0;
+       int note = 0;
        switch(movestate)
        {
        // layout: originally I wanted
@@ -250,9 +250,9 @@ float W_Tuba_GetNote(entity pl, float hittype)
        return note;
 }
 
-float W_Tuba_NoteSendEntity(entity to, float sf)
+bool W_Tuba_NoteSendEntity(entity to, int sf)
 {
-       float f;
+       int f;
 
        msg_entity = to;
        if(!sound_allowed(MSG_ONE, self.realowner))
@@ -367,7 +367,7 @@ void W_Tuba_NoteOn(float hittype)
        }
 }
 
-float W_Tuba(float req)
+bool W_Tuba(int req)
 {
        switch(req)
        {
@@ -493,7 +493,7 @@ float W_Tuba(float req)
 }
 #endif
 #ifdef CSQC
-float W_Tuba(float req)
+bool W_Tuba(int req)
 {
        // nothing to do here; particles of tuba are handled differently
        // WEAPONTODO
index 374256403d88def7a6fde94d0526e3a51f3b98e8..3c0d21354de46d73af552d758ab95f81bd293f10 100644 (file)
@@ -53,6 +53,8 @@ REGISTER_WEAPON(
 
 #ifdef SVQC
 VORTEX_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP)
+
+.float vortex_lasthit;
 #endif
 #else
 #ifdef SVQC
@@ -107,10 +109,18 @@ void W_Vortex_Attack(float issecondary)
        }
 
        yoda = 0;
+       damage_goodhits = 0;
        FireRailgunBullet(w_shotorg, w_shotorg + w_shotdir * MAX_SHOT_DISTANCE, mydmg, myforce, mymindist, mymaxdist, myhalflife, myforcehalflife, WEP_VORTEX);
 
        if(yoda && flying)
                Send_Notification(NOTIF_ONE, self, MSG_ANNCE, ANNCE_ACHIEVEMENT_YODA);
+       if(damage_goodhits && self.vortex_lasthit)
+       {
+               Send_Notification(NOTIF_ONE, self, MSG_ANNCE, ANNCE_ACHIEVEMENT_IMPRESSIVE);
+               damage_goodhits = 0; // only every second time
+       }
+
+       self.vortex_lasthit = damage_goodhits;
 
        //beam and muzzle flash done on client
        SendCSQCVortexBeamParticle(charge);
@@ -121,7 +131,7 @@ void W_Vortex_Attack(float issecondary)
 void spawnfunc_weapon_vortex(void); // defined in t_items.qc
 
 .float vortex_chargepool_pauseregen_finished;
-float W_Vortex(float req)
+bool W_Vortex(int req)
 {
        float dt;
        float ammo_amount;
@@ -254,6 +264,11 @@ float W_Vortex(float req)
                        VORTEX_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP);
                        return true;
                }
+               case WR_SETUP:
+               {
+                       self.vortex_lasthit = 0;
+                       return true;
+               }
                case WR_CHECKAMMO1:
                {
                        ammo_amount = self.WEP_AMMO(VORTEX) >= WEP_CVAR_PRI(vortex, ammo);
@@ -279,6 +294,11 @@ float W_Vortex(float req)
                        VORTEX_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS);
                        return true;
                }
+               case WR_RESETPLAYER:
+               {
+                       self.vortex_lasthit = 0;
+                       return true;
+               }
                case WR_RELOAD:
                {
                        W_Reload(min(WEP_CVAR_PRI(vortex, ammo), WEP_CVAR_SEC(vortex, ammo)), "weapons/reload.wav");
@@ -298,7 +318,7 @@ float W_Vortex(float req)
 #endif
 #ifdef CSQC
 float autocvar_g_balance_vortex_secondary = 0; // WEAPONTODO
-float W_Vortex(float req)
+bool W_Vortex(int req)
 {
        switch(req)
        {
diff --git a/qcsrc/common/weapons/weapons.qc b/qcsrc/common/weapons/weapons.qc
deleted file mode 100644 (file)
index 55fcc0e..0000000
+++ /dev/null
@@ -1,375 +0,0 @@
-#ifndef WEAPONS_C
-#define WEAPONS_C
-
-#include "weapons.qh"
-
-#if defined(CSQC)
-       #include "../../dpdefs/csprogsdefs.qh"
-       #include "../../client/defs.qh"
-       #include "../constants.qh"
-       #include "../stats.qh"
-       #include "../../warpzonelib/anglestransform.qh"
-       #include "../../warpzonelib/mathlib.qh"
-       #include "../../warpzonelib/common.qh"
-       #include "../../warpzonelib/client.qh"
-       #include "../util.qh"
-       #include "../buffs.qh"
-       #include "../../client/autocvars.qh"
-       #include "../deathtypes.qh"
-       #include "../../csqcmodellib/interpolate.qh"
-       #include "../../client/movetypes.qh"
-       #include "../../client/main.qh"
-       #include "../../csqcmodellib/cl_model.qh"
-#elif defined(MENUQC)
-#elif defined(SVQC)
-       #include "../../dpdefs/progsdefs.qh"
-    #include "../../dpdefs/dpextensions.qh"
-    #include "../../warpzonelib/anglestransform.qh"
-    #include "../../warpzonelib/mathlib.qh"
-    #include "../../warpzonelib/common.qh"
-    #include "../../warpzonelib/util_server.qh"
-    #include "../../warpzonelib/server.qh"
-    #include "../constants.qh"
-    #include "../stats.qh"
-    #include "../teams.qh"
-    #include "../util.qh"
-    #include "../buffs.qh"
-    #include "../monsters/monsters.qh"
-    #include "config.qh"
-    #include "../../server/weapons/csqcprojectile.qh"
-    #include "../../server/weapons/tracing.qh"
-    #include "../../server/t_items.qh"
-    #include "../../server/autocvars.qh"
-    #include "../../server/constants.qh"
-    #include "../../server/defs.qh"
-    #include "../notifications.qh"
-    #include "../deathtypes.qh"
-    #include "../../server/mutators/mutators_include.qh"
-    #include "../mapinfo.qh"
-    #include "../../server/command/common.qh"
-    #include "../../csqcmodellib/sv_model.qh"
-    #include "../../server/portals.qh"
-    #include "../../server/g_hook.qh"
-#endif
-#ifndef MENUQC
-#include "calculations.qc"
-#endif
-#include "all.qh"
-
-// WEAPON PLUGIN SYSTEM
-entity weapon_info[WEP_MAXCOUNT];
-entity dummy_weapon_info;
-
-#if WEP_MAXCOUNT > 72
-# error Kein Weltraum links auf dem Gerät
-#endif
-
-WepSet WepSet_FromWeapon(float a) {
-       a -= WEP_FIRST;
-#if WEP_MAXCOUNT > 24
-       if(a >= 24) {
-               a -= 24;
-#if WEP_MAXCOUNT > 48
-               if(a >= 24) {
-                       a -= 24;
-                       return '0 0 1' * power2of(a);
-               }
-#endif
-               return '0 1 0' * power2of(a);
-       }
-#endif
-       return '1 0 0' * power2of(a);
-}
-#ifdef SVQC
-void WepSet_AddStat()
-{
-       addstat(STAT_WEAPONS, AS_INT, weapons_x);
-#if WEP_MAXCOUNT > 24
-       addstat(STAT_WEAPONS2, AS_INT, weapons_y);
-#if WEP_MAXCOUNT > 48
-       addstat(STAT_WEAPONS3, AS_INT, weapons_z);
-#endif
-#endif
-}
-void WriteWepSet(float dst, WepSet w)
-{
-#if WEP_MAXCOUNT > 48
-       WriteInt72_t(dst, w);
-#elif WEP_MAXCOUNT > 24
-       WriteInt48_t(dst, w);
-#else
-       WriteInt24_t(dst, w.x);
-#endif
-}
-#endif
-#ifdef CSQC
-WepSet WepSet_GetFromStat()
-{
-       WepSet w = '0 0 0';
-       w.x = getstati(STAT_WEAPONS);
-#if WEP_MAXCOUNT > 24
-       w.y = getstati(STAT_WEAPONS2);
-#if WEP_MAXCOUNT > 48
-       w.z = getstati(STAT_WEAPONS3);
-#endif
-#endif
-       return w;
-}
-WepSet ReadWepSet()
-{
-#if WEP_MAXCOUNT > 48
-       return ReadInt72_t();
-#elif WEP_MAXCOUNT > 24
-       return ReadInt48_t();
-#else
-       return ReadInt24_t() * '1 0 0';
-#endif
-}
-#endif
-
-void register_weapon(
-       int id,
-       WepSet bit,
-       float(float) func,
-       .float ammotype,
-       float i,
-       float weapontype,
-       float pickupbasevalue,
-       vector clr,
-       string modelname,
-       string simplemdl,
-       string crosshair,
-       string wepimg,
-       string refname,
-       string wepname)
-{
-       entity e;
-       weapon_info[id - 1] = e = spawn();
-       e.classname = "weapon_info";
-       e.weapon = id;
-       e.weapons = bit;
-       e.weapon_func = func;
-       e.ammo_field = ammotype;
-       e.impulse = i;
-       e.spawnflags = weapontype;
-       e.bot_pickupbasevalue = pickupbasevalue;
-       e.wpcolor = clr;
-       e.wpmodel = strzone(strcat("wpn-", ftos(id)));
-       e.mdl = modelname;
-       e.model = strzone(strcat("models/weapons/g_", modelname, ".md3"));
-       e.w_simplemdl = strzone(simplemdl); // simpleitems weapon model/image
-       e.w_crosshair = strzone(car(crosshair));
-       string s = cdr(crosshair);
-       e.w_crosshair_size = ((s != "") ? stof(s) : 1); // so that we can scale the crosshair from code (for compat)
-       e.model2 = strzone(wepimg);
-       e.netname = refname;
-       e.message = wepname;
-
-       #ifdef CSQC
-       func(WR_INIT);
-       #endif
-}
-float w_null(float dummy)
-{
-       return 0;
-}
-void register_weapons_done()
-{
-       dummy_weapon_info = spawn();
-       dummy_weapon_info.classname = "weapon_info";
-       dummy_weapon_info.weapon = 0; // you can recognize dummies by this
-       dummy_weapon_info.weapons = '0 0 0';
-       dummy_weapon_info.netname = "";
-       dummy_weapon_info.message = "AOL CD Thrower";
-       dummy_weapon_info.weapon_func = w_null;
-       dummy_weapon_info.wpmodel = "";
-       dummy_weapon_info.mdl = "";
-       dummy_weapon_info.model = "";
-       dummy_weapon_info.spawnflags = 0;
-       dummy_weapon_info.impulse = -1;
-       dummy_weapon_info.bot_pickupbasevalue = 0;
-       dummy_weapon_info.ammo_field = ammo_none;
-
-       dummy_weapon_info.w_crosshair = "gfx/crosshair1";
-       dummy_weapon_info.w_crosshair_size = 1;
-       dummy_weapon_info.model2 = "";
-
-       int i;
-       weaponorder_byid = "";
-       for(i = WEP_MAXCOUNT; i >= 1; --i)
-               if(weapon_info[i-1])
-                       weaponorder_byid = strcat(weaponorder_byid, " ", ftos(i));
-       weaponorder_byid = strzone(substring(weaponorder_byid, 1, strlen(weaponorder_byid) - 1));
-}
-entity get_weaponinfo(int id)
-{
-       entity w;
-       if(id < WEP_FIRST || id > WEP_LAST)
-               return dummy_weapon_info;
-       w = weapon_info[id - 1];
-       if(w)
-               return w;
-       return dummy_weapon_info;
-}
-string W_FixWeaponOrder(string order, float complete)
-{
-       return fixPriorityList(order, WEP_FIRST, WEP_LAST, 230 - WEP_FIRST, complete);
-}
-string W_NameWeaponOrder_MapFunc(string s)
-{
-       entity wi;
-       if(s == "0" || stof(s))
-       {
-               wi = get_weaponinfo(stof(s));
-               if(wi != dummy_weapon_info)
-                       return wi.netname;
-       }
-       return s;
-}
-
-string W_UndeprecateName(string s)
-{
-       switch ( s )
-       {
-               case "nex"            : return "vortex";
-               case "rocketlauncher" : return "devastator";
-               case "laser"          : return "blaster";
-               case "minstanex"      : return "vaporizer";
-               case "grenadelauncher": return "mortar";
-               case "uzi"            : return "machinegun";
-               default               : return s;
-       }
-}
-string W_NameWeaponOrder(string order)
-{
-       return mapPriorityList(order, W_NameWeaponOrder_MapFunc);
-}
-string W_NumberWeaponOrder_MapFunc(string s)
-{
-       float i;
-       if(s == "0" || stof(s))
-               return s;
-       s = W_UndeprecateName(s);
-       for(i = WEP_FIRST; i <= WEP_LAST; ++i)
-               if(s == get_weaponinfo(i).netname)
-                       return ftos(i);
-       return s;
-}
-string W_NumberWeaponOrder(string order)
-{
-       return mapPriorityList(order, W_NumberWeaponOrder_MapFunc);
-}
-
-float W_FixWeaponOrder_BuildImpulseList_buf[WEP_MAXCOUNT];
-string W_FixWeaponOrder_BuildImpulseList_order;
-void W_FixWeaponOrder_BuildImpulseList_swap(int i, int j, entity pass)
-{
-       float h;
-       h = W_FixWeaponOrder_BuildImpulseList_buf[i];
-       W_FixWeaponOrder_BuildImpulseList_buf[i] = W_FixWeaponOrder_BuildImpulseList_buf[j];
-       W_FixWeaponOrder_BuildImpulseList_buf[j] = h;
-}
-float W_FixWeaponOrder_BuildImpulseList_cmp(int i, int j, entity pass)
-{
-       entity e1, e2;
-       float d;
-       e1 = get_weaponinfo(W_FixWeaponOrder_BuildImpulseList_buf[i]);
-       e2 = get_weaponinfo(W_FixWeaponOrder_BuildImpulseList_buf[j]);
-       d = (e1.impulse + 9) % 10 - (e2.impulse + 9) % 10;
-       if(d != 0)
-               return -d; // high impulse first!
-       return
-               strstrofs(strcat(" ", W_FixWeaponOrder_BuildImpulseList_order, " "), sprintf(" %d ", W_FixWeaponOrder_BuildImpulseList_buf[i]), 0)
-               -
-               strstrofs(strcat(" ", W_FixWeaponOrder_BuildImpulseList_order, " "), sprintf(" %d ", W_FixWeaponOrder_BuildImpulseList_buf[j]), 0)
-               ; // low char index first!
-}
-string W_FixWeaponOrder_BuildImpulseList(string o)
-{
-       int i;
-       W_FixWeaponOrder_BuildImpulseList_order = o;
-       for(i = WEP_FIRST; i <= WEP_LAST; ++i)
-               W_FixWeaponOrder_BuildImpulseList_buf[i - WEP_FIRST] = i;
-       heapsort(WEP_LAST - WEP_FIRST + 1, W_FixWeaponOrder_BuildImpulseList_swap, W_FixWeaponOrder_BuildImpulseList_cmp, world);
-       o = "";
-       for(i = WEP_FIRST; i <= WEP_LAST; ++i)
-               o = strcat(o, " ", ftos(W_FixWeaponOrder_BuildImpulseList_buf[i - WEP_FIRST]));
-       W_FixWeaponOrder_BuildImpulseList_order = string_null;
-       return substring(o, 1, -1);
-}
-
-string W_FixWeaponOrder_AllowIncomplete(string order)
-{
-       return W_FixWeaponOrder(order, 0);
-}
-
-string W_FixWeaponOrder_ForceComplete(string order)
-{
-       if(order == "")
-               order = W_NumberWeaponOrder(cvar_defstring("cl_weaponpriority"));
-       return W_FixWeaponOrder(order, 1);
-}
-
-void W_RandomWeapons(entity e, float n)
-{
-       float i, j;
-       WepSet remaining;
-       WepSet result;
-       remaining = e.weapons;
-       result = '0 0 0';
-       for(i = 0; i < n; ++i)
-       {
-               RandomSelection_Init();
-               for(j = WEP_FIRST; j <= WEP_LAST; ++j)
-                       if(remaining & WepSet_FromWeapon(j))
-                               RandomSelection_Add(world, j, string_null, 1, 1);
-               result |= WepSet_FromWeapon(RandomSelection_chosen_float);
-               remaining &= ~WepSet_FromWeapon(RandomSelection_chosen_float);
-       }
-       e.weapons = result;
-}
-
-string GetAmmoPicture(.float ammotype)
-{
-       switch(ammotype)
-       {
-               case ammo_shells:  return "ammo_shells";
-               case ammo_nails:   return "ammo_bullets";
-               case ammo_rockets: return "ammo_rockets";
-               case ammo_cells:   return "ammo_cells";
-               case ammo_plasma:  return "ammo_cells";
-               case ammo_fuel:    return "ammo_fuel";
-               default: return ""; // wtf, no ammo type?
-       }
-}
-
-#ifdef CSQC
-.float GetAmmoFieldFromNum(int i)
-{
-       switch(i)
-       {
-               case 0: return ammo_shells;
-               case 1: return ammo_nails;
-               case 2: return ammo_rockets;
-               case 3: return ammo_cells;
-               case 4: return ammo_plasma;
-               case 5: return ammo_fuel;
-               default: return ammo_none;
-       }
-}
-
-int GetAmmoStat(.float ammotype)
-{
-       switch(ammotype)
-       {
-               case ammo_shells: return STAT_SHELLS;
-               case ammo_nails: return STAT_NAILS;
-               case ammo_rockets: return STAT_ROCKETS;
-               case ammo_cells: return STAT_CELLS;
-               case ammo_plasma: return STAT_PLASMA;
-               case ammo_fuel: return STAT_FUEL;
-               default: return -1;
-       }
-}
-#endif
-#endif
diff --git a/qcsrc/common/weapons/weapons.qh b/qcsrc/common/weapons/weapons.qh
deleted file mode 100644 (file)
index 7ac8a9e..0000000
+++ /dev/null
@@ -1,213 +0,0 @@
-#ifndef WEAPONS_H
-#define WEAPONS_H
-
-#ifndef MENUQC
-#include "calculations.qh"
-#endif
-
-const int MAX_SHOT_DISTANCE = 32768;
-
-// weapon pickup ratings for bot logic
-const int BOT_PICKUP_RATING_LOW  =  2500;
-const int BOT_PICKUP_RATING_MID  =  5000;
-const int BOT_PICKUP_RATING_HIGH = 10000;
-
-// weapon flags
-const int WEP_TYPE_OTHER          =  0x00; // not for damaging people
-const int WEP_TYPE_SPLASH         =  0x01; // splash damage
-const int WEP_TYPE_HITSCAN        =  0x02; // hitscan
-const int WEP_TYPEMASK            =  0x0F;
-const int WEP_FLAG_CANCLIMB       =  0x10; // can be used for movement
-const int WEP_FLAG_NORMAL         =  0x20; // in "most weapons" set
-const int WEP_FLAG_HIDDEN         =  0x40; // hides from menu
-const int WEP_FLAG_RELOADABLE     =  0x80; // can has reload
-const int WEP_FLAG_SUPERWEAPON    = 0x100; // powerup timer
-const int WEP_FLAG_MUTATORBLOCKED = 0x200; // hides from impulse 99 etc. (mutators are allowed to clear this flag)
-
-// weapon requests
-const int WR_SETUP          =  1; // (SERVER) setup weapon data
-const int WR_THINK          =  2; // (SERVER) logic to run every frame
-const int WR_CHECKAMMO1     =  3; // (SERVER) checks ammo for weapon primary
-const int WR_CHECKAMMO2     =  4; // (SERVER) checks ammo for weapon second
-const int WR_AIM            =  5; // (SERVER) runs bot aiming code for this weapon
-const int WR_INIT           =  6; // (BOTH)   precaches models/sounds used by this weapon, also sets up weapon properties
-const int WR_SUICIDEMESSAGE =  7; // (SERVER) notification number for suicide message (may inspect w_deathtype for details)
-const int WR_KILLMESSAGE    =  8; // (SERVER) notification number for kill message (may inspect w_deathtype for details)
-const int WR_RELOAD         =  9; // (SERVER) handles reloading for weapon
-const int WR_RESETPLAYER    = 10; // (SERVER) clears fields that the weapon may use
-const int WR_IMPACTEFFECT   = 11; // (CLIENT) impact effect for weapon explosion
-const int WR_PLAYERDEATH    = 12; // (SERVER) called whenever a player dies
-const int WR_GONETHINK      = 13; // (SERVER) logic to run when weapon is lost
-const int WR_CONFIG         = 14; // (ALL)    dump weapon cvars to config in data directory (see: sv_cmd dumpweapons)
-const int WR_ZOOMRETICLE    = 15; // (CLIENT) weapon specific zoom reticle
-const int WR_DROP           = 16; // (SERVER) the weapon is dropped
-const int WR_PICKUP         = 17; // (SERVER) a weapon is picked up
-
-// variables:
-string weaponorder_byid;
-
-// weapon sets
-typedef vector WepSet;
-WepSet WepSet_FromWeapon(float a);
-#ifdef SVQC
-void WepSet_AddStat();
-void WriteWepSet(float dest, WepSet w);
-#endif
-#ifdef CSQC
-WepSet WepSet_GetFromStat();
-WepSet ReadWepSet();
-#endif
-
-// weapon name macros
-#define WEP_FIRST 1
-#define WEP_MAXCOUNT 24 // Increase as needed. Can be up to three times as much.
-int WEP_COUNT;
-int WEP_LAST;
-WepSet WEPSET_ALL;
-WepSet WEPSET_SUPERWEAPONS;
-
-// functions:
-entity get_weaponinfo(float id);
-string W_FixWeaponOrder(string order, float complete);
-string W_UndeprecateName(string s);
-string W_NameWeaponOrder(string order);
-string W_NumberWeaponOrder(string order);
-string W_FixWeaponOrder_BuildImpulseList(string o);
-string W_FixWeaponOrder_AllowIncomplete(string order);
-string W_FixWeaponOrder_ForceComplete(string order);
-void W_RandomWeapons(entity e, float n);
-
-string GetAmmoPicture(.float ammotype);
-
-#ifdef CSQC
-.float GetAmmoFieldFromNum(int i);
-int GetAmmoStat(.float ammotype);
-#endif
-
-// ammo types
-.float ammo_shells;
-.float ammo_nails;
-.float ammo_rockets;
-.float ammo_cells;
-.float ammo_plasma;
-.float ammo_fuel;
-.float ammo_none;
-
-// other useful macros
-#define WEP_ACTION(wpn,wrequest) (get_weaponinfo(wpn)).weapon_func(wrequest)
-#define WEP_AMMO(wpn) ((get_weaponinfo(WEP_##wpn)).ammo_field) // only used inside weapon files/with direct name, don't duplicate prefix
-#define WEP_NAME(wpn) ((get_weaponinfo(wpn)).message)
-
-
-// ======================
-//  Configuration Macros
-// ======================
-
-// create cvars for weapon settings
-#define WEP_ADD_CVAR_NONE(wepname,name) [[last]] float autocvar_g_balance_##wepname##_##name;
-
-#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)
-
-#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;
-
-// read cvars from weapon settings
-#define WEP_CVAR(wepname,name) autocvar_g_balance_##wepname##_##name
-#define WEP_CVAR_PRI(wepname,name) WEP_CVAR(wepname, primary_##name)
-#define WEP_CVAR_SEC(wepname,name) WEP_CVAR(wepname, secondary_##name)
-#define WEP_CVAR_BOTH(wepname,isprimary,name) ((isprimary) ? WEP_CVAR_PRI(wepname, name) : WEP_CVAR_SEC(wepname, name))
-
-// set initialization values for weapon settings
-#define WEP_SKIP_CVAR(unuseda,unusedb,unusedc,unusedd) /* skip cvars */
-#define WEP_SET_PROP(wepid,wepname,type,prop,name) get_weaponinfo(WEP_##wepid).##prop = autocvar_g_balance_##wepname##_##name;
-
-
-// =====================
-//  Weapon Registration
-// =====================
-
-float w_null(float dummy);
-
-void register_weapon(
-       float id,
-       WepSet bit,
-       float(float) func,
-       .float ammotype,
-       float i,
-       float weapontype,
-       float pickupbasevalue,
-       vector clr,
-       string modelname,
-       string simplemdl,
-       string crosshair,
-       string wepimg,
-       string refname,
-       string wepname);
-
-void register_weapons_done();
-
-// entity properties of weaponinfo:
-// fields which are explicitly/manually set are marked with "M", fields set automatically are marked with "A"
-.int weapon;                // M: WEP_id    // WEP_...
-.WepSet weapons;            // A: WEPSET_id // WEPSET_...
-.float(float) weapon_func;  // M: function  // w_...
-..float ammo_field;         // M: ammotype  // main ammo field
-.int impulse;               // M: impulse   // weapon impulse
-.int spawnflags;            // M: flags     // WEPSPAWNFLAG_... combined
-.float bot_pickupbasevalue; // M: rating    // bot weapon priority
-.vector wpcolor;            // M: color     // waypointsprite color
-.string wpmodel;            // A: wpn-id    // wpn- sprite name
-.string mdl;                // M: modelname // name of model (without g_ v_ or h_ prefixes)
-.string model;              // A: modelname // full path to g_ model
-.string w_simplemdl;        // M: simplemdl // simpleitems weapon model/image
-.string w_crosshair;        // M: crosshair // per-weapon crosshair: "CrosshairImage Size"
-.float w_crosshair_size;    // A: crosshair // per-weapon crosshair size (argument two of "crosshair" field)
-.string model2;             // M: wepimg    // "weaponfoobar" side view image file of weapon // WEAPONTODO: Move out of skin files, move to common files
-.string netname;            // M: refname   // reference name name
-.string message;            // M: wepname   // human readable name
-
-
-// note: the fabs call is just there to hide "if result is constant" warning
-#define REGISTER_WEAPON_2(id,bit,function,ammotype,impulse,flags,rating,color,modelname,simplemdl,crosshair,wepimg,refname,wepname) \
-       int id; \
-       WepSet bit; \
-       float function(float); \
-       void RegisterWeapons_##id() \
-       { \
-               WEP_LAST = (id = WEP_FIRST + WEP_COUNT); \
-               bit = WepSet_FromWeapon(id); \
-               WEPSET_ALL |= bit; \
-               if((flags) & WEP_FLAG_SUPERWEAPON) \
-                       WEPSET_SUPERWEAPONS |= bit; \
-               ++WEP_COUNT; \
-               register_weapon(id,bit,function,ammotype,impulse,flags,rating,color,modelname,simplemdl,crosshair,wepimg,refname,wepname); \
-       } \
-       ACCUMULATE_FUNCTION(RegisterWeapons, RegisterWeapons_##id)
-#ifdef MENUQC
-#define REGISTER_WEAPON(id,function,ammotype,impulse,flags,rating,color,modelname,simplemdl,crosshair,wepimg,refname,wepname) \
-       REGISTER_WEAPON_2(WEP_##id,WEPSET_##id,w_null,ammotype,impulse,flags,rating,color,modelname,simplemdl,crosshair,wepimg,refname,wepname)
-#else
-#define REGISTER_WEAPON(id,function,ammotype,impulse,flags,rating,color,modelname,simplemdl,crosshair,wepimg,refname,wepname) \
-       REGISTER_WEAPON_2(WEP_##id,WEPSET_##id,function,ammotype,impulse,flags,rating,color,modelname,simplemdl,crosshair,wepimg,refname,wepname)
-#endif
-
-#include "all.qh"
-
-#undef WEP_ADD_CVAR_MO_PRI
-#undef WEP_ADD_CVAR_MO_SEC
-#undef WEP_ADD_CVAR_MO_BOTH
-#undef WEP_ADD_CVAR_MO_NONE
-#undef WEP_ADD_CVAR
-#undef WEP_ADD_PROP
-#undef REGISTER_WEAPON
-
-ACCUMULATE_FUNCTION(RegisterWeapons, register_weapons_done);
-#endif
index 6d3542bd0028ad55f84a4c817e4c78b5f6bf1d16..95489ad4326de10d9874c5fd29118e1cdd3ba8cc 100644 (file)
@@ -68,7 +68,7 @@ void CSQCModel_InterpolateAnimation_1To2_PreNote(int sf)
                self.frame2time = self.frame1time;
        }
 }
-void CSQCModel_InterpolateAnimation_PreNote(float sf)
+void CSQCModel_InterpolateAnimation_PreNote(int sf)
 {
 #ifdef CSQCMODEL_HAVE_TWO_FRAMES
        CSQCModel_InterpolateAnimation_2To4_PreNote(sf);
@@ -104,7 +104,7 @@ void CSQCModel_InterpolateAnimation_1To2_Note(int sf, float set_times)
                        self.frame1time = time;
        }
 }
-void CSQCModel_InterpolateAnimation_Note(float sf)
+void CSQCModel_InterpolateAnimation_Note(int sf)
 {
 #ifdef CSQCMODEL_HAVE_TWO_FRAMES
        CSQCModel_InterpolateAnimation_2To4_Note(sf, true);
index c2aca6f7a2677a9291b294ca17cbbea5f8377063..98f1da03b49561fb6e3b7ac272196f87622615b2 100644 (file)
@@ -42,12 +42,12 @@ entity CSQCModel_server2csqc(float pl);
 
 // this is exported for custom frame animation code. Use with care.
 // to update frames, first call this:
-void CSQCModel_InterpolateAnimation_2To4_PreNote(float sf);
-void CSQCModel_InterpolateAnimation_1To2_PreNote(float sf);
+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(float sf, float set_times);
-void CSQCModel_InterpolateAnimation_1To2_Note(float sf, float set_times);
+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();
index 1f3017afdefd64766649fc7636b9602034b718a9..4360527674e16be74180abadb8a95aac5279e226 100644 (file)
@@ -35,6 +35,7 @@
 #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
@@ -104,12 +105,12 @@ void CSQCPlayer_Unpredict()
        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.pmove_flags = player_pmflags;
+       self.flags = player_pmflags;
 }
 
 void CSQCPlayer_SetMinsMaxs()
 {
-       if(self.pmove_flags & PMF_DUCKED)
+       if(self.flags & FL_DUCKED)
        {
                self.mins = PL_CROUCH_MIN;
                self.maxs = PL_CROUCH_MAX;
@@ -125,13 +126,35 @@ void CSQCPlayer_SetMinsMaxs()
 
 void CSQCPlayer_SavePrediction()
 {
-       player_pmflags = self.pmove_flags;
+       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()
+{
+       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)
 {
        CSQCPlayer_Unpredict();
@@ -166,7 +189,7 @@ void CSQCPlayer_PredictTo(float endframe, float apply_error)
                {
                        if (!getinputstate(csqcplayer_moveframe))
                                break;
-                       runstandardplayerphysics(self);
+                       CSQCPlayer_Physics();
                        CSQCPlayer_SetMinsMaxs();
                        csqcplayer_moveframe++;
                }
@@ -177,7 +200,7 @@ void CSQCPlayer_PredictTo(float endframe, float apply_error)
        input_angles = view_angles;
 }
 
-float CSQCPlayer_IsLocalPlayer()
+bool CSQCPlayer_IsLocalPlayer()
 {
        return (self == csqcplayer);
 }
@@ -199,16 +222,16 @@ void CSQCPlayer_SetCamera()
                        self.view_ofs = '0 0 1' * getstati(STAT_VIEWHEIGHT);
 
                        // get crouch state from the server
-                       if(getstati(STAT_VIEWHEIGHT) == PL_VIEW_OFS_z)
-                               self.pmove_flags &= ~PMF_DUCKED;
-                       else if(getstati(STAT_VIEWHEIGHT) == PL_CROUCH_VIEW_OFS_z)
-                               self.pmove_flags |= PMF_DUCKED;
+                       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.pmove_flags |= PMF_ONGROUND;
+                               self.flags |= FL_ONGROUND;
                        else
-                               self.pmove_flags &= ~PMF_ONGROUND;
+                               self.flags &= ~FL_ONGROUND;
 
                        CSQCPlayer_SetMinsMaxs();
 
@@ -232,21 +255,21 @@ void CSQCPlayer_SetCamera()
                                v = v0;
                                csqcplayer_status = CSQCPLAYERSTATUS_PREDICTED;
                                CSQCPlayer_PredictTo(servercommandframe + 1, false);
-                               CSQCPlayer_SetPredictionError(self.origin - o, self.velocity - v, pmove_onground - !!(self.pmove_flags & PMF_ONGROUND));
+                               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.pmove_flags &= ~PMF_DUCKED;
-                               else if(getstati(STAT_VIEWHEIGHT) == PL_CROUCH_VIEW_OFS_z)
-                                       self.pmove_flags |= PMF_DUCKED;
+                               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.pmove_flags |= PMF_ONGROUND;
+                                       self.flags |= FL_ONGROUND;
                                else
-                                       self.pmove_flags &= ~PMF_ONGROUND;
+                                       self.flags &= ~FL_ONGROUND;
 
                                CSQCPlayer_SavePrediction();
                        }
@@ -254,10 +277,10 @@ void CSQCPlayer_SetCamera()
 
 #ifdef CSQCMODEL_SERVERSIDE_CROUCH
                        // get crouch state from the server (LAG)
-                       if(getstati(STAT_VIEWHEIGHT) == PL_VIEW_OFS_z)
-                               self.pmove_flags &= ~PMF_DUCKED;
-                       else if(getstati(STAT_VIEWHEIGHT) == PL_CROUCH_VIEW_OFS_z)
-                               self.pmove_flags |= PMF_DUCKED;
+                       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();
index 55e63cf56dfd144e886970d17f1b35967a6cccca..e427e6cf363f855510aaaa56b65b7df23384801a 100644 (file)
@@ -34,6 +34,8 @@ 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();
index 425c985ad6926cb6a060f30e924ec33964e79ddf..32c8b870755997168cc9c7a708bcf9ac15f75923 100644 (file)
@@ -36,7 +36,7 @@
 
 // generic CSQC model code
 
-float CSQCModel_Send(entity to, int sf)
+bool CSQCModel_Send(entity to, int sf)
 {
        // some nice flags for CSQCMODEL_IF
        float isplayer = (IS_CLIENT(self));
index 4effe6492446b65192b91d838bebd11da4828c1b..c4d8c54ce05c4b6b847a36f54d1d6672beda0379 100644 (file)
 
 #pragma noref 1
 
-/*
-==============================================================================
+#define true _true
+#define false _false
+#define TRUE _TRUE
+#define FALSE _FALSE
 
-                       SOURCE FOR GLOBALVARS_T C STRUCTURE
-                       MUST NOT BE MODIFIED, OR CRC ERRORS WILL APPEAR
+#include "upstream/csprogsdefs.qc"
 
-==============================================================================
-*/
-
-//
-// system globals
-//
-entity         self;
-entity         other;
-entity         world;
-float          time;
-float          frametime;
-
-int            player_localentnum;     //the entnum
-int            player_localnum;        //the playernum
-float          maxclients;     //a constant filled in by the engine. gah, portability eh?
-
-float          clientcommandframe;     //player movement
-float          servercommandframe;     //clientframe echoed off the server
-
-string         mapname;
-
-//
-// global variables set by built in functions
-//
-vector         v_forward, v_up, v_right;       // set by makevectors()
-
-// set by traceline / tracebox
-float          trace_allsolid;
-float          trace_startsolid;
-float          trace_fraction;
-vector         trace_endpos;
-vector         trace_plane_normal;
-float          trace_plane_dist;
-entity         trace_ent;
-float          trace_inopen;
-float          trace_inwater;
-
-//
-// required prog functions
-//
-void()         CSQC_Init;
-void()         CSQC_Shutdown;
-float(float f, float t, float n)       CSQC_InputEvent;
-void(float w, float h)         CSQC_UpdateView;
-bool(string s) CSQC_ConsoleCommand;
-
-//these fields are read and set by the default player physics
-vector         pmove_org;
-vector         pmove_vel;
-vector         pmove_mins;
-vector         pmove_maxs;
-//retrieved from the current movement commands (read by player physics)
-float          input_timelength;
-vector         input_angles;
-vector         input_movevalues;       //forwards, right, up.
-int                    input_buttons;          //attack, use, jump (default physics only uses jump)
-
-float          movevar_gravity;
-float          movevar_stopspeed;
-float          movevar_maxspeed;
-float          movevar_spectatormaxspeed;      //used by NOCLIP movetypes.
-float          movevar_accelerate;
-float          movevar_airaccelerate;
-float          movevar_wateraccelerate;
-float          movevar_friction;
-float          movevar_waterfriction;
-float          movevar_entgravity;     //the local player's gravity field. Is a multiple (1 is the normal value)
-
-//================================================
-void           end_sys_globals;                // flag for structure dumping
-//================================================
-
-/*
-==============================================================================
-
-                       SOURCE FOR ENTVARS_T C STRUCTURE
-                       MUST NOT BE MODIFIED, OR CRC ERRORS WILL APPEAR
-
-==============================================================================
-*/
-
-//
-// system fields (*** = do not set in prog code, maintained by C code)
-//
-.int           modelindex;             // *** model index in the precached list
-.vector                absmin, absmax; // *** origin + mins / maxs
-
-.int           entnum; // *** the ent number as on the server
-.float         drawmask;
-.void()                predraw;
-
-.float         movetype;
-.float         solid;
-
-.vector                origin;                 // ***
-.vector                oldorigin;              // ***
-.vector                velocity;
-.vector                angles;
-.vector                avelocity;
-
-.string                classname;              // spawn function
-.string                model;
-.int           frame;
-.int           skin;
-.int           effects;
-
-.vector                mins, maxs;             // bounding box extents reletive to origin
-.vector                size;                   // maxs - mins
-
-.void()                touch;
-.void()                use;
-.void()                think;
-.void()                blocked;                // for doors or plats, called when can't push other
-
-.float         nextthink;
-
-.entity                chain;
-
-.string                netname;
-
-.entity        enemy;
-
-.int           flags;
-
-.int           colormap;
-
-.entity                owner;          // who launched a missile
-
-//================================================
-void           end_sys_fields;                 // flag for structure dumping
-//================================================
-
-/*
-==============================================================================
-
-                       OPTIONAL FIELDS AND GLOBALS
-
-==============================================================================
-*/
-
-// Additional OPTIONAL Fields and Globals
-float          intermission; // indicates intermission state (0 = normal, 1 = scores, 2 = finale text)
-
-vector         view_angles; // same as input_angles
-vector         view_punchangle; // from server
-vector         view_punchvector; // from server
-
-/*
-==============================================================================
-
-                       CONSTANT DEFINITIONS
-
-==============================================================================
-*/
-
-const int MASK_ENGINE                  = 1;
-const int MASK_ENGINEVIEWMODELS        = 2;
-const int MASK_NORMAL                  = 4;
-
-const int RF_VIEWMODEL                 = 1;
-const int RF_EXTERNALMODEL             = 2;
-const int RF_DEPTHHACK                 = 4;
-const int RF_ADDITIVE                  = 8;
-const int RF_USEAXIS                   = 16;
-
-const int VF_MIN                               = 1;    //(vector)
-const int VF_MIN_X                             = 2;    //(float)
-const int VF_MIN_Y                             = 3;    //(float)
-const int VF_SIZE                              = 4;    //(vector) (viewport size)
-const int VF_SIZE_Y                            = 5;    //(float)
-const int VF_SIZE_X                            = 6;    //(float)
-const int VF_VIEWPORT                  = 7;    //(vector, vector)
-const int VF_FOV                               = 8;    //(vector)
-const int VF_FOVX                              = 9;    //(float)
-const int VF_FOVY                              = 10;   //(float)
-const int VF_ORIGIN                            = 11;   //(vector)
-const int VF_ORIGIN_X                  = 12;   //(float)
-const int VF_ORIGIN_Y                  = 13;   //(float)
-const int VF_ORIGIN_Z                  = 14;   //(float)
-const int VF_ANGLES                            = 15;   //(vector)
-const int VF_ANGLES_X                  = 16;   //(float)
-const int VF_ANGLES_Y                  = 17;   //(float)
-const int VF_ANGLES_Z                  = 18;   //(float)
-const int VF_DRAWWORLD                 = 19;   //(float)
-const int VF_DRAWENGINESBAR            = 20;   //(float)
-const int VF_DRAWCROSSHAIR             = 21;   //(float)
-
-const int VF_CL_VIEWANGLES             = 33;   //(vector)
-const int VF_CL_VIEWANGLES_X   = 34;   //(float)
-const int VF_CL_VIEWANGLES_Y   = 35;   //(float)
-const int VF_CL_VIEWANGLES_Z   = 36;   //(float)
-
-const int VF_PERSPECTIVE       = 200;
-
-//const int STAT_HEALTH                        = 0;
-//const int STAT_WEAPONMODEL   = 2;
-//const int STAT_AMMO                  = 3;
-//const int STAT_ARMOR                 = 4;
-//const int STAT_WEAPONFRAME   = 5;
-//const int STAT_SHELLS                        = 6;
-//const int STAT_NAILS                 = 7;
-//const int STAT_ROCKETS               = 8;
-//const int STAT_CELLS                 = 9;
-//const int STAT_ACTIVEWEAPON  = 10;
-//const int STAT_TOTALSECRETS  = 11;
-//const int STAT_TOTALMONSTERS = 12;
-//const int STAT_SECRETS               = 13;
-//const int STAT_MONSTERS              = 14;
-//const int STAT_ITEMS                 = 15;
-//const int STAT_VIEWHEIGHT            = 16;
-
-// Quake Sound Constants
-const int CHAN_AUTO                            = 0;
-const int CHAN_WEAPON                  = 1;
-const int CHAN_VOICE                   = 2;
-const int CHAN_ITEM                            = 3;
-const int CHAN_BODY                            = 4;
-
-const int ATTN_NONE                            = 0;
-const int ATTN_NORM                            = 1;
-const int ATTN_IDLE                            = 2;
-const int ATTN_STATIC                  = 3;
-
-// Frik File Constants
-const int FILE_READ                            = 0;
-const int FILE_APPEND                  = 1;
-const int FILE_WRITE                   = 2;
-
-// Quake Point Contents
-const int CONTENT_EMPTY                        = -1;
-const int CONTENT_SOLID                        = -2;
-const int CONTENT_WATER                        = -3;
-const int CONTENT_SLIME                        = -4;
-const int CONTENT_LAVA                 = -5;
-const int CONTENT_SKY                  = -6;
-
-// Quake Solid Constants
-const int SOLID_NOT                            = 0;
-const int SOLID_TRIGGER                        = 1;
-const int SOLID_BBOX                   = 2;
-const int SOLID_SLIDEBOX               = 3;
-const int SOLID_BSP                            = 4;
-const int SOLID_CORPSE                 = 5;
-
-// Quake Move Constants
-const int MOVE_NORMAL                  = 0;
-const int MOVE_NOMONSTERS              = 1;
-const int MOVE_MISSILE                 = 2;
-
-const float EXTRA_LOW                  = -99999999;
-const float EXTRA_HIGH                 = 99999999;
-
-const vector VEC_1                             = '1 1 1';
-const vector VEC_0                             = '0 0 0';
-const vector VEC_M1                            = '-1 -1 -1';
-
-//const float M_PI                             = 3.14159265358979323846;
-
-vector VEC_HULL_MIN                            = '-16 -16 -24';
-vector VEC_HULL_MAX                            = '16 16 32';
-
-// Quake Temporary Entity Constants
-const int TE_SPIKE                             = 0;
-const int TE_SUPERSPIKE                        = 1;
-const int TE_GUNSHOT                   = 2;
-const int TE_EXPLOSION                 = 3;
-const int TE_TAREXPLOSION              = 4;
-const int TE_LIGHTNING1                        = 5;
-const int TE_LIGHTNING2                        = 6;
-const int TE_WIZSPIKE                  = 7;
-const int TE_KNIGHTSPIKE               = 8;
-const int TE_LIGHTNING3                        = 9;
-const int TE_LAVASPLASH                        = 10;
-const int TE_TELEPORT                  = 11;
-const int TE_EXPLOSION2                        = 12;
-
-// Darkplaces Additions
-const int TE_EXPLOSIONRGB              = 53;
-const int TE_GUNSHOTQUAD               = 57;
-const int TE_EXPLOSIONQUAD             = 70;
-const int TE_SPIKEQUAD                 = 58;
-const int TE_SUPERSPIKEQUAD            = 59;
-
-// PFlags for Dynamic Lights
-const int PFLAGS_NOSHADOW              = 1;
-const int PFLAGS_CORONA                        = 2;
-const int PFLAGS_FULLDYNAMIC   = 128;
-
-const int EF_ADDITIVE                  = 32;
-const int EF_BLUE                              = 64;
-const int EF_FLAME                             = 1024;
-const int EF_FULLBRIGHT                        = 512;
-const int EF_NODEPTHTEST               = 8192;
-const int EF_NODRAW                            = 16;
-const int EF_NOSHADOW                  = 4096;
-const int EF_RED                               = 128;
-const int EF_STARDUST                  = 2048;
-const int EF_SELECTABLE                = 16384;
-
-const int PFL_ONGROUND                 = 1;
-const int PFL_CROUCH                   = 2;
-const int PFL_DEAD                             = 4;
-const int PFL_GIBBED                   = 8;
-
-// draw flags
-const int DRAWFLAG_NORMAL              = 0;
-const int DRAWFLAG_ADDITIVE    = 1;
-const int DRAWFLAG_MODULATE    = 2;
-const int DRAWFLAG_2XMODULATE  = 3;
-const int DRAWFLAG_SCREEN              = 4;
-const int DRAWFLAG_MIPMAP              = 0x100; // only for R_BeginPolygon
-
-/*
-==============================================================================
-
-                       BUILTIN DEFINITIONS
-                       EXTENSIONS ARE NOT ADDED HERE, BUT BELOW!
-
-==============================================================================
-*/
-
-void(vector ang) makevectors = #1;
-void(entity e, vector o) setorigin = #2;
-void(entity e, string m) setmodel = #3;
-void(entity e, vector min, vector max) setsize = #4;
-
-void() break_to_debugger = #6;
-float() random = #7;
-void(entity e, float chan, string samp) sound = #8;
-vector(vector v) normalize = #9;
-void(string e) error = #10;
-void(string e) objerror = #11;
-float(vector v) vlen = #12;
-float(vector v) vectoyaw = #13;
-entity() spawn = #14;
-void(entity e) remove = #15;
-float(vector v1, vector v2, float tryents, entity ignoreentity) traceline = #16;
-
-entity(entity start, .string fld, string match) find = #18;
-void(string s) precache_sound = #19;
-void(string s) precache_model = #20;
-
-entity(vector org, float rad) findradius = #22;
-
-void(string s, ...) dprint = #25;
-string(float f) ftos = #26;
-string(vector v) vtos = #27;
-void() coredump = #28;
-void() traceon = #29;
-void() traceoff = #30;
-void(entity e) eprint = #31;
-// settrace optional
-float(float yaw, float dist, float settrace) walkmove = #32;
-
-float() droptofloor = #34;
-void(float style, string value) lightstyle = #35;
-int(float v) rint      = #36;
-int(float v) floor     = #37;
-int(float v) ceil      = #38;
-
-float(entity e) checkbottom = #40;
-float(vector v) pointcontents = #41;
-
-float(float f) fabs = #43;
-
-float(string s) cvar = #45;
-void(string s, ...) localcmd = #46;
-entity(entity e) nextent = #47;
-void(vector o, vector d, float color, float count) particle = #48;
-void() ChangeYaw = #49;
-
-vector(vector v) vectoangles = #51;
-vector(vector v, vector w) vectoangles2 = #51;
-
-float(float f) sin = #60;
-float(float f) cos = #61;
-float(float f) sqrt = #62;
-void(entity ent) changepitch = #63;
-void(entity e, entity ignore) tracetoss = #64;
-string(entity ent) etos = #65;
-
-string(string s) precache_file = #68;
-void(entity e) makestatic = #69;
-
-void(string name, string value) cvar_set = #72;
-
-void(vector pos, string samp, float vol, float atten) ambientsound = #74;
-string(string s) precache_model2 = #75;
-string(string s) precache_sound2 = #76;
-string(string s) precache_file2 = #77;
-
-float(string s) stof = #81;
-
-
-void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox = #90;
-vector() randomvec = #91;
-vector(vector org) getlight = #92;
-vector(vector org, float lpflags) getlight2 = #92;
-vector getlight_dir;
-vector getlight_ambient;
-vector getlight_diffuse;
-const float LP_LIGHTMAP        = 1;
-const float LP_RTWORLD = 2;
-const float LP_DYNLIGHT = 4;
-const float LP_COMPLETE = 7;
-
-float(string name, string value) registercvar = #93;
-float( float a, ... ) min = #94;
-float( float b, ... ) max = #95;
-float(float minimum, float val, float maximum) bound = #96;
-float(float f, float f) pow = #97;
-entity(entity start, .float fld, float match) findfloat = #98;
-float(string s) checkextension = #99;
-// FrikaC and Telejano range #100-#199
-
-int(string filename, int mode) fopen = #110;
-void(float fhandle) fclose = #111;
-string(float fhandle) fgets = #112;
-void(float fhandle, string s) fputs = #113;
-float(string s) strlen = #114;
-string(...) strcat = #115;
-string(string s, float start, float length) substring = #116;
-vector(string) stov = #117;
-string(string s) strzone = #118;
-void(string s) strunzone = #119;
-
-// FTEQW range #200-#299
-
-float(float number, float quantity) bitshift = #218;
-
-//float(string str, string sub[, float startpos]) strstrofs = #221;
-int(string str, string sub, float startpos) strstrofs = #221;
-int(string str, float ofs) str2chr = #222;
-string(int c, ...) chr2str = #223;
-string(float ccase, float calpha, float cnum, string s, ...) strconv = #224;
-string(float chars, string s, ...) strpad = #225;
-string(string info, string key, string value, ...) infoadd = #226;
-string(string info, string key) infoget = #227;
-int(string s1, string s2) strcmp = #228;
-int(string s1, string s2, float len) strncmp = #228;
-int(string s1, string s2) strcasecmp = #229;
-int(string s1, string s2, float len) strncasecmp = #230;
-
-// CSQC range #300-#399
-void() clearscene = #300;
-void(float mask) addentities = #301;
-void(entity ent) addentity = #302;
-float(float property, ...) setproperty = #303;
-float(float property) getproperty = #309;
-vector(float property) getpropertyvec = #309;
-void() renderscene = #304;
-void(vector org, float radius, vector lightcolours) adddynamiclight = #305;
-void(vector org, float radius, vector lightcolours, float style, string cubemapname, float pflags) adddynamiclight2 = #305;
-//void(string texturename, float flag[, float is2d, float lines]) R_BeginPolygon = #306;
-void(string texturename, float flag, ...) R_BeginPolygon = #306;
-void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex = #307;
-void() R_EndPolygon = #308;
-vector (vector v) cs_unproject = #310;
-vector (vector v) cs_project = #311;
-
-void(float width, vector pos1, vector pos2, float flag) drawline = #315;
-float(string name) iscachedpic = #316;
-string(string name, ...) precache_pic = #317;
-string(string name) precache_cubemap = #317;
-vector(string picname) draw_getimagesize = #318;
-void(string name) freepic = #319;
-float(vector position, float character, vector scale, vector rgb, float alpha, float flag) drawcharacter = #320;
-float(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawstring = #321;
-float(vector position, string pic, vector size, vector rgb, float alpha, float flag) drawpic = #322;
-float(vector position, vector size, vector rgb, float alpha, float flag) drawfill = #323;
-void(float x, float y, float width, float height) drawsetcliparea = #324;
-void(void) drawresetcliparea = #325;
-float(vector position, string text, vector scale, float alpha, float flag) drawcolorcodedstring = #326;
-vector(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawcolorcodedstring2 = #326;
-
-float(int stnum) getstatf = #330;
-int(int stnum, ...) getstati = #331; // can optionally take first bit and count
-string(float firststnum) getstats = #332;
-void(entity e, float mdlindex) setmodelindex = #333;
-string(float mdlindex) modelnameforindex = #334;
-int(string effectname) particleeffectnum = #335;
-void(entity ent, float effectnum, vector start, vector end) trailparticles = #336;
-//void(float effectnum, vector origin [, vector dir, float count]) pointparticles = #337;
-void(float effectnum, vector origin , vector dir, float count) pointparticles = #337;
-void(string s, ...) centerprint = #338;
-void(string s, ...) print = #339;
-string(float keynum) keynumtostring = #340;
-float(string keyname) stringtokeynum = #341;
-string(float keynum) getkeybind = #342;
-void(float usecursor) setcursormode = #343;
-vector() getmousepos = #344;
-float(float framenum) getinputstate = #345;
-void(float sens) setsensitivityscale = #346;
-void(...) runstandardplayerphysics = #347; // this may or may not take a player ent
-string(float playernum, string keyname) getplayerkeyvalue = #348;
-float() isdemo = #349;
-float() isserver = #350;
-void(vector origin, vector forward, vector right, vector up) SetListener = #351;
-void(string cmdname) registercommand = #352;
-float(entity ent) wasfreed = #353;
-string(string key) serverkey = #354;
-
-// Use proper case; refer to the id1 Write* functions!
-int() ReadByte         = #360;
-int() ReadChar         = #361;
-int() ReadShort                = #362;
-int() ReadLong         = #363;
-float() ReadCoord      = #364;
-float() ReadAngle      = #365;
-string() ReadString    = #366;
-float() ReadFloat      = #367;
-
-// LordHavoc's range #400-#499
-void(entity from, entity to) copyentity = #400;
-
-entity(.string fld, string match) findchain = #402;
-entity(.float fld, float match) findchainfloat = #403;
-void(vector org, string modelname, float startframe, float endframe, float framerate) effect = #404;
-void(vector org, vector velocity, float howmany) te_blood = #405;
-void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower = #406;
-void(vector org, vector color) te_explosionrgb = #407;
-void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube = #408;
-void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain = #409;
-void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow = #410;
-void(vector org, vector vel, float howmany) te_spark = #411;
-void(vector org) te_gunshotquad = #412;
-void(vector org) te_spikequad = #413;
-void(vector org) te_superspikequad = #414;
-void(vector org) te_explosionquad = #415;
-void(vector org) te_smallflash = #416;
-void(vector org, float radius, float lifetime, vector color) te_customflash = #417;
-void(vector org) te_gunshot = #418;
-void(vector org) te_spike = #419;
-void(vector org) te_superspike = #420;
-void(vector org) te_explosion = #421;
-void(vector org) te_tarexplosion = #422;
-void(vector org) te_wizspike = #423;
-void(vector org) te_knightspike = #424;
-void(vector org) te_lavasplash = #425;
-void(vector org) te_teleport = #426;
-void(vector org, float colorstart, float colorlength) te_explosion2 = #427;
-void(entity own, vector start, vector end) te_lightning1 = #428;
-void(entity own, vector start, vector end) te_lightning2 = #429;
-void(entity own, vector start, vector end) te_lightning3 = #430;
-void(entity own, vector start, vector end) te_beam = #431;
-void(vector dir) vectorvectors = #432;
-void(vector org) te_plasmaburn = #433;
-//float(entity e, float s) getsurfacenumpoints = #434;
-//vector(entity e, float s, float n) getsurfacepoint = #435;
-//vector(entity e, float s) getsurfacenormal = #436;
-//string(entity e, float s) getsurfacetexture = #437;
-//float(entity e, vector p) getsurfacenearpoint = #438;
-//vector(entity e, float s, vector p) getsurfaceclippedpoint = #439;
-
-int(string s) tokenize = #441;
-string(float n) argv = #442;
-void(entity e, entity tagentity, string tagname) setattachment = #443;
-float(string pattern, float caseinsensitive, float quiet) search_begin = #444;
-void(float handle) search_end = #445;
-float(float handle) search_getsize = #446;
-string(float handle, float num) search_getfilename = #447;
-string(string s) cvar_string = #448;
-entity(entity start, .float fld, float match) findflags = #449;
-entity(.float fld, float match) findchainflags = #450;
-int(entity ent, string tagname) gettagindex = #451;
-vector(entity ent, float tagindex) gettaginfo = #452;
-
-void(vector org, vector vel, float howmany) te_flamejet = #457;
-
-entity(float num) entitybyindex = #459;
-int() buf_create = #460;
-void(float bufhandle) buf_del = #461;
-float(float bufhandle) buf_getsize = #462;
-void(float bufhandle_from, float bufhandle_to) buf_copy = #463;
-void(float bufhandle, float sortpower, float backward) buf_sort = #464;
-string(float bufhandle, string glue) buf_implode = #465;
-string(float bufhandle, float string_index) bufstr_get = #466;
-void(float bufhandle, float string_index, string str) bufstr_set = #467;
-float(float bufhandle, string str, float order) bufstr_add = #468;
-void(float bufhandle, float string_index) bufstr_free = #469;
-
-//float(float s) asin = #471;
-//float(float c) acos = #472;
-//float(float t) atan = #473;
-//float(float c, float s) atan2 = #474;
-//float(float a) tan = #475;
-float(string s) strippedstringlen = #476;
-float(string s) strlennocol = #476; // This is the correct name for the function, but not removing the decolorizedstring mapping.
-string(string s) decolorizedstring = #477;
-string(string s) strdecolorize = #477; // This is the correct name for the function, but not removing the decolorizedstring mapping.
-string(float uselocaltime, string format, ...) strftime = #478;
-string(string s) strtolower = #480;
-string(string s) strtoupper = #481;
-string(string s) cvar_defstring = #482;
-void(vector origin, string sample, float volume, float attenuation) pointsound = #483;
-string(string search, string replace, string subject) strreplace = #484;
-string(string search, string replace, string subject) strireplace = #485;
-//vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
-#ifdef SUPPORT_GECKO
-float gecko_create( string name ) = #487;
-void gecko_destroy( string name ) = #488;
-void gecko_navigate( string name, string URI ) = #489;
-float gecko_keyevent( string name, float key, float eventtype ) = #490;
-void gecko_mousemove( string name, float x, float y ) = #491;
-void gecko_resize( string name, float w, float h ) = #492;
-vector gecko_get_texture_extent( string name ) = #493;
-#else
-
-#endif
-
-/*
-==============================================================================
-
-                       EXTENSION DEFINITIONS
-
-==============================================================================
-*/
-
-// DP_CSQC_SPAWNPARTICLE
-// idea: VorteX
-// darkplaces implementation: VorteX
-// constant definitions:
-// particle base behavior:
-float PT_ALPHASTATIC = 1;
-float PT_STATIC = 2;
-float PT_SPARK = 3;
-float PT_BEAM = 4;
-float PT_RAIN = 5;
-float PT_RAINDECAL = 6;
-float PT_SNOW = 7;
-float PT_BUBBLE = 8;
-float PT_BLOOD = 9;
-float PT_SMOKE = 10;
-float PT_DECAL = 11;
-float PT_ENTITYPARTICLE = 12;
-// particle blendtypes:
-float PBLEND_ALPHA = 0;
-float PBLEND_ADD = 1;
-float PBLEND_INVMOD = 2;
-// particle orientation:
-float PARTICLE_BILLBOARD = 0;
-float PARTICLE_SPARK = 1;
-float PARTICLE_ORIENTED_DOUBLESIDED = 2;
-float PARTICLE_BEAM = 3;
-// global definitions:
-float particle_type; // one of PT_
-float particle_blendmode; // one of PBLEND_ values
-float particle_orientation; // one of PARTICLE_ values
-vector particle_color1;
-vector particle_color2;
-float particle_tex; // number of chunk in particlefont
-float particle_size;
-float particle_sizeincrease;
-float particle_alpha;
-float particle_alphafade;
-float particle_time;
-float particle_gravity;
-float particle_bounce;
-float particle_airfriction;
-float particle_liquidfriction;
-float particle_originjitter;
-float particle_velocityjitter;
-float particle_qualityreduction; // enable culling of this particle when FPS is low
-float particle_stretch;
-vector particle_staincolor1;
-vector particle_staincolor2;
-float particle_staintex;
-float particle_stainalpha;
-float particle_stainsize;
-float particle_delayspawn;
-float particle_delaycollision;
-float particle_angle;
-float particle_spin;
-// builtin definitions:
-float(float max_themes) initparticlespawner = #522; // check fields/globals for integration and enable particle spawner, return 1 is succeded, otherwise returns 0
-void() resetparticle = #523; // reset p_ globals to default theme #0
-void(float theme) particletheme = #524; // restore p_ globals from saved theme
-float() particlethemesave = #525; // save p_ globals to new particletheme and return it's index
-void(float theme) particlethemeupdate = #525; // save p_ globals to new particletheme and return it's index
-void(float theme) particlethemefree = #526; // delete a particle theme
-float(vector org, vector vel) spawnparticle = #527; // returns 0 when failed, 1 when spawned
-float(vector org, vector vel, float theme) quickparticle = #527; // not reading globals, just theme, returns 0 when failed, 1 when spawned
-float(vector org, vector vel, float delay, float collisiondelay) delayedparticle = #528;
-float(vector org, vector vel, float delay, float collisiondelay, float theme) quickdelayedparticle = #528;
-// description: this builtin provides an easy and flexible way to spawn particles,
-// it is not created as replace for DP_SV_POINTPARTICLES but as an addition to it.
-// With this extension you can create a specific particles like rain particles, or entity particles
-// notes:
-// 1) 0 is default particle template, it could be changed
-// 2) color vectors could have value 0-255 of each component
-// restrictions: max themes could be between 4 and 2048
-// warning: you should call initparticlespawner() at very beginning BEFORE all other particle spawner functions
-// function to query particle info
-// don't remove this function as it protects all particle_ globals from FTEQCC/FRIKQCC non-referenced removal optimisation
-void() printparticle =
-{
-       // vortex: this also protects from 'non-referenced' optimisation on some compilers
-       print("PARTICLE:\n");
-       print(strcat("  type: ", ftos(particle_type), "\n"));
-       print(strcat("  blendmode: ", ftos(particle_blendmode), "\n"));
-       print(strcat("  orientation: ", ftos(particle_orientation), "\n"));
-       print(strcat("  color1: ", vtos(particle_color1), "\n"));
-       print(strcat("  color2: ", vtos(particle_color2), "\n"));
-       print(strcat("  tex: ", ftos(particle_tex), "\n"));
-       print(strcat("  size: ", ftos(particle_size), "\n"));
-       print(strcat("  sizeincrease: ", ftos(particle_sizeincrease), "\n"));
-       print(strcat("  alpha: ", ftos(particle_alpha), "\n"));
-       print(strcat("  alphafade: ", ftos(particle_alphafade), "\n"));
-       print(strcat("  time: ", ftos(particle_time), "\n"));
-       print(strcat("  gravity: ", ftos(particle_gravity), "\n"));
-       print(strcat("  bounce: ", ftos(particle_bounce), "\n"));
-       print(strcat("  airfriction: ", ftos(particle_airfriction), "\n"));
-       print(strcat("  liquidfriction: ", ftos(particle_liquidfriction), "\n"));
-       print(strcat("  originjitter: ", ftos(particle_originjitter), "\n"));
-       print(strcat("  velocityjitter: ", ftos(particle_velocityjitter), "\n"));
-       print(strcat("  qualityreduction: ", ftos(particle_qualityreduction), "\n"));
-       print(strcat("  stretch: ", ftos(particle_stretch), "\n"));
-       print(strcat("  staincolor1: ", vtos(particle_staincolor1), "\n"));
-       print(strcat("  staincolor2: ", vtos(particle_staincolor2), "\n"));
-       print(strcat("  staintex: ", ftos(particle_staintex), "\n"));
-       print(strcat("  stainalpha: ", ftos(particle_stainalpha), "\n"));
-       print(strcat("  stainsize: ", ftos(particle_stainsize), "\n"));
-       print(strcat("  delayspawn: ", ftos(particle_delayspawn), "\n"));
-       print(strcat("  delaycollision: ", ftos(particle_delaycollision), "\n"));
-       print(strcat("  angle: ", ftos(particle_angle), "\n"));
-       print(strcat("  spin: ", ftos(particle_spin), "\n"));
-}
-
-// DP_CSQC_ENTITYTRANSPARENTSORTING_OFFSET
-// idea: VorteX
-// darkplaces implementation: VorteX
-float RF_USETRANSPARENTOFFSET = 64; // enables transparent origin offsetting
-// global definitions
-float transparent_offset; // should be set before entity is added
-// description: offset a model's meshes origin used for transparent sorting. Could be used to tweak sorting bugs on very large transparent entities or hacking transparent sorting order for certain objects
-// example: transparent_offset = 1000000; // entity always appear on background of other transparents
-// note: offset is done in view forward axis
-
-// DP_CSQC_ENTITYWORLDOBJECT
-// idea: VorteX
-// darkplaces implementation: VorteX
-const float RF_WORLDOBJECT = 128;
-// description: when renderflag is set, engine will not use culling methods for this entity, e.g. it will always be drawn
-// useful for large outdoor objects (like asteroids on sky horizon or sky models)
-
-// DP_CSQC_ENTITYMODELLIGHT
-// idea: VorteX
-// darkplaces implementation: VorteX
-const float RF_MODELLIGHT = 4096;
-.vector modellight_ambient;
-.vector modellight_diffuse;
-.vector modellight_dir;
-// description: allows CSQC to override directional model lightning on entity
-
-// DP_CSQC_SETPAUSE
-// idea: VorteX
-// darkplaces implementation: VorteX
-// builtin definitions:
-void(float ispaused) setpause = #531;
-// description: provides ability to set pause in local games (similar to one set once console is activated)
-// not stopping sound/cd track, useful for inventory screens, ingame menus with input etc.
-
-// DP_CSQC_QUERYRENDERENTITY
-// idea: VorteX
-// darkplaces implementation: VorteX
-// constant definitions:
-// render entity fields:
-float E_ACTIVE             = 0; // float 0/1
-float E_ORIGIN      = 1; // vector
-float E_FORWARD     = 2; // vector
-float E_RIGHT       = 3; // vector
-float E_UP          = 4; // vector
-float E_SCALE       = 5; // float
-float E_ORIGINANDVECTORS = 6; // returns origin, + sets v_* vectors to orientation
-float E_ALPHA       = 7; // float
-float E_COLORMOD    = 8; // vector
-float E_PANTSCOLOR  = 9; // vector
-float E_SHIRTCOLOR  = 10; // vector
-float E_SKIN        = 11; // float
-float E_MINS        = 12; // vector
-float E_MAXS        = 13; // vector
-float E_ABSMIN      = 14; // vector
-float E_ABSMAX      = 15; // vector
-float E_LIGHT       = 16; // vector - modellight
-// builtin definitions:
-float(float entitynum, float fldnum) getentity = #504;
-vector(float entitynum, float fldnum) getentityvec = #504;
-// description: allows to query parms from render entities, especially useful with attaching CSQC ents to
-// server entities networked and interpolated by engine (monsters, players), number of entity is it's SVQC number
-// you can send it via tempentity/CSQC entity message. Note that this builtin doesnt know about entity removing/reallocating
-// so it's meaning to work for short period of time, dont use it on missiles/grenades whatever will be removed next five seconds
-
-//DP_GFX_FONTS
-//idea: Blub\0, divVerent
-//darkplaces implementation: Blub\0
-//console commands:
-//  loadfont fontname fontmaps size1 size2 ...
-//   A font can simply be gfx/tgafile (freetype fonts doent need extension),
-//   or alternatively you can specify multiple fonts and faces
-//   Like this: gfx/vera-sans:2,gfx/fallback:1
-//   to load face 2 of the font gfx/vera-sans and use face 1
-//   of gfx/fallback as fallback font
-//   You can also specify a list of font sizes to load, like this:
-//   loadfont console gfx/conchars,gfx/fallback 8 12 16 24 32
-//   In many cases, 8 12 16 24 32 should be a good choice.
-//   for slots see:
-//constant definitions:
-float drawfont;            // set it before drawstring()/drawchar() calls
-float FONT_DEFAULT = 0;    // 'default'
-float FONT_CONSOLE = 1;    // 'console', REALLY should be fixed width (ls!)
-float FONT_SBAR = 2;       // 'sbar', used on hud, must be fixed width
-float FONT_NOTIFY = 3;     // 'notify', used on sprint/bprint
-float FONT_CHAT = 4;       // 'chat'
-float FONT_CENTERPRINT = 5;// 'centerprint'
-float FONT_INFOBAR = 6;    // 'infobar'
-float FONT_MENU = 7;       // 'menu', should be fixed width
-float FONT_USER0 = 8;      // 'user0', userdefined fonts
-float FONT_USER1 = 9;      // 'user1', userdefined fonts
-float FONT_USER2 = 10;     // 'user2', userdefined fonts
-float FONT_USER3 = 11;     // 'user3', userdefined fonts
-float FONT_USER4 = 12;     // 'user4', userdefined fonts
-float FONT_USER5 = 13;     // 'user5', userdefined fonts
-float FONT_USER6 = 14;     // 'user6', userdefined fonts
-float FONT_USER7 = 15;     // 'user7' slot, userdefined fonts
-//builtin definitions:
-float findfont(string s) = #356; // find font by fontname and return it's index
-float loadfont(string fontname, string fontmaps, string sizes, float slot, float fix_scale, float fix_voffset) = #357;
-// loads font immediately so stringwidth() function can be used just after builtin call
-// returns a font slotnum (which is used to set drawfont to)
-// first 3 parms are identical to "loadfont" console command ones
-// slot could be one of FONT_ constants or result of findfont() or -1 to not use it
-// if slot is given, font will be loaded to this slotnum and fontname become new title for it
-// this way you can rename user* fonts to something more usable
-// fix_* parms let you fix badly made fonts by applying some transformations to them
-// fix_scale : per-character center-oriented scale (doesn't change line height at all)
-// fix_voffset : vertical offset for each character, it's a multiplier to character height
-float stringwidth(string text, float allowColorCodes, vector size) = #327; // get a width of string with given font and char size
-float stringwidth_menu(string text, float allowColorCodes, vector size) = #468; // in menu.dat it has different builtin #
-//description: engine support for custom fonts in console, hud, qc etc.
-// limits:
-//  max 128 chars for font name
-//  max 3 font fallbacks
-//  max 8 sizes per font
-
-//DP_GFX_FONTS_FREETYPE
-//idea: Blub\0, divVerent
-//darkplaces implementation: Blub\0
-//cvar definitions:
-//   r_font_disable_freetype 0/1 : disable freetype fonts loading (uttetly disables freetype library initialization)
-//   r_font_antialias 0/1 : antialiasing when loading font
-//   r_font_hint 0/1/2/3  : hinting when loading font, 0 is no hinting, 1 light autohinting , 2 full autohinting, 3 full hinting
-//   r_font_postprocess_blur X      : font outline blur amount
-//   r_font_postprocess_outline X   : font outline width
-//   r_font_postprocess_shadow_x X  : font outline shadow x shift amount, applied during outlining
-//   r_font_postprocess_shadow_y X  : font outline shadow y shift amount, applied during outlining
-//   r_font_postprocess_shadow_z X  : font outline shadow z shift amount, applied during blurring
-//description: engine support for truetype/freetype fonts
-//so .AFM+.PFB/.OTF/.TTF files could be stuffed as fontmaps in loadfont()
-//(console command version will support them as well)
-
-//DP_CSQC_BINDMAPS
-//idea: daemon, motorsep
-//darkplaces implementation: divVerent
-//builtin definitions:
-string(float key, float bindmap) getkeybind_bindmap = #342;
-float(float key, string bind, float bindmap) setkeybind_bindmap = #630;
-vector(void) getbindmaps = #631;
-float(vector bm) setbindmaps = #632;
-string(string command, float bindmap) findkeysforcommand = #610;
-//<already in EXT_CSQC> float(string key) stringtokeynum = #341;
-//<already in EXT_CSQC> string(float keynum) keynumtostring = #340;
-//description: key bind setting/getting including support for switchable
-//bindmaps.
-
-//DP_CRYPTO
-//idea: divVerent
-//darkplaces implementation: divVerent
-//builtin definitions: (CSQC)
-float(string url, float id, string content_type, string delim, float buf, float keyid) crypto_uri_postbuf = #513;
-//description:
-//use -1 as buffer handle to justs end delim as postdata
-
-//DP_CSQC_MAINVIEW
-//idea: divVerent
-//darkplaces implementation: divVerent
-//constant definitions:
-const int VF_MAINVIEW         = 400;
-//use setproperty(VF_MAINVIEW, 1); before calling R_RenderView for the render
-//that shall become the "main" view, which is e.g. used by PRYDON_CLIENTCURSOR
-//this flag is set for the first scene, and not cleared by R_ClearScene
-//this flag is automatically cleared by R_RenderView
-//so when not using this extension, the first view rendered is the main view
-
-//DP_CSQC_MINFPS_QUALITY
-//idea: divVerent
-//darkplaces implementation: divVerent
-//constant definitions:
-const int VF_MINFPS_QUALITY   = 401;
-//use getproperty(VF_MINFPS_QUALITY); to do CSQC based LOD based on cl_minfps
-//1 should lead to an unmodified view
-
-//DP_CSQC_V_CALCREFDEF_WIP1
-//DP_CSQC_V_CALCREFDEF_WIP2
-//idea: divVerent
-//darkplaces implementation: divVerent
-//builtin definitions:
-void(entity e, float refdefflags) V_CalcRefdef = #640;
-//constant definitions:
-const int PMF_DUCKED = 4;
-const int PMF_ONGROUND = 8;
-const int REFDEFFLAG_TELEPORTED = 1;
-const int REFDEFFLAG_JUMPING = 2;
-const int REFDEFFLAG_DEAD = 4;
-const int REFDEFFLAG_INTERMISSION = 8;
-//- use this on the player entity after performing prediction
-//- pass REFDEFFLAG_TELEPORTED if the player teleported since last frame
-//- pass REFDEFFLAG_JUMPING if jump button is pressed
-//- pass REFDEFFLAG_DEAD if dead (DP_CSQC_V_CALCREFDEF_WIP2)
-//- pass REFDEFFLAG_INTERMISSION if in intermission (DP_CSQC_V_CALCREFDEF_WIP2)
-//- the player entity needs to have origin, velocity, pmove_flags set according
-//  to prediction (the above two PMF_ flags are used in the player's pmove_flags)
-//- NOTE: to check for this, ALSO OR a check with DP_CSQC_V_CALCREFDEF to also support
-//  the finished extension once done
-
-// assorted builtins
-float  drawsubpic(vector position, vector size, string pic, vector srcPosition, vector srcSize, vector rgb, float alpha, float flag) = #328;
-vector drawgetimagesize(string pic) = #318;
-const float SPA_POSITION =  0;
-const float SPA_S_AXIS =  1;
-const float SPA_T_AXIS =  2;
-const float SPA_R_AXIS =  3;
-const float SPA_TEXCOORDS0 =  4;
-const float SPA_LIGHTMAP0_TEXCOORDS =  5;
-const float SPA_LIGHTMAP_COLOR =  6;
-float (entity e, float s)                                              getsurfacenumpoints = #434;
-vector (entity e, float s, float n)                                    getsurfacepoint = #435;
-vector (entity e, float s)                                             getsurfacenormal = #436;
-string (entity e, float s)                                             getsurfacetexture = #437;
-float (entity e, vector p)                                             getsurfacenearpoint = #438;
-vector (entity e, float s, vector p)                                   getsurfaceclippedpoint = #439;
-vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
-float(entity e, float s) getsurfacenumtriangles = #628;
-vector(entity e, float s, float n) getsurfacetriangle = #629;
-
-//DP_QC_ASINACOSATANATAN2TAN
-//idea: Urre
-//darkplaces implementation: LordHavoc
-//constant definitions:
-float DEG2RAD = 0.0174532925199432957692369076848861271344287188854172545609719144;
-float RAD2DEG = 57.2957795130823208767981548141051703324054724665643215491602438612;
-float PI      = 3.1415926535897932384626433832795028841971693993751058209749445923;
-//builtin definitions:
-float(float s) asin = #471; // returns angle in radians for a given sin() value, the result is in the range -PI*0.5 to PI*0.5
-float(float c) acos = #472; // returns angle in radians for a given cos() value, the result is in the range 0 to PI
-float(float t) atan = #473; // returns angle in radians for a given tan() value, the result is in the range -PI*0.5 to PI*0.5
-float(float c, float s) atan2 = #474; // returns angle in radians for a given cos() and sin() value pair, the result is in the range -PI to PI (this is identical to vectoyaw except it returns radians rather than degrees)
-float(float a) tan = #475; // returns tangent value (which is simply sin(a)/cos(a)) for the given angle in radians, the result is in the range -infinity to +infinity
-//description:
-//useful math functions for analyzing vectors, note that these all use angles in radians (just like the cos/sin functions) not degrees unlike makevectors/vectoyaw/vectoangles, so be sure to do the appropriate conversions (multiply by DEG2RAD or RAD2DEG as needed).
-//note: atan2 can take unnormalized vectors (just like vectoyaw), and the function was included only for completeness (more often you want vectoyaw or vectoangles), atan2(v_x,v_y) * RAD2DEG gives the same result as vectoyaw(v)
-
-//DP_QC_SPRINTF
-//idea: divVerent
-//darkplaces implementation: divVerent
-//builtin definitions:
-string(string format, ...) sprintf = #627;
-//description:
-//you know sprintf :P
-//supported stuff:
-//  %
-//  optional: <argpos>$ for the argument to format
-//  flags: #0- +
-//  optional: <width>, *, or *<argpos>$ for the field width
-//  optional: .<precision>, .*, or .*<argpos>$ for the precision
-//  length modifiers: h for forcing a float, l for forcing an int/entity (by default, %d etc. cast a float to int)
-//  conversions:
-//    d takes a float if no length is specified or h is, and an int/entity if l is specified as length, and cast it to an int
-//    i takes an int/entity if no length is specified or i is, and a float if h is specified as length, and cast it to an int
-//    ouxXc take a float if no length is specified or h is, and an int/entity if l is specified as length, and cast it to an unsigned int
-//    eEfFgG take a float if no length is specified or h is, and an int/entity if l is specified as length, and cast it to a double
-//    s takes a string
-//    vV takes a vector, and processes the three components as if it were a gG for all three components, separated by space
-//    For conversions s and c, the flag # makes precision and width interpreted
-//      as byte count, by default it is interpreted as character count in UTF-8
-//      enabled engines. No other conversions can create wide characters, and #
-//      has another meaning in these.
-
-//DP_QC_GETTIME
-//idea: tZork
-//darkplaces implementation: tZork, divVerent
-//constant definitions:
-float GETTIME_FRAMESTART = 0; // time of start of frame
-float GETTIME_REALTIME = 1; // current time (may be OS specific)
-float GETTIME_HIRES = 2; // like REALTIME, but may reset between QC invocations and thus can be higher precision
-float GETTIME_UPTIME = 3; // time since start of the engine
-//builtin definitions:
-float(float tmr) gettime = #519;
-//description:
-//some timers to query...
-
-//DP_QC_GETTIME_CDTRACK
-//idea: divVerent
-//darkplaces implementation: divVerent
-//constant definitions:
-float GETTIME_CDTRACK = 4;
-//description:
-//returns the playing time of the current cdtrack when passed to gettime()
-//see DP_END_GETSOUNDTIME for similar functionality but for entity sound channels
-
-//DP_QC_TOKENIZEBYSEPARATOR
-//idea: Electro, SavageX, LordHavoc
-//darkplaces implementation: LordHavoc
-//builtin definitions:
-int(string s, string separator1, ...) tokenizebyseparator = #479;
-//description:
-//this function returns tokens separated by any of the supplied separator strings, example:
-//numnumbers = tokenizebyseparator("10.2.3.4", ".");
-//returns 4 and the tokens are "10" "2" "3" "4"
-//possibly useful for parsing IPv4 addresses (such as "1.2.3.4") and IPv6 addresses (such as "[1234:5678:9abc:def0:1234:5678:9abc:def0]:26000")
-
-//DP_QC_TOKENIZE_CONSOLE
-//idea: divVerent
-//darkplaces implementation: divVerent
-//builtin definitions:
-int(string s) tokenize_console = #514;
-int(float i) argv_start_index = #515;
-int(float i) argv_end_index = #516;
-//description:
-//this function returns tokens separated just like the console does
-//also, functions are provided to get the index of the first and last character of each token in the original string
-//Passing negative values to them, or to argv, will be treated as indexes from the LAST token (like lists work in Perl). So argv(-1) will return the LAST token.
-
-//DP_SND_SOUND7_WIP1
-//DP_SND_SOUND7_WIP2
-//idea: divVerent
-//darkplaces implementation: divVerent
-//builtin definitions:
-void(entity e, float chan, string samp, float vol, float atten, float speed, float flags) sound7 = #8;
-float SOUNDFLAG_RELIABLE = 1;
-//description:
-//plays a sound, with some more flags
-//extensions to sound():
-//- channel may be in the range from -128 to 127; channels -128 to 0 are "auto",
-//  i.e. support multiple sounds at once, but cannot be stopped/restarted
-//- a value 0 in the speed parameter means no change; otherwise, it is a
-//  percentage of playback speed ("pitch shifting"). 100 is normal pitch, 50 is
-//  half speed, 200 is double speed, etc. (DP_SND_SOUND7_WIP2)
-//- the flag SOUNDFLAG_RELIABLE can be specified, which makes the sound send
-//  to MSG_ALL (reliable) instead of MSG_BROADCAST (unreliable, default);
-//  similarily, SOUNDFLAG_RELIABLE_TO_ONE sends to MSG_ONE
-//- channel 0 is controlled by snd_channel0volume; channel 1 and -1 by
-//  snd_channel1volume, etc. (so, a channel shares the cvar with its respective
-//  auto-channel); however, the mod MUST define snd_channel8volume and upwards
-//  in default.cfg if they are to be used, as the engine does not create them
-//  to not litter the cvar list
-//- this extension applies to CSQC as well; CSQC_Event_Sound will get speed and
-//  flags as extra 7th and 8th argument
-//- WIP2 ideas: SOUNDFLAG_RELIABLE_TO_ONE, SOUNDFLAG_NOPHS, SOUNDFLAG_FORCELOOP
-//- NOTE: to check for this, ALSO OR a check with DP_SND_SOUND7 to also support
-//  the finished extension once done
-
-//DP_PRECACHE_PIC_FLAGS
-//idea: divVerent
-//darkplaces implementation: divVerent
-//constant definitions:
-float PRECACHE_PIC_FROMWAD = 1; // this one actually is part of EXT_CSQC
-float PRECACHE_PIC_NOTPERSISTENT = 2; // picture may get deallocated when unused
-float PRECACHE_PIC_MIPMAP = 8; // mipmap the texture for possibly better downscaling at memory expense
-//notes: these constants are given as optional second argument to precache_pic()
-
-//DP_QC_TRACE_MOVETYPE_WORLDONLY
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//constant definitions:
-float MOVE_WORLDONLY = 3;
-//description:
-//allows traces to hit only world (ignoring all entities, unlike MOVE_NOMONSTERS which hits all bmodels), use as the nomonsters parameter to trace functions
-
-//DP_SND_GETSOUNDTIME
-//idea: VorteX
-//darkplaces implementation: VorteX
-//constant definitions:
-float(entity e, float channel) getsoundtime = #533; // get currently sound playing position on entity channel, -1 if not playing or error
-float(string sample) soundlength = #534; // returns length of sound sample in seconds, -1 on error (sound not precached, sound system not initialized etc.)
-//description: provides opportunity to query length of sound samples and realtime tracking of sound playing on entities (similar to DP_GETTIME_CDTRACK)
-//note: beware dedicated server not running sound engine at all, so in dedicated mode this builtins will not work in server progs
-//note also: menu progs not supporting getsoundtime() (will give a warning) since it has no sound playing on entities
-//examples of use:
-//  - QC-driven looped sounds
-//  - QC events when sound playing is finished
-//  - toggleable ambientsounds
-//  - subtitles
-
-//DP_QC_NUM_FOR_EDICT
-//idea: Blub\0
-//darkplaces implementation: Blub\0
-//Function to get the number of an entity - a clean way.
-float(entity num) num_for_edict = #512;
-
-//DP_TRACE_HITCONTENTSMASK_SURFACEINFO
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//globals:
-.int dphitcontentsmask; // if non-zero on the entity passed to traceline/tracebox/tracetoss this will override the normal collidable contents rules and instead hit these contents values (for example AI can use tracelines that hit DONOTENTER if it wants to, by simply changing this field on the entity passed to traceline), this affects normal movement as well as trace calls
-float trace_dpstartcontents; // DPCONTENTS_ value at start position of trace
-int trace_dphitcontents; // DPCONTENTS_ value of impacted surface (not contents at impact point, just contents of the surface that was hit)
-int trace_dphitq3surfaceflags; // Q3SURFACEFLAG_ value of impacted surface
-string trace_dphittexturename; // texture name of impacted surface
-//constants:
-const int DPCONTENTS_SOLID = 1; // hit a bmodel, not a bounding box
-const int DPCONTENTS_WATER = 2;
-const int DPCONTENTS_SLIME = 4;
-const int DPCONTENTS_LAVA = 8;
-const int DPCONTENTS_SKY = 16;
-const int DPCONTENTS_BODY = 32; // hit a bounding box, not a bmodel
-const int DPCONTENTS_CORPSE = 64; // hit a SOLID_CORPSE entity
-const int DPCONTENTS_NODROP = 128; // an area where backpacks should not spawn
-const int DPCONTENTS_PLAYERCLIP = 256; // blocks player movement
-const int DPCONTENTS_MONSTERCLIP = 512; // blocks monster movement
-const int DPCONTENTS_DONOTENTER = 1024; // AI hint brush
-const int DPCONTENTS_LIQUIDSMASK = 14; // WATER | SLIME | LAVA
-const int DPCONTENTS_BOTCLIP = 2048; // AI hint brush
-const int DPCONTENTS_OPAQUE = 4096; // only fully opaque brushes get this (may be useful for line of sight checks)
-const int Q3SURFACEFLAG_NODAMAGE = 1;
-const int Q3SURFACEFLAG_SLICK = 2; // low friction surface
-const int Q3SURFACEFLAG_SKY = 4; // sky surface (also has NOIMPACT and NOMARKS set)
-const int Q3SURFACEFLAG_LADDER = 8; // climbable surface
-const int Q3SURFACEFLAG_NOIMPACT = 16; // projectiles should remove themselves on impact (this is set on sky)
-const int Q3SURFACEFLAG_NOMARKS = 32; // projectiles should not leave marks, such as decals (this is set on sky)
-const int Q3SURFACEFLAG_FLESH = 64; // projectiles should do a fleshy effect (blood?) on impact
-const int Q3SURFACEFLAG_NODRAW = 128; // compiler hint (not important to qc)
-//float Q3SURFACEFLAG_HINT = 256; // compiler hint (not important to qc)
-//float Q3SURFACEFLAG_SKIP = 512; // compiler hint (not important to qc)
-//float Q3SURFACEFLAG_NOLIGHTMAP = 1024; // compiler hint (not important to qc)
-//float Q3SURFACEFLAG_POINTLIGHT = 2048; // compiler hint (not important to qc)
-const int Q3SURFACEFLAG_METALSTEPS = 4096; // walking on this surface should make metal step sounds
-const int Q3SURFACEFLAG_NOSTEPS = 8192; // walking on this surface should not make footstep sounds
-const int Q3SURFACEFLAG_NONSOLID = 16384; // compiler hint (not important to qc)
-//float Q3SURFACEFLAG_LIGHTFILTER = 32768; // compiler hint (not important to qc)
-//float Q3SURFACEFLAG_ALPHASHADOW = 65536; // compiler hint (not important to qc)
-//float Q3SURFACEFLAG_NODLIGHT = 131072; // compiler hint (not important to qc)
-//float Q3SURFACEFLAG_DUST = 262144; // translucent 'light beam' effect (not important to qc)
-//description:
-//adds additional information after a traceline/tracebox/tracetoss call.
-//also (very important) sets trace_* globals before calling .touch functions,
-//this allows them to inspect the nature of the collision (for example
-//determining if a projectile hit sky), clears trace_* variables for the other
-//object in a touch event (that is to say, a projectile moving will see the
-//trace results in its .touch function, but the player it hit will see very
-//little information in the trace_ variables as it was not moving at the time)
-
-//DP_QC_CVAR_TYPE
-//idea: divVerent
-//DarkPlaces implementation: divVerent
-//builtin definitions:
-float(string name) cvar_type = #495;
-const int CVAR_TYPEFLAG_EXISTS = 1;
-const int CVAR_TYPEFLAG_SAVED = 2;
-const int CVAR_TYPEFLAG_PRIVATE = 4;
-const int CVAR_TYPEFLAG_ENGINE = 8;
-const int CVAR_TYPEFLAG_HASDESCRIPTION = 16;
-const int CVAR_TYPEFLAG_READONLY = 32;
-
-//DP_QC_CRC16
-//idea: divVerent
-//darkplaces implementation: divVerent
-//Some hash function to build hash tables with. This has to be be the CRC-16-CCITT that is also required for the QuakeWorld download protocol.
-//When caseinsensitive is set, the CRC is calculated of the lower cased string.
-int(bool caseinsensitive, string s, ...) crc16 = #494;
-
-//DP_QC_URI_ESCAPE
-//idea: divVerent
-//darkplaces implementation: divVerent
-//URI::Escape's functionality
-string(string in) uri_escape = #510;
-string(string in) uri_unescape = #511;
-
-//DP_QC_DIGEST
-//idea: motorsep, Spike
-//DarkPlaces implementation: divVerent
-//builtin definitions:
-string(string digest, string data, ...) digest_hex = #639;
-//description:
-//returns a given hex digest of given data
-//the returned digest is always encoded in hexadecimal
-//only the "MD4" digest is always supported!
-//if the given digest is not supported, string_null is returned
-//the digest string is matched case sensitively, use "MD4", not "md4"!
-
-//DP_QC_DIGEST_SHA256
-//idea: motorsep, Spike
-//DarkPlaces implementation: divVerent
-//description:
-//"SHA256" is also an allowed digest type
-
-//DP_QC_LOG
-//darkplaces implementation: divVerent
-//builtin definitions:
-float log(float f) = #532;
-//description:
-//logarithm
-
-//FTE_CSQC_SKELETONOBJECTS
-//idea: Spike, LordHavoc
-//darkplaces implementation: LordHavoc
-//builtin definitions:
-// all skeleton numbers are 1-based (0 being no skeleton)
-// all bone numbers are 1-based (0 being invalid)
-float(float modlindex) skel_create = #263; // create a skeleton (be sure to assign this value into .skeletonindex for use), returns skeleton index (1 or higher) on success, returns 0 on failure (for example if the modelindex is not skeletal), it is recommended that you create a new skeleton if you change modelindex, as the skeleton uses the hierarchy from the model.
-float(float skel, entity ent, float modlindex, float retainfrac, float firstbone, float lastbone) skel_build = #264; // blend in a percentage of standard animation, 0 replaces entirely, 1 does nothing, 0.5 blends half, etc, and this only alters the bones in the specified range for which out of bounds values like 0,100000 are safe (uses .frame, .frame2, .frame3, .frame4, .lerpfrac, .lerpfrac3, .lerpfrac4, .frame1time, .frame2time, .frame3time, .frame4time), returns skel on success, 0 on failure
-float(float skel) skel_get_numbones = #265; // returns how many bones exist in the created skeleton, 0 if skeleton does not exist
-string(float skel, float bonenum) skel_get_bonename = #266; // returns name of bone (as a tempstring), "" if invalid bonenum (< 1 for example) or skeleton does not exist
-int(float skel, float bonenum) skel_get_boneparent = #267; // returns parent num for supplied bonenum, 0 if bonenum has no parent or bone does not exist (returned value is always less than bonenum, you can loop on this)
-int(float skel, string tagname) skel_find_bone = #268; // get number of bone with specified name, 0 on failure, bonenum (1-based) on success, same as using gettagindex but takes modelindex instead of entity
-vector(float skel, float bonenum) skel_get_bonerel = #269; // get matrix of bone in skeleton relative to its parent - sets v_forward, v_right, v_up, returns origin (relative to parent bone)
-vector(float skel, float bonenum) skel_get_boneabs = #270; // get matrix of bone in skeleton in model space - sets v_forward, v_right, v_up, returns origin (relative to entity)
-void(float skel, float bonenum, vector org) skel_set_bone = #271; // set matrix of bone relative to its parent, reads v_forward, v_right, v_up, takes origin as parameter (relative to parent bone)
-void(float skel, float bonenum, vector org) skel_mul_bone = #272; // transform bone matrix (relative to its parent) by the supplied matrix in v_forward, v_right, v_up, takes origin as parameter (relative to parent bone)
-void(float skel, float startbone, float endbone, vector org) skel_mul_bones = #273; // transform bone matrices (relative to their parents) by the supplied matrix in v_forward, v_right, v_up, takes origin as parameter (relative to parent bones)
-void(float skeldst, float skelsrc, float startbone, float endbone) skel_copybones = #274; // copy bone matrices (relative to their parents) from one skeleton to another, useful for copying a skeleton to a corpse
-void(float skel) skel_delete = #275; // deletes skeleton at the beginning of the next frame (you can add the entity, delete the skeleton, renderscene, and it will still work)
-float(float modlindex, string framename) frameforname = #276; // finds number of a specified frame in the animation, returns -1 if no match found
-float(float modlindex, float framenum) frameduration = #277; // returns the intended play time (in seconds) of the specified framegroup, if it does not exist the result is 0, if it is a single frame it may be a small value around 0.1 or 0.
-//fields:
-.float skeletonindex; // active skeleton overriding standard animation on model
-.int frame; // primary framegroup animation (strength = 1 - lerpfrac - lerpfrac3 - lerpfrac4)
-.int frame2; // secondary framegroup animation (strength = lerpfrac)
-.int frame3; // tertiary framegroup animation (strength = lerpfrac3)
-.int frame4; // quaternary framegroup animation (strength = lerpfrac4)
-.float lerpfrac; // strength of framegroup blend
-.float lerpfrac3; // strength of framegroup blend
-.float lerpfrac4; // strength of framegroup blend
-.float frame1time; // start time of framegroup animation
-.float frame2time; // start time of framegroup animation
-.float frame3time; // start time of framegroup animation
-.float frame4time; // start time of framegroup animation
-//description:
-//this extension provides a way to do complex skeletal animation on an entity.
-//
-//see also DP_SKELETONOBJECTS (this extension implemented on server as well as client)
-//
-//notes:
-//each model contains its own skeleton, reusing a skeleton with incompatible models will yield garbage (or not render).
-//each model contains its own animation data, you can use animations from other model files (for example saving out all character animations as separate model files).
-//if an engine supports loading an animation-only file format such as .md5anim in FTEQW, it can be used to animate any model with a compatible skeleton.
-//proper use of this extension may require understanding matrix transforms (v_forward, v_right, v_up, origin), and you must keep in mind that v_right is negative for this purpose.
-//
-//features include:
-//multiple animations blended together.
-//animating a model with animations from another model with a compatible skeleton.
-//restricting animation blends to certain bones of a model - for example independent animation of legs, torso, head.
-//custom bone controllers - for example making eyes track a target location.
-//
-//
-//
-//example code follows...
-//
-//this helper function lets you identify (by parentage) what group a bone
-//belongs to - for example "torso", "leftarm", would return 1 ("torso") for
-//all children of the bone named "torso", unless they are children of
-//"leftarm" (which is a child of "torso") which would return 2 instead...
-float(float skel, float bonenum, string g1, string g2, string g3, string g4, string g5, string g6) example_skel_findbonegroup =
-{
-       string bonename;
-       while (bonenum >= 0)
-       {
-               bonename = skel_get_bonename(skel, bonenum);
-               if (bonename == g1) return 1;
-               if (bonename == g2) return 2;
-               if (bonename == g3) return 3;
-               if (bonename == g4) return 4;
-               if (bonename == g5) return 5;
-               if (bonename == g6) return 6;
-               bonenum = skel_get_boneparent(skel, bonenum);
-       }
-       return 0;
-};
-// create a skeletonindex for our player using current modelindex
-void() example_skel_player_setup =
-{
-       self.skeletonindex = skel_create(self.modelindex);
-};
-// setup bones of skeleton based on an animation
-// note: animmodelindex can be a different model than self.modelindex
-void(float animmodelindex, float framegroup, float framegroupstarttime) example_skel_player_update_begin =
-{
-       // start with our standard animation
-       self.frame = framegroup;
-       self.frame2 = 0;
-       self.frame3 = 0;
-       self.frame4 = 0;
-       self.frame1time = framegroupstarttime;
-       self.frame2time = 0;
-       self.frame3time = 0;
-       self.frame4time = 0;
-       self.lerpfrac = 0;
-       self.lerpfrac3 = 0;
-       self.lerpfrac4 = 0;
-       skel_build(self.skeletonindex, self, animmodelindex, 0, 0, 100000);
-};
-// apply a different framegroup animation to bones with a specified parent
-void(float animmodelindex, float framegroup, float framegroupstarttime, float blendalpha, string groupbonename, string excludegroupname1, string excludegroupname2) example_skel_player_update_applyoverride =
-{
-       self.frame = framegroup;
-       self.frame2 = 0;
-       self.frame3 = 0;
-       self.frame4 = 0;
-       self.frame1time = framegroupstarttime;
-       self.frame2time = 0;
-       self.frame3time = 0;
-       self.frame4time = 0;
-       self.lerpfrac = 0;
-       self.lerpfrac3 = 0;
-       self.lerpfrac4 = 0;
-       float bonenum = 0;
-       float numbones = skel_get_numbones(self.skeletonindex);
-       while (bonenum < numbones)
-       {
-               if (example_skel_findbonegroup(self.skeletonindex, bonenum, groupbonename, excludegroupname1, excludegroupname2, "", "", "") == 1)
-                       skel_build(self.skeletonindex, self, animmodelindex, 1 - blendalpha, bonenum, bonenum + 1);
-               bonenum = bonenum + 1;
-       }
-};
-// make eyes point at a target location, be sure v_forward, v_right, v_up are set correctly before calling
-void(vector eyetarget, string bonename) example_skel_player_update_eyetarget =
-{
-       float bonenum = skel_find_bone(self.skeletonindex, bonename) - 1;
-       if (bonenum < 0)
-               return;
-       vector oldforward = v_forward;
-       vector oldright = v_right;
-       vector oldup = v_up;
-       vector v = eyetarget - self.origin;
-       vector modeleyetarget;
-       modeleyetarget.x =   v * v_forward;
-       modeleyetarget.y = 0-v * v_right;
-       modeleyetarget.z =   v * v_up;
-       // this is an eyeball, make it point at the target location
-       // first get all the data we can...
-       vector relorg = skel_get_bonerel(self.skeletonindex, bonenum);
-       vector relforward = v_forward;
-       vector relright = v_right;
-       vector relup = v_up;
-       vector boneorg = skel_get_boneabs(self.skeletonindex, bonenum);
-       vector boneforward = v_forward;
-       vector boneright = v_right;
-       vector boneup = v_up;
-       vector parentorg = skel_get_boneabs(self.skeletonindex, skel_get_boneparent(self.skeletonindex, bonenum));
-       vector parentforward = v_forward;
-       vector parentright = v_right;
-       vector parentup = v_up;
-       // get the vector from the eyeball to the target
-       vector u = modeleyetarget - boneorg;
-       // now transform it inversely by the parent matrix to produce new rel vectors
-       v.x = u * parentforward;
-       v.y = u * parentright;
-       v.z = u * parentup;
-       vector ang = vectoangles2(v, relup);
-       ang.x = 0 - ang.x;
-       makevectors(ang);
-       // set the relative bone matrix
-       skel_set_bone(self.skeletonindex, bonenum, relorg);
-       // restore caller's v_ vectors
-       v_forward = oldforward;
-       v_right = oldright;
-       v_up = oldup;
-};
-// delete skeleton when we're done with it
-// note: skeleton remains valid until next frame when it is really deleted
-void() example_skel_player_delete =
-{
-       skel_delete(self.skeletonindex);
-       self.skeletonindex = 0;
-};
-//
-// END OF EXAMPLES FOR FTE_CSQC_SKELETONOBJECTS
-//
-
-//DP_QC_ENTITYDATA
-//idea: KrimZon
-//darkplaces implementation: KrimZon
-//builtin definitions:
-float() numentityfields = #496;
-string(float fieldnum) entityfieldname = #497;
-float(float fieldnum) entityfieldtype = #498;
-string(float fieldnum, entity ent) getentityfieldstring = #499;
-float(float fieldnum, entity ent, string s) putentityfieldstring = #500;
-//constants:
-//Returned by entityfieldtype
-float FIELD_STRING   = 1;
-float FIELD_FLOAT    = 2;
-float FIELD_VECTOR   = 3;
-float FIELD_ENTITY   = 4;
-float FIELD_FUNCTION = 6;
-//description:
-//Versatile functions intended for storing data from specific entities between level changes, but can be customized for some kind of partial savegame.
-//WARNING: .entity fields cannot be saved and restored between map loads as they will leave dangling pointers.
-//numentityfields returns the number of entity fields. NOT offsets. Vectors comprise 4 fields: v, v_x, v_y and v_z.
-//entityfieldname returns the name as a string, eg. "origin" or "classname" or whatever.
-//entityfieldtype returns a value that the constants represent, but the field may be of another type in more exotic progs.dat formats or compilers.
-//getentityfieldstring returns data as would be written to a savegame, eg... "0.05" (float), "0 0 1" (vector), or "Hello World!" (string). Function names can also be returned.
-//putentityfieldstring puts the data returned by getentityfieldstring back into the entity.
-
-//DP_QC_ENTITYSTRING
-void(string s) loadfromdata = #529;
-void(string s) loadfromfile = #530;
-void(string s) callfunction = #605;
-void(float fh, entity e) writetofile = #606;
-float(string s) isfunction = #607;
-void(entity e, string s) parseentitydata = #608;
-
-//DP_COVERAGE
-//idea: divVerent
-//darkplaces implementation: divVerent
-//function definitions:
-void coverage() = #642;  // Reports a coverage event. The engine counts for each of the calls to this builtin whether it has been called.
-
-// assorted builtins
-//const int STAT_MOVEVARS_TICRATE              = 240;
-//const int STAT_MOVEVARS_TIMESCALE            = 241;
-//const int STAT_FRAGLIMIT                             = 235;
-//const int STAT_TIMELIMIT                             = 236;
-//const int STAT_MOVEVARS_GRAVITY       = 242;
-string(void) ReadPicture                               = #501;
-const int PARTICLES_USEALPHA = 1;
-float particles_alphamin, particles_alphamax;
-const int PARTICLES_USECOLOR = 2;
-vector particles_colormin, particles_colormax;
-const int PARTICLES_USEFADE = 4;  // fades the COUNT (fade alpha using alphamin/alphamax)
-float particles_fade;
-const int PARTICLES_DRAWASTRAIL = 128;
-void(float effectindex, entity own, vector org_from, vector org_to, vector dir_from, vector dir_to, float countmultiplier, float flags) boxparticles = #502;
-float trace_networkentity;
-const int RF_FULLBRIGHT        = 256;
-const int RF_NOSHADOW  = 512;
-const int RF_DYNAMICMODELLIGHT = 8192;
-
-float gettaginfo_parent;
-string gettaginfo_name;
-vector gettaginfo_offset;
-vector gettaginfo_forward;
-vector gettaginfo_right;
-vector gettaginfo_up;
-float checkpvs(vector viewpos, entity viewee) = #240;
+#undef true
+#undef false
+#undef TRUE
+#undef FALSE
 
 #pragma noref 0
 
index 109e9195bb03cda7212ef627a29fbe8cd5785e4c..2487da4ff357a8751c3ab8e643ce0168ad02c47a 100644 (file)
 #ifndef DPEXTENSIONS_H
 #define DPEXTENSIONS_H
-//DarkPlaces supported extension list, draft version 1.04
 
-//things that don't have extensions yet:
-.float disableclientprediction;
+#pragma noref 1
 
-//definitions that id Software left out:
-//these are passed as the 'nomonsters' parameter to traceline/tracebox (yes really this was supported in all quake engines, nomonsters is misnamed)
-float MOVE_NORMAL = 0; // same as false
-float MOVE_NOMONSTERS = 1; // same as true
-float MOVE_MISSILE = 2; // save as movement with .movetype == MOVETYPE_FLYMISSILE
+#include "upstream/dpextensions.qc"
 
-//checkextension function
-//idea: expected by almost everyone
-//darkplaces implementation: LordHavoc
-float(string s) checkextension = #99;
-//description:
-//check if (cvar("pr_checkextension")) before calling this, this is the only
-//guaranteed extension to be present in the extension system, it allows you
-//to check if an extension is available, by name, to check for an extension
-//use code like this:
-//// (it is recommended this code be placed in worldspawn or a worldspawn called function somewhere)
-//if (cvar("pr_checkextension"))
-//if (checkextension("DP_SV_SETCOLOR"))
-//     ext_setcolor = true;
-//from then on you can check ext_setcolor to know if that extension is available
+int(entity ent, string tagname) _gettagindex = #451;
+#define gettagindex _gettagindex
 
-//BX_WAL_SUPPORT
-//idea: id Software
-//darkplaces implementation: LordHavoc
-//description:
-//indicates the engine supports .wal textures for filenames in the textures/ directory
-//(note: DarkPlaces has supported this since 2001 or 2002, but did not advertise it as an extension, then I noticed Betwix was advertising it and added the extension accordingly)
+int(string effectname) _particleeffectnum = #335;
+#define particleeffectnum _particleeffectnum
 
-//DP_BUTTONCHAT
-//idea: Vermeulen
-//darkplaces implementation: LordHavoc
-//field definitions:
-.float buttonchat;
-//description:
-//true if the player is currently chatting (in messagemode, menus or console)
+int(string s, string separator1, ...) _tokenizebyseparator = #479;
+#define tokenizebyseparator _tokenizebyseparator
 
-//DP_BUTTONUSE
-//idea: id Software
-//darkplaces implementation: LordHavoc
-//field definitions:
-.float buttonuse;
-//client console commands:
-//+use
-//-use
-//description:
-//made +use and -use commands work, they now control the .buttonuse field (.button1 was used by many mods for other purposes).
+int(string s) _tokenize_console = #514;
+#define tokenize_console _tokenize_console
 
-//DP_CL_LOADSKY
-//idea: Nehahra, LordHavoc
-//darkplaces implementation: LordHavoc
-//client console commands:
-//"loadsky" (parameters: "basename", example: "mtnsun_" would load "mtnsun_up.tga" and "mtnsun_rt.tga" and similar names, use "" to revert to quake sky, note: this is the same as Quake2 skybox naming)
-//description:
-//sets global skybox for the map for this client (can be stuffed to a client by QC), does not hurt much to repeatedly execute this command, please don't use this in mods if it can be avoided (only if changing skybox is REALLY needed, otherwise please use DP_GFX_SKYBOX).
+int(int i) _argv_start_index = #515;
+#define argv_start_index _argv_start_index
 
-//DP_CON_SET
-//idea: id Software
-//darkplaces implementation: LordHavoc
-//description:
-//indicates this engine supports the "set" console command which creates or sets a non-archived cvar (not saved to config.cfg on exit), it is recommended that set and seta commands be placed in default.cfg for mod-specific cvars.
+int(int i) _argv_end_index = #516;
+#define argv_end_index _argv_end_index
 
-//DP_CON_SETA
-//idea: id Software
-//darkplaces implementation: LordHavoc
-//description:
-//indicates this engine supports the "seta" console command which creates or sets an archived cvar (saved to config.cfg on exit), it is recommended that set and seta commands be placed in default.cfg for mod-specific cvars.
+int(string s) _strlen = #114;
+#define strlen _strlen
 
-//DP_CON_ALIASPARAMETERS
-//idea: many
-//darkplaces implementation: Black
-//description:
-//indicates this engine supports aliases containing $1 through $9 parameter macros (which when called will expand to the parameters passed to the alias, for example alias test "say $2 $1", then you can type test hi there and it will execute say there hi), as well as $0 (name of the alias) and $* (all parameters $1 onward).
+float(float skel, float bonenum) _skel_get_boneparent = #267;
+#define skel_get_boneparent _skel_get_boneparent
 
-//DP_CON_EXPANDCVAR
-//idea: many, PHP
-//darkplaces implementation: Black
-//description:
-//indicates this engine supports console commandlines containing $cvarname which will expand to the contents of that cvar as a parameter, for instance say my fov is $fov, will say "my fov is 90", or similar.
+float(float skel, string tagname) _skel_find_bone = #268;
+#define skel_find_bone _skel_find_bone
 
-//DP_CON_STARTMAP
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//description:
-//adds two engine-called aliases named startmap_sp and startmap_dm which are called when the engine tries to start a singleplayer game from the menu (startmap_sp) or the -listen or -dedicated options are used or the engine is a dedicated server (uses startmap_dm), these allow a mod or game to specify their own map instead of start, and also distinguish between singleplayer and -listen/-dedicated, also these need not be a simple "map start" command, they can do other things if desired, startmap_sp and startmap_dm both default to "map start".
+float(string str, string sub, float startpos) _strstrofs = #221;
+#define strstrofs _strstrofs
 
-//DP_EF_ADDITIVE
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//effects bit:
-const int   EF_ADDITIVE     = 32;
-//description:
-//additive blending when this object is rendered
+float(string str, float ofs) _str2chr = #222;
+#define str2chr _str2chr
 
-//DP_EF_BLUE
-//idea: id Software
-//darkplaces implementation: LordHavoc
-//effects bit:
-const int   EF_BLUE         = 64;
-//description:
-//entity emits blue light (used for quad)
+string(int c, ...) _chr2str = #223;
+#define chr2str _chr2str
 
-//DP_EF_DOUBLESIDED
-//idea: LordHavoc
-//darkplaces implementation: [515] and LordHavoc
-//effects bit:
-const int EF_DOUBLESIDED = 32768;
-//description:
-//render entity as double sided (backfaces are visible, I.E. you see the 'interior' of the model, rather than just the front), can be occasionally useful on transparent stuff.
+int(string s1, string s2) _strcmp = #228;
+#define strcmp _strcmp
 
-//DP_EF_DYNAMICMODELLIGHT
-//idea: C.Brutail, divVerent, maikmerten
-//darkplaces implementation: divVerent
-//effects bit:
-const int   EF_DYNAMICMODELLIGHT     = 131072;
-//description:
-//force dynamic model light on the entity, even if it's a BSP model (or anything else with lightmaps or light colors)
+int(string s1, string s2, int len) _strncmp = #228;
+#define strncmp _strncmp
 
-//DP_EF_FLAME
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//effects bit:
-const int   EF_FLAME        = 1024;
-//description:
-//entity is on fire
+int(string s1, string s2) _strcasecmp = #229;
+#define strcasecmp _strcasecmp
 
-//DP_EF_FULLBRIGHT
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//effects bit:
-const int   EF_FULLBRIGHT   = 512;
-//description:
-//entity is always brightly lit
+int(string s1, string s2, int len) _strncasecmp = #230;
+#define strncasecmp _strncasecmp
 
-//DP_EF_NODEPTHTEST
-//idea: Supa
-//darkplaces implementation: LordHavoc
-//effects bit:
-const int   EF_NODEPTHTEST       = 8192;
-//description:
-//makes entity show up to client even through walls, useful with EF_ADDITIVE for special indicators like where team bases are in a map, so that people don't get lost
+int() _buf_create = #460;
+#define buf_create _buf_create
 
-//DP_EF_NODRAW
-//idea: id Software
-//darkplaces implementation: LordHavoc
-//effects bit:
-const int   EF_NODRAW       = 16;
-//description:
-//prevents server from sending entity to client (forced invisible, even if it would have been a light source or other such things)
+#pragma noref 0
 
-//DP_EF_NOGUNBOB
-//idea: Chris Page, Dresk
-//darkplaces implementation: LordHAvoc
-//effects bit:
-const int   EF_NOGUNBOB     = 256;
-//description:
-//this has different meanings depending on the entity it is used on:
-//player entity - prevents gun bobbing on player.viewmodel
-//viewmodelforclient entity - prevents gun bobbing on an entity attached to the player's view
-//other entities - no effect
-//uses:
-//disabling gun bobbing on a diving mask or other model used as a .viewmodel.
-//disabling gun bobbing on view-relative models meant to be part of the heads up display.  (note: if fov is changed these entities may be off-screen, or too near the center of the screen, so use fov 90 in this case)
-
-//DP_EF_NOSHADOW
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//effects bit:
-const int   EF_NOSHADOW     = 4096;
-//description:
-//realtime lights will not cast shadows from this entity (but can still illuminate it)
-
-//DP_EF_RED
-//idea: id Software
-//darkplaces implementation: LordHavoc
-//effects bit:
-const int   EF_RED          = 128;
-//description:
-//entity emits red light (used for invulnerability)
-
-//DP_EF_RESTARTANIM_BIT
-//idea: id software
-//darkplaces implementation: divVerent
-//effects bit:
-const int   EF_RESTARTANIM_BIT = 1048576;
-//description:
-//when toggled, the current animation is restarted. Useful for weapon animation.
-//to toggle this bit in QC, you can do:
-//  self.effects += (EF_RESTARTANIM_BIT - 2 * (self.effects & EF_RESTARTANIM_BIT));
-
-//DP_EF_STARDUST
-//idea: MythWorks Inc
-//darkplaces implementation: LordHavoc
-//effects bit:
-const int   EF_STARDUST     = 2048;
-//description:
-//entity emits bouncing sparkles in every direction
-
-//DP_EF_TELEPORT_BIT
-//idea: id software
-//darkplaces implementation: divVerent
-//effects bit:
-const int   EF_TELEPORT_BIT = 2097152;
-//description:
-//when toggled, interpolation of the entity is skipped for one frame. Useful for teleporting.
-//to toggle this bit in QC, you can do:
-//  self.effects += (EF_TELEPORT_BIT - 2 * (self.effects & EF_TELEPORT_BIT));
-
-//DP_ENT_ALPHA
-//idea: Nehahra
-//darkplaces implementation: LordHavoc
-//fields:
-.float alpha;
-//description:
-//controls opacity of the entity, 0.0 is forced to be 1.0 (otherwise everything would be invisible), use -1 if you want to make something invisible, 1.0 is solid (like normal).
-
-//DP_ENT_COLORMOD
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//field definition:
-.vector colormod;
-//description:
-//controls color of the entity, '0 0 0', is forced to be '1 1 1' (otherwise everything would be black), used for tinting objects, for instance using '1 0.6 0.4' on an ogre would give you an orange ogre (order is red green blue), note the colors can go up to '8 8 8' (8x as bright as normal).
-
-//DP_ENT_CUSTOMCOLORMAP
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//description:
-//if .colormap is set to 1024 + pants + shirt * 16, those colors will be used for colormapping the entity, rather than looking up a colormap by player number.
-
-/*
-//NOTE: no longer supported by darkplaces because all entities are delta compressed now
-//DP_ENT_DELTACOMPRESS // no longer supported
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//effects bit:
-float EF_DELTA = 8388608;
-//description:
-//(obsolete) applies delta compression to the network updates of the entity, making updates smaller, this might cause some unreliable behavior in packet loss situations, so it should only be used on numerous (nails/plasma shots/etc) or unimportant objects (gibs/shell casings/bullet holes/etc).
-*/
-
-//DP_ENT_EXTERIORMODELTOCLIENT
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//fields:
-.entity exteriormodeltoclient;
-//description:
-//the entity is visible to all clients with one exception: if the specified client is using first person view (not using chase_active) the entity will not be shown.  Also if tag attachments are supported any entities attached to the player entity will not be drawn in first person.
-
-//DP_ENT_GLOW
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//field definitions:
-.float glow_color;
-.float glow_size;
-.float glow_trail;
-//description:
-//customizable glowing light effect on the entity, glow_color is a paletted (8bit) color in the range 0-255 (note: 0 and 254 are white), glow_size is 0 or higher (up to the engine what limit to cap it to, darkplaces imposes a 1020 limit), if glow_trail is true it will leave a trail of particles of the same color as the light.
-
-//DP_ENT_GLOWMOD
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//field definition:
-.vector glowmod;
-//description:
-//controls color of the entity's glow texture (fullbrights), '0 0 0', is forced to be '1 1 1' (otherwise everything would be black), used for tinting objects, see colormod (same color restrictions apply).
-
-//DP_ENT_LOWPRECISION
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//effects bit:
-const int EF_LOWPRECISION = 4194304;
-//description:
-//uses low quality origin coordinates, reducing network traffic compared to the default high precision, intended for numerous objects (projectiles/gibs/bullet holes/etc).
-
-//DP_ENT_SCALE
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//field definitions:
-.float scale;
-//description:
-//controls rendering scale of the object, 0 is forced to be 1, darkplaces uses 1/16th accuracy and a limit of 15.9375, can be used to make an object larger or smaller.
-
-//DP_ENT_TRAILEFFECTNUM
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//field definitions:
-.float traileffectnum;
-//description:
-//use a custom effectinfo.txt effect on this entity, assign it like this:
-//self.traileffectnum = particleeffectnum("mycustomeffect");
-//this will do both the dlight and particle trail as described in the effect, basically equivalent to trailparticles() in CSQC but performed on a server entity.
-
-//DP_ENT_VIEWMODEL
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//field definitions:
-.entity viewmodelforclient;
-//description:
-//this is a very special capability, attachs the entity to the view of the client specified, origin and angles become relative to the view of that client, all effects can be used (multiple skins on a weapon model etc)...  the entity is not visible to any other client.
-
-//DP_GFX_EXTERNALTEXTURES
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//description:
-//loads external textures found in various directories (tenebrae compatible)...
-/*
-in all examples .tga is merely the base texture, it can be any of these:
-.tga (base texture)
-_glow.tga (fullbrights or other glowing overlay stuff, NOTE: this is done using additive blend, not alpha)
-_pants.tga (pants overlay for colormapping on models, this should be shades of grey (it is tinted by pants color) and black wherever the base texture is not black, as this is an additive blend)
-_shirt.tga (same idea as pants, but for shirt color)
-_diffuse.tga (this may be used instead of base texture for per pixel lighting)
-_gloss.tga (specular texture for per pixel lighting, note this can be in color (tenebrae only supports greyscale))
-_norm.tga (normalmap texture for per pixel lighting)
-_bump.tga (bumpmap, converted to normalmap at load time, supported only for reasons of tenebrae compatibility)
-_luma.tga (same as _glow but supported only for reasons of tenebrae compatibility)
-
-due to glquake's incomplete Targa(r) loader, this section describes
-required Targa(r) features support:
-types:
-type 1 (uncompressed 8bit paletted with 24bit/32bit palette)
-type 2 (uncompressed 24bit/32bit true color, glquake supported this)
-type 3 (uncompressed 8bit greyscale)
-type 9 (RLE compressed 8bit paletted with 24bit/32bit palette)
-type 10 (RLE compressed 24bit/32bit true color, glquake supported this)
-type 11 (RLE compressed 8bit greyscale)
-attribute bit 0x20 (Origin At Top Left, top to bottom, left to right)
-
-image formats guaranteed to be supported: tga, pcx, lmp
-image formats that are optional: png, jpg
-
-mdl/spr/spr32 examples:
-skins are named _A (A being a number) and skingroups are named like _A_B
-these act as suffixes on the model name...
-example names for skin _2_1 of model "progs/armor.mdl":
-game/override/progs/armor.mdl_2_1.tga
-game/textures/progs/armor.mdl_2_1.tga
-game/progs/armor.mdl_2_1.tga
-example names for skin _0 of the model "progs/armor.mdl":
-game/override/progs/armor.mdl_0.tga
-game/textures/progs/armor.mdl_0.tga
-game/progs/armor.mdl_0.tga
-note that there can be more skins files (of the _0 naming) than the mdl
-contains, this is only useful to save space in the .mdl file if classic quake
-compatibility is not a concern.
-
-bsp/md2/md3 examples:
-example names for the texture "quake" of model "maps/start.bsp":
-game/override/quake.tga
-game/textures/quake.tga
-game/quake.tga
-
-sbar/menu/console textures: for example the texture "conchars" (console font) in gfx.wad
-game/override/gfx/conchars.tga
-game/textures/gfx/conchars.tga
-game/gfx/conchars.tga
-*/
-
-//DP_GFX_EXTERNALTEXTURES_PERMAPTEXTURES
-//idea: Fuh?
-//darkplaces implementation: LordHavoc
-//description:
-//Q1BSP and HLBSP map loading loads external textures found in textures/<mapname>/ as well as textures/.
-//Where mapname is the bsp filename minus the extension (typically .bsp) and minus maps/ if it is in maps/ (any other path is not removed)
-//example:
-//maps/e1m1.bsp uses textures in the directory textures/e1m1/ and falls back to textures/
-//maps/b_batt0.bsp uses textures in the directory textures/b_batt0.bsp and falls back to textures/
-//as a more extreme example:
-//progs/something/blah.bsp uses textures in the directory textures/progs/something/blah/ and falls back to textures/
-
-//DP_GFX_FOG
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//worldspawn fields:
-//"fog" (parameters: "density red green blue", example: "0.1 0.3 0.3 0.3")
-//description:
-//global fog for the map, can not be changed by QC
-
-//DP_GFX_QUAKE3MODELTAGS
-//idea: id Software
-//darkplaces implementation: LordHavoc
-//field definitions:
-.entity tag_entity; // entity this is attached to (call setattachment to set this)
-.float tag_index; // which tag on that entity (0 is relative to the entity, > 0 is an index into the tags on the model if it has any) (call setattachment to set this)
-//builtin definitions:
-void(entity e, entity tagentity, string tagname) setattachment = #443; // attachs e to a tag on tagentity (note: use "" to attach to entity origin/angles instead of a tag)
-//description:
-//allows entities to be visually attached to model tags (which follow animations perfectly) on other entities, for example attaching a weapon to a player's hand, or upper body attached to lower body, allowing it to change angles and frame separately (note: origin and angles are relative to the tag, use '0 0 0' for both if you want it to follow exactly, this is similar to viewmodelforclient's behavior).
-//note 2: if the tag is not found, it defaults to "" (attach to origin/angles of entity)
-//note 3: attaching to world turns off attachment
-//note 4: the entity that this is attached to must be visible for this to work
-//note 5: if an entity is attached to the player entity it will not be drawn in first person.
-
-//DP_GFX_SKINFILES
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//description:
-//alias models (mdl, md2, md3) can have .skin files to replace conventional texture naming, these have a naming format such as:
-//progs/test.md3_0.skin
-//progs/test.md3_1.skin
-//...
-//
-//these files contain replace commands (replace meshname shadername), example:
-//replace "helmet" "progs/test/helmet1.tga" // this is a mesh shader replacement
-//replace "teamstripes" "progs/test/redstripes.tga"
-//replace "visor" "common/nodraw" // this makes the visor mesh invisible
-////it is not possible to rename tags using this format
-//
-//Or the Quake3 syntax (100% compatible with Quake3's .skin files):
-//helmet,progs/test/helmet1.tga // this is a mesh shader replacement
-//teamstripes,progs/test/redstripes.tga
-//visor,common/nodraw // this makes the visor mesh invisible
-//tag_camera, // this defines that the first tag in the model is called tag_camera
-//tag_test, // this defines that the second tag in the model is called tag_test
-//
-//any names that are not replaced are automatically show up as a grey checkerboard to indicate the error status, and "common/nodraw" is a special case that is invisible.
-//this feature is intended to allow multiple skin sets on md3 models (which otherwise only have one skin set).
-//other commands might be added someday but it is not expected.
-
-//DP_GFX_SKYBOX
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//worldspawn fields:
-//"sky" (parameters: "basename", example: "mtnsun_" would load "mtnsun_up.tga" and "mtnsun_rt.tga" and similar names, note: "sky" is also used the same way by Quake2)
-//description:
-//global skybox for the map, can not be changed by QC
-
-//DP_UTF8
-//idea: Blub\0, divVerent
-//darkplaces implementation: Blub\0
-//cvar definitions:
-//   utf8_enable: enable utf8 encoding
-//description: utf8 characters are allowed inside cvars, protocol strings, files, progs strings, etc., 
-//and count as 1 char for string functions like strlen, substring, etc.
-// note: utf8_enable is run-time cvar, could be changed during execution
-// note: beware that str2chr() could return value bigger than 255 once utf8 is enabled
-
-//DP_HALFLIFE_MAP
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//description:
-//simply indicates that the engine supports HalfLife maps (BSP version 30, NOT the QER RGBA ones which are also version 30).
-
-//DP_HALFLIFE_MAP_CVAR
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//cvars:
-//halflifebsp 0/1
-//description:
-//engine sets this cvar when loading a map to indicate if it is halflife format or not.
-
-//DP_HALFLIFE_SPRITE
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//description:
-//simply indicates that the engine supports HalfLife sprites.
-
-//DP_INPUTBUTTONS
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//field definitions:
-.float button3;
-.float button4;
-.float button5;
-.float button6;
-.float button7;
-.float button8;
-.float button9;
-.float button10;
-.float button11;
-.float button12;
-.float button13;
-.float button14;
-.float button15;
-.float button16;
-//description:
-//set to the state of the +button3, +button4, +button5, +button6, +button7, and +button8 buttons from the client, this does not involve protocol changes (the extra 6 button bits were simply not used).
-//the exact mapping of protocol button bits on the server is:
-//self.button0 = (bits & 1) != 0;
-///* button1 is skipped because mods abuse it as a variable, and accordingly it has no bit */
-//self.button2 = (bits & 2) != 0;
-//self.button3 = (bits & 4) != 0;
-//self.button4 = (bits & 8) != 0;
-//self.button5 = (bits & 16) != 0;
-//self.button6 = (bits & 32) != 0;
-//self.button7 = (bits & 64) != 0;
-//self.button8 = (bits & 128) != 0;
-
-// DP_LIGHTSTYLE_STATICVALUE
-// idea: VorteX
-// darkplaces implementation: VorteX
-// description: allows alternative 'static' lightstyle syntax : "=value"
-// examples: "=0.5", "=2.0", "=2.75"
-// could be used to control switchable lights or making styled lights with brightness > 2
-// Warning: this extension is experimental. It safely works in CSQC, but SVQC use is limited by the fact 
-// that other engines (which do not support this extension) could connect to a game and misunderstand this kind of lightstyle syntax
-
-//DP_LITSPRITES
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//description:
-//indicates this engine supports lighting on sprites, any sprite with ! in its filename (both on disk and in the qc) will be lit rather than having forced EF_FULLBRIGHT (EF_FULLBRIGHT on the entity can still force these sprites to not be lit).
-
-//DP_LITSUPPORT
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//description:
-//indicates this engine loads .lit files for any quake1 format .bsp files it loads to enhance maps with colored lighting.
-//implementation description: these files begin with the header QLIT followed by version number 1 (as little endian 32bit), the rest of the file is a replacement lightmaps lump, except being 3x as large as the lightmaps lump of the map it matches up with (and yes the between-lightmap padding is expanded 3x to keep this consistent), so the lightmap offset in each surface is simply multiplied by 3 during loading to properly index the lit data, and the lit file is loaded instead of the lightmap lump, other renderer changes are needed to display these of course...  see the litsupport.zip sample code (almost a tutorial) at http://icculus.org/twilight/darkplaces for more information.
-
-//DP_MONSTERWALK
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//description:
-//MOVETYPE_WALK is permitted on non-clients, so bots can move smoothly, run off ledges, etc, just like a real player.
-
-//DP_MOVETYPEBOUNCEMISSILE
-//idea: id Software
-//darkplaces implementation: id Software
-//movetype definitions:
-//float MOVETYPE_BOUNCEMISSILE = 11; // already in defs.qc
-//description:
-//MOVETYPE_BOUNCE but without gravity, and with full reflection (no speed loss like grenades have), in other words - bouncing laser bolts.
-
-//DP_MOVETYPEFLYWORLDONLY
-//idea: Samual
-//darkplaces implementation: Samual
-//movetype definitions:
-float MOVETYPE_FLY_WORLDONLY = 33;
-//description:
-//like MOVETYPE_FLY, but does all traces with MOVE_WORLDONLY, and is ignored by MOVETYPE_PUSH. Should only be combined with SOLID_NOT and SOLID_TRIGGER.
-
-//DP_NULL_MODEL
-//idea: Chris
-//darkplaces implementation: divVerent
-//definitions:
-//string dp_null_model = "null";
-//description:
-//setmodel(e, "null"); makes an entity invisible, have a zero bbox, but
-//networked. useful for shared CSQC entities.
-
-//DP_MOVETYPEFOLLOW
-//idea: id Software, LordHavoc (redesigned)
-//darkplaces implementation: LordHavoc
-//movetype definitions:
-float MOVETYPE_FOLLOW = 12;
-//description:
-//MOVETYPE_FOLLOW implemented, this uses existing entity fields in unusual ways:
-//aiment - the entity this is attached to.
-//punchangle - the original angles when the follow began.
-//view_ofs - the relative origin (note that this is un-rotated by punchangle, and that is actually the only purpose of punchangle).
-//v_angle - the relative angles.
-//here's an example of how you would set a bullet hole sprite to follow a bmodel it was created on, even if the bmodel rotates:
-//hole.movetype = MOVETYPE_FOLLOW; // make the hole follow
-//hole.solid = SOLID_NOT; // MOVETYPE_FOLLOW is always non-solid
-//hole.aiment = bmodel; // make the hole follow bmodel
-//hole.punchangle = bmodel.angles; // the original angles of bmodel
-//hole.view_ofs = hole.origin - bmodel.origin; // relative origin
-//hole.v_angle = hole.angles - bmodel.angles; // relative angles
-
-//DP_QC_ASINACOSATANATAN2TAN
-//idea: Urre
-//darkplaces implementation: LordHavoc
-//constant definitions:
-float DEG2RAD = 0.0174532925199432957692369076848861271344287188854172545609719144;
-float RAD2DEG = 57.2957795130823208767981548141051703324054724665643215491602438612;
-float PI      = 3.1415926535897932384626433832795028841971693993751058209749445923;
-//builtin definitions:
-float(float s) asin = #471; // returns angle in radians for a given sin() value, the result is in the range -PI*0.5 to PI*0.5
-float(float c) acos = #472; // returns angle in radians for a given cos() value, the result is in the range 0 to PI
-float(float t) atan = #473; // returns angle in radians for a given tan() value, the result is in the range -PI*0.5 to PI*0.5
-float(float c, float s) atan2 = #474; // returns angle in radians for a given cos() and sin() value pair, the result is in the range -PI to PI (this is identical to vectoyaw except it returns radians rather than degrees)
-float(float a) tan = #475; // returns tangent value (which is simply sin(a)/cos(a)) for the given angle in radians, the result is in the range -infinity to +infinity
-//description:
-//useful math functions for analyzing vectors, note that these all use angles in radians (just like the cos/sin functions) not degrees unlike makevectors/vectoyaw/vectoangles, so be sure to do the appropriate conversions (multiply by DEG2RAD or RAD2DEG as needed).
-//note: atan2 can take unnormalized vectors (just like vectoyaw), and the function was included only for completeness (more often you want vectoyaw or vectoangles), atan2(v_x,v_y) * RAD2DEG gives the same result as vectoyaw(v)
-
-//DP_QC_AUTOCVARS
-//idea: divVerent
-//darkplaces implementation: divVerent
-//description:
-//allows QC variables to be bound to cvars
-//(works for float, string, vector types)
-//example:
-// float autocvar_developer;
-// float autocvar_registered;
-// string autocvar__cl_name;
-//NOTE: copying a string-typed autocvar to another variable/field, and then
-//changing the cvar or returning from progs is UNDEFINED. Writing to autocvar
-//globals is UNDEFINED. Accessing autocvar globals after changing that cvar in
-//the same frame by any means other than cvar_set() from the same QC VM is
-//IMPLEMENTATION DEFINED (an implementation may either yield the previous, or
-//the current, value). Changing them via cvar_set() in the same QC VM
-//immediately must reflect on the autocvar globals. Whether autocvar globals,
-//after restoring a savegame, have the cvar's current value, or the original
-//value at time of saving, is UNDEFINED. Restoring a savegame however must not
-//restore the cvar values themselves.
-//In case the cvar does NOT exist, then it is automatically created with the
-//value of the autocvar initializer, if given. This is possible with e.g.
-//frikqcc and fteqcc the following way:
-// var float autocvar_whatever = 42;
-//If no initializer is given, the cvar will be initialized to a string
-//equivalent to the NULL value of the given data type, that is, the empty
-//string, 0, or '0 0 0'. However, when automatic cvar creation took place, a
-//warning is printed to the game console.
-//NOTE: to prevent an ambiguity with float names for vector types, autocvar
-//names MUST NOT end with _x, _y or _z!
-
-//DP_QC_CHANGEPITCH
-//idea: id Software
-//darkplaces implementation: id Software
-//field definitions:
-.float idealpitch;
-.float pitch_speed;
-//builtin definitions:
-void(entity ent) changepitch = #63;
-//description:
-//equivalent to changeyaw, ent is normally self. (this was a Q2 builtin)
-
-//DP_QC_COPYENTITY
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//builtin definitions:
-void(entity from, entity to) copyentity = #400;
-//description:
-//copies all data in the entity to another entity.
-
-//DP_QC_CRC16
-//idea: divVerent
-//darkplaces implementation: divVerent
-//Some hash function to build hash tables with. This has to be be the CRC-16-CCITT that is also required for the QuakeWorld download protocol.
-//When caseinsensitive is set, the CRC is calculated of the lower cased string.
-float(float caseinsensitive, string s, ...) crc16 = #494;
-
-//DP_QC_CVAR_DEFSTRING
-//idea: id Software (Doom3), LordHavoc
-//darkplaces implementation: LordHavoc
-//builtin definitions:
-string(string s) cvar_defstring = #482;
-//description:
-//returns the default value of a cvar, as a tempstring.
-
-//DP_QC_CVAR_DESCRIPTION
-//idea: divVerent
-//DarkPlaces implementation: divVerent
-//builtin definitions:
-string(string name) cvar_description = #518;
-//description:
-//returns the description of a cvar
-
-//DP_QC_CVAR_STRING
-//idea: VorteX
-//DarkPlaces implementation: VorteX, LordHavoc
-//builtin definitions:
-string(string s) cvar_string = #448;
-//description:
-//returns the value of a cvar, as a tempstring.
-
-//DP_QC_CVAR_TYPE
-//idea: divVerent
-//DarkPlaces implementation: divVerent
-//builtin definitions:
-float(string name) cvar_type = #495;
-float CVAR_TYPEFLAG_EXISTS = 1;
-float CVAR_TYPEFLAG_SAVED = 2;
-float CVAR_TYPEFLAG_PRIVATE = 4;
-float CVAR_TYPEFLAG_ENGINE = 8;
-float CVAR_TYPEFLAG_HASDESCRIPTION = 16;
-float CVAR_TYPEFLAG_READONLY = 32;
-
-//DP_QC_DIGEST
-//idea: motorsep, Spike
-//DarkPlaces implementation: divVerent
-//builtin definitions:
-string(string digest, string data, ...) digest_hex = #639;
-//description:
-//returns a given hex digest of given data
-//the returned digest is always encoded in hexadecimal
-//only the "MD4" digest is always supported!
-//if the given digest is not supported, string_null is returned
-//the digest string is matched case sensitively, use "MD4", not "md4"!
-
-//DP_QC_DIGEST_SHA256
-//idea: motorsep, Spike
-//DarkPlaces implementation: divVerent
-//description:
-//"SHA256" is also an allowed digest type
-
-//DP_QC_EDICT_NUM
-//idea: 515
-//DarkPlaces implementation: LordHavoc
-//builtin definitions:
-entity(float entnum) edict_num = #459;
-float(entity ent) wasfreed = #353; // same as in EXT_CSQC extension
-//description:
-//edict_num returns the entity corresponding to a given number, this works even for freed entities, but you should call wasfreed(ent) to see if is currently active.
-//wasfreed returns whether an entity slot is currently free (entities that have never spawned are free, entities that have had remove called on them are also free).
-
-//DP_QC_ENTITYDATA
-//idea: KrimZon
-//darkplaces implementation: KrimZon
-//builtin definitions:
-float() numentityfields = #496;
-string(float fieldnum) entityfieldname = #497;
-float(float fieldnum) entityfieldtype = #498;
-string(float fieldnum, entity ent) getentityfieldstring = #499;
-float(float fieldnum, entity ent, string s) putentityfieldstring = #500;
-//constants:
-//Returned by entityfieldtype
-float FIELD_STRING   = 1;
-float FIELD_FLOAT    = 2;
-float FIELD_VECTOR   = 3;
-float FIELD_ENTITY   = 4;
-float FIELD_FUNCTION = 6;
-//description:
-//Versatile functions intended for storing data from specific entities between level changes, but can be customized for some kind of partial savegame.
-//WARNING: .entity fields cannot be saved and restored between map loads as they will leave dangling pointers.
-//numentityfields returns the number of entity fields. NOT offsets. Vectors comprise 4 fields: v, v_x, v_y and v_z.
-//entityfieldname returns the name as a string, eg. "origin" or "classname" or whatever.
-//entityfieldtype returns a value that the constants represent, but the field may be of another type in more exotic progs.dat formats or compilers.
-//getentityfieldstring returns data as would be written to a savegame, eg... "0.05" (float), "0 0 1" (vector), or "Hello World!" (string). Function names can also be returned.
-//putentityfieldstring puts the data returned by getentityfieldstring back into the entity.
-
-//DP_QC_ENTITYSTRING
-void(string s) loadfromdata = #529;
-void(string s) loadfromfile = #530;
-void(string s) callfunction = #605;
-void(float fh, entity e) writetofile = #606;
-float(string s) isfunction = #607;
-void(entity e, string s) parseentitydata = #608;
-
-//DP_QC_ETOS
-//idea: id Software
-//darkplaces implementation: id Software
-//builtin definitions:
-string(entity ent) etos = #65;
-//description:
-//prints "entity 1" or similar into a string. (this was a Q2 builtin)
-
-//DP_QC_EXTRESPONSEPACKET
-//idea: divVerent
-//darkplaces implementation: divVerent
-//builtin definitions:
-string(void) getextresponse = #624;
-//description:
-//returns a string of the form "\"ipaddress:port\" data...", or the NULL string
-//if no packet was found. Packets can be queued into the client/server by
-//sending a packet starting with "\xFF\xFF\xFF\xFFextResponse " to the
-//listening port.
-
-//DP_QC_FINDCHAIN
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//builtin definitions:
-entity(.string fld, string match) findchain = #402;
-//description:
-//similar to find() but returns a chain of entities like findradius.
-
-//DP_QC_FINDCHAIN_TOFIELD
-//idea: divVerent
-//darkplaces implementation: divVerent
-//builtin definitions:
-entity(.string fld, float match, .entity tofield) findradius_tofield = #22;
-entity(.string fld, string match, .entity tofield) findchain_tofield = #402;
-entity(.string fld, float match, .entity tofield) findchainflags_tofield = #450;
-entity(.string fld, float match, .entity tofield) findchainfloat_tofield = #403;
-//description:
-//similar to findchain() etc, but stores the chain into .tofield instead of .chain
-//actually, the .entity tofield is an optional field of the the existing findchain* functions
-
-//DP_QC_FINDCHAINFLAGS
-//idea: Sajt
-//darkplaces implementation: LordHavoc
-//builtin definitions:
-entity(.float fld, float match) findchainflags = #450;
-//description:
-//similar to findflags() but returns a chain of entities like findradius.
-
-//DP_QC_FINDCHAINFLOAT
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//builtin definitions:
-entity(.entity fld, entity match) findchainentity = #403;
-entity(.float fld, float match) findchainfloat = #403;
-//description:
-//similar to findentity()/findfloat() but returns a chain of entities like findradius.
-
-//DP_QC_FINDFLAGS
-//idea: Sajt
-//darkplaces implementation: LordHavoc
-//builtin definitions:
-entity(entity start, .float fld, float match) findflags = #449;
-//description:
-//finds an entity with the specified flag set in the field, similar to find()
-
-//DP_QC_FINDFLOAT
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//builtin definitions:
-entity(entity start, .entity fld, entity match) findentity = #98;
-entity(entity start, .float fld, float match) findfloat = #98;
-//description:
-//finds an entity or float field value, similar to find(), but for entity and float fields.
-
-//DP_QC_FS_SEARCH
-//idea: Black
-//darkplaces implementation: Black
-//builtin definitions:
-float(string pattern, float caseinsensitive, float quiet) search_begin = #444;
-void(float handle) search_end = #445;
-float(float handle) search_getsize = #446;
-string(float handle, float num) search_getfilename = #447;
-//description:
-//search_begin performs a filename search with the specified pattern (for example "maps/*.bsp") and stores the results in a search slot (minimum of 128 supported by any engine with this extension), the other functions take this returned search slot number, be sure to search_free when done (they are also freed on progs reload).
-//search_end frees a search slot (also done at progs reload).
-//search_getsize returns how many filenames were found.
-//search_getfilename returns a filename from the search.
-
-//DP_QC_GETLIGHT
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//builtin definitions:
-vector(vector org) getlight = #92;
-//description:
-//returns the lighting at the requested location (in color), 0-255 range (can exceed 255).
-
-//DP_QC_GETSURFACE
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//builtin definitions:
-float(entity e, float s) getsurfacenumpoints = #434;
-vector(entity e, float s, float n) getsurfacepoint = #435;
-vector(entity e, float s) getsurfacenormal = #436;
-string(entity e, float s) getsurfacetexture = #437;
-float(entity e, vector p) getsurfacenearpoint = #438;
-vector(entity e, float s, vector p) getsurfaceclippedpoint = #439;
-//description:
-//functions to query surface information.
-
-//DP_QC_GETSURFACEPOINTATTRIBUTE
-//idea: BlackHC
-//darkplaces implementation: BlackHC
-// constants
-float SPA_POSITION = 0;
-float SPA_S_AXIS = 1;
-float SPA_T_AXIS = 2;
-float SPA_R_AXIS = 3; // same as SPA_NORMAL
-float SPA_TEXCOORDS0 = 4;
-float SPA_LIGHTMAP0_TEXCOORDS = 5;
-float SPA_LIGHTMAP0_COLOR = 6;
-//builtin definitions:
-vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
-
-//description:
-//function to query extended information about a point on a certain surface
-
-//DP_QC_GETSURFACETRIANGLE
-//idea: divVerent
-//darkplaces implementation: divVerent
-//builtin definitions:
-float(entity e, float s) getsurfacenumtriangles = #628;
-vector(entity e, float s, float n) getsurfacetriangle = #629;
-//description:
-//function to query triangles of a surface
-
-//DP_QC_GETTAGINFO
-//idea: VorteX, LordHavoc
-//DarkPlaces implementation: VorteX
-//builtin definitions:
-int(entity ent, string tagname) gettagindex = #451;
-vector(entity ent, float tagindex) gettaginfo = #452;
-//description:
-//gettagindex returns the number of a tag on an entity, this number is the same as set by setattachment (in the .tag_index field), allowing the qc to save a little cpu time by keeping the number around if it wishes (this could already be done by calling setattachment and saving off the tag_index).
-//gettaginfo returns the origin of the tag in worldspace and sets v_forward, v_right, and v_up to the current orientation of the tag in worldspace, this automatically resolves all dependencies (attachments, including viewmodelforclient), this means you could fire a shot from a tag on a gun entity attached to the view for example.
-
-//DP_QC_GETTAGINFO_BONEPROPERTIES
-//idea: daemon
-//DarkPlaces implementation: divVerent
-//global definitions:
-float gettaginfo_parent;
-string gettaginfo_name;
-vector gettaginfo_offset;
-vector gettaginfo_forward;
-vector gettaginfo_right;
-vector gettaginfo_up;
-//description:
-//when this extension is present, gettaginfo fills in some globals with info about the bone that had been queried
-//gettaginfo_parent is set to the number of the parent bone, or 0 if it is a root bone
-//gettaginfo_name is set to the name of the bone whose index had been specified in gettaginfo
-//gettaginfo_offset, gettaginfo_forward, gettaginfo_right, gettaginfo_up contain the transformation matrix of the bone relative to its parent. Note that the matrix may contain a scaling component.
-
-//DP_QC_GETTIME
-//idea: tZork
-//darkplaces implementation: tZork, divVerent
-//constant definitions:
-float GETTIME_FRAMESTART = 0; // time of start of frame
-float GETTIME_REALTIME = 1; // current time (may be OS specific)
-float GETTIME_HIRES = 2; // like REALTIME, but may reset between QC invocations and thus can be higher precision
-float GETTIME_UPTIME = 3; // time since start of the engine
-//builtin definitions:
-float(float tmr) gettime = #519;
-//description:
-//some timers to query...
-
-//DP_QC_GETTIME_CDTRACK
-//idea: divVerent
-//darkplaces implementation: divVerent
-//constant definitions:
-float GETTIME_CDTRACK = 4;
-//description:
-//returns the playing time of the current cdtrack when passed to gettime()
-//see DP_END_GETSOUNDTIME for similar functionality but for entity sound channels
-
-//DP_QC_I18N
-//idea: divVerent
-//darkplaces implementation: divVerent
-//description:
-//
-//The engine supports translating by gettext compatible .po files.
-//progs.dat uses progs.dat.<LANGUAGE>.po
-//menu.dat uses menu.dat.<LANGUAGE>.po
-//csprogs.dat uses csprogs.dat.<LANGUAGE>.po
-//
-//To create a string that can be translated, define it as
-//  string dotranslate_FILENOTFOUND = "File not found";
-//Note: if the compiler does constant folding, this will only work if there is
-//no other "File not found" string in the progs!
-//
-//Alternatively, if using the Xonotic patched fteqcc compiler, you can simplify
-//this by using _("File not found") directly in the source code.
-//
-//The language is set by the "prvm_language" cvar: if prvm_language is set to
-//"de", it will read progs.dat.de.po for translating strings in progs.dat.
-//
-//If prvm_language is set to the special name "dump", progs.dat.pot will be
-//written, which is a translation template to be edited by filling out the
-//msgstr entries.
-
-//DP_QC_LOG
-//darkplaces implementation: divVerent
-//builtin definitions:
-float log(float f) = #532;
-//description:
-//logarithm
-
-//DP_QC_MINMAXBOUND
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//builtin definitions:
-float(float a, float b, ...) min = #94;
-float(float a, float b, float c) min3 = #94;
-float(float a, float b, float c, float d) min4 = #94;
-float(float a, float b, float c, float d, float e) min5 = #94;
-float(float a, float b, float c, float d, float e, float f) min6 = #94;
-float(float a, float b, float c, float d, float e, float f, float g) min7 = #94;
-float(float a, float b, float c, float d, float e, float f, float g, float h) min8 = #94;
-float(float a, float b, ...) max = #95;
-float(float a, float b, float c) max3 = #95;
-float(float a, float b, float c, float d) max4 = #95;
-float(float a, float b, float c, float d, float e) max5 = #95;
-float(float a, float b, float c, float d, float e, float f) max6 = #95;
-float(float a, float b, float c, float d, float e, float f, float g) max7 = #95;
-float(float a, float b, float c, float d, float e, float f, float g, float h) max8 = #95;
-float(float minimum, float val, float maximum) bound = #96;
-//description:
-//min returns the lowest of all the supplied numbers.
-//max returns the highest of all the supplied numbers.
-//bound clamps the value to the range and returns it.
-
-//DP_QC_MULTIPLETEMPSTRINGS
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//description:
-//this extension makes all builtins returning tempstrings (ftos for example)
-//cycle through a pool of multiple tempstrings (at least 16), allowing
-//multiple ftos results to be gathered before putting them to use, normal
-//quake only had 1 tempstring, causing many headaches.
-//
-//Note that for longer term storage (or compatibility on engines having
-//FRIK_FILE but not this extension) the FRIK_FILE extension's
-//strzone/strunzone builtins provide similar functionality (slower though).
-//
-//NOTE: this extension is superseded by DP_QC_UNLIMITEDTEMPSTRINGS
-
-//DP_QC_NUM_FOR_EDICT
-//idea: Blub\0
-//darkplaces implementation: Blub\0
-//Function to get the number of an entity - a clean way.
-float(entity num) num_for_edict = #512;
-
-//DP_QC_RANDOMVEC
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//builtin definitions:
-vector() randomvec = #91;
-//description:
-//returns a vector of length < 1, much quicker version of this QC: do {v_x = random()*2-1;v_y = random()*2-1;v_z = random()*2-1;} while(vlen(v) > 1)
-
-//DP_QC_SINCOSSQRTPOW
-//idea: id Software, LordHavoc
-//darkplaces implementation: id Software, LordHavoc
-//builtin definitions:
-float(float val) sin = #60;
-float(float val) cos = #61;
-float(float val) sqrt = #62;
-float(float a, float b) pow = #97;
-//description:
-//useful math functions, sine of val, cosine of val, square root of val, and raise a to power b, respectively.
-
-//DP_QC_SPRINTF
-//idea: divVerent
-//darkplaces implementation: divVerent
-//builtin definitions:
-string(string format, ...) sprintf = #627;
-//description:
-//you know sprintf :P
-//supported stuff:
-//  %
-//  optional: <argpos>$ for the argument to format
-//  flags: #0- +
-//  optional: <width>, *, or *<argpos>$ for the field width
-//  optional: .<precision>, .*, or .*<argpos>$ for the precision
-//  length modifiers: h for forcing a float, l for forcing an int/entity (by default, %d etc. cast a float to int)
-//  conversions:
-//    d takes a float if no length is specified or h is, and an int/entity if l is specified as length, and cast it to an int
-//    i takes an int/entity if no length is specified or i is, and a float if h is specified as length, and cast it to an int
-//    ouxXc take a float if no length is specified or h is, and an int/entity if l is specified as length, and cast it to an unsigned int
-//    eEfFgG take a float if no length is specified or h is, and an int/entity if l is specified as length, and cast it to a double
-//    s takes a string
-//    vV takes a vector, and processes the three components as if it were a gG for all three components, separated by space
-//    For conversions s and c, the flag # makes precision and width interpreted
-//      as byte count, by default it is interpreted as character count in UTF-8
-//      enabled engines. No other conversions can create wide characters, and #
-//      has another meaning in these. When in character count mode, color codes
-//      are ignored. To get UTF-8 semantics WITHOUT color code parsing, use
-//      the + flag.
-
-//DP_QC_STRFTIME
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//builtin definitions:
-string(float uselocaltime, string format, ...) strftime = #478;
-//description:
-//provides the ability to get the local (in your timezone) or world (Universal Coordinated Time) time as a string using the formatting of your choice:
-//example: "%Y-%m-%d %H:%M:%S"   (result looks like: 2007-02-08 01:03:15)
-//note: "%F %T" gives the same result as "%Y-%m-%d %H:%M:%S" (ISO 8601 date format and 24-hour time)
-//for more format codes please do a web search for strftime 3 and you should find the man(3) pages for this standard C function.
-//
-//practical uses:
-//changing day/night cycle (shops closing, monsters going on the prowl) in an RPG, for this you probably want to use s = strftime(true, "%H");hour = stof(s);
-//printing current date/time for competitive multiplayer games, such as the beginning/end of each round in real world time.
-//activating eastereggs in singleplayer games on certain dates.
-//
-//note: some codes such as %x and %X use your locale settings and thus may not make sense to international users, it is not advisable to use these as the server and clients may be in different countries.
-//note: if you display local time to a player, it would be a good idea to note whether it is local time using a string like "%F %T (local)", and otherwise use "%F %T (UTC)".
-//note: be aware that if the game is saved and reloaded a week later the date and time will be different, so if activating eastereggs in a singleplayer game or something you may want to only check when a level is loaded and then keep the same easteregg state throughout the level so that the easteregg does not deactivate when reloading from a savegame (also be aware that precaches should not depend on such date/time code because reloading a savegame often scrambles the precaches if so!).
-//note: this function can return a NULL string (you can check for it with if (!s)) if the localtime/gmtime functions returned NULL in the engine code, such as if those functions don't work on this platform (consoles perhaps?), so be aware that this may return nothing.
-
-//DP_QC_STRINGCOLORFUNCTIONS
-//idea: Dresk
-//darkplaces implementation: Dresk
-//builtin definitions:
-float(string s) strlennocol = #476; // returns how many characters are in a string, minus color codes
-string(string s) strdecolorize = #477; // returns a string minus the color codes of the string provided
-//description:
-//provides additional functionality to strings by supporting functions that isolate and identify strings with color codes
-
-//DP_QC_STRING_CASE_FUNCTIONS
-//idea: Dresk
-//darkplaces implementation: LordHavoc / Dresk
-//builtin definitions:
-string(string s) strtolower = #480; // returns the passed in string in pure lowercase form
-string(string s) strtoupper = #481; // returns the passed in string in pure uppercase form
-//description:
-//provides simple string uppercase and lowercase functions
-
-//DP_QC_TOKENIZEBYSEPARATOR
-//idea: Electro, SavageX, LordHavoc
-//darkplaces implementation: LordHavoc
-//builtin definitions:
-int(string s, string separator1, ...) tokenizebyseparator = #479;
-//description:
-//this function returns tokens separated by any of the supplied separator strings, example:
-//numnumbers = tokenizebyseparator("10.2.3.4", ".");
-//returns 4 and the tokens are "10" "2" "3" "4"
-//possibly useful for parsing IPv4 addresses (such as "1.2.3.4") and IPv6 addresses (such as "[1234:5678:9abc:def0:1234:5678:9abc:def0]:26000")
-
-//DP_QC_TOKENIZE_CONSOLE
-//idea: divVerent
-//darkplaces implementation: divVerent
-//builtin definitions:
-int(string s) tokenize_console = #514;
-int(float i) argv_start_index = #515;
-int(float i) argv_end_index = #516;
-//description:
-//this function returns tokens separated just like the console does
-//also, functions are provided to get the index of the first and last character of each token in the original string
-//Passing negative values to them, or to argv, will be treated as indexes from the LAST token (like lists work in Perl). So argv(-1) will return the LAST token.
-
-//DP_QC_TRACEBOX
-//idea: id Software
-//darkplaces implementation: id Software
-//builtin definitions:
-void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox = #90;
-//description:
-//similar to traceline but much more useful, traces a box of the size specified (technical note: in quake1 and halflife bsp maps the mins and maxs will be rounded up to one of the hull sizes, quake3 bsp does not have this problem, this is the case with normal moving entities as well).
-
-//DP_QC_TRACETOSS
-//idea: id Software
-//darkplaces implementation: id Software
-//builtin definitions:
-void(entity ent, entity ignore) tracetoss = #64;
-//description:
-//simulates movement of the entity as if it is MOVETYPE_TOSS and starting with it's current state (location, velocity, etc), returns relevant trace_ variables (trace_fraction is always 0, all other values are supported - trace_ent, trace_endpos, trace_plane_normal), does not actually alter the entity.
-
-//DP_QC_TRACE_MOVETYPE_HITMODEL
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//constant definitions:
-float MOVE_HITMODEL = 4;
-//description:
-//allows traces to hit alias models (not sprites!) instead of entity boxes, use as the nomonsters parameter to trace functions, note that you can hit invisible model entities (alpha < 0 or EF_NODRAW or model "", it only checks modelindex)
-
-//DP_QC_TRACE_MOVETYPE_WORLDONLY
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//constant definitions:
-float MOVE_WORLDONLY = 3;
-//description:
-//allows traces to hit only world (ignoring all entities, unlike MOVE_NOMONSTERS which hits all bmodels), use as the nomonsters parameter to trace functions
-
-//DP_QC_UNLIMITEDTEMPSTRINGS
-//idea: divVerent
-//darkplaces implementation: LordHavoc
-//description:
-//this extension alters Quake behavior such that instead of reusing a single
-//tempstring (or multiple) there are an unlimited number of tempstrings, which
-//are removed only when a QC function invoked by the engine returns,
-//eliminating almost all imaginable concerns with string handling in QuakeC.
-//
-//in short:
-//you can now use and abuse tempstrings as much as you like, you still have to
-//use strzone (FRIK_FILE) for permanent storage however.
-//
-//
-//
-//implementation notes for other engine coders:
-//these tempstrings are expected to be stored in a contiguous buffer in memory
-//which may be fixed size or controlled by a cvar, or automatically grown on
-//demand (in the case of DarkPlaces).
-//
-//this concept is similar to quake's Zone system, however these are all freed
-//when the QC interpreter returns.
-//
-//this is basically a poor man's garbage collection system for strings.
-
-//DP_QC_VECTOANGLES_WITH_ROLL
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//builtin definitions:
-vector(vector forward, vector up) vectoangles2 = #51; // same number as vectoangles
-//description:
-//variant of vectoangles that takes an up vector to calculate roll angle (also uses this to calculate yaw correctly if the forward is straight up or straight down)
-//note: just like normal vectoangles you need to negate the pitch of the returned angles if you want to feed them to makevectors or assign to self.v_angle
-
-//DP_QC_VECTORVECTORS
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//builtin definitions:
-void(vector dir) vectorvectors = #432;
-//description:
-//creates v_forward, v_right, and v_up vectors given a forward vector, similar to makevectors except it takes a forward direction vector instead of angles.
-
-//DP_QC_WHICHPACK
-//idea: divVerent
-//darkplaces implementation: divVerent
-//builtin definitions:
-string(string filename) whichpack = #503;
-//description:
-//returns the name of the pak/pk3/whatever containing the given file, in the same path space as FRIK_FILE functions use (that is, possibly with a path name prefix)
-
-//DP_QC_URI_ESCAPE
-//idea: divVerent
-//darkplaces implementation: divVerent
-//URI::Escape's functionality
-string(string in) uri_escape = #510;
-string(string in) uri_unescape = #511;
-
-//DP_QC_URI_GET
-//idea: divVerent
-//darkplaces implementation: divVerent
-//loads text from an URL into a string
-//returns 1 on success of initiation, 0 if there are too many concurrent
-//connections already or if the URL is invalid
-//the following callback will receive the data and MUST exist!
-//  void(float id, float status, string data) URI_Get_Callback;
-//status is either
-//  negative for an internal error,
-//  0 for success, or
-//  the HTTP response code on server error (e.g. 404)
-//if 1 is returned by uri_get, the callback will be called in the future
-float(string url, float id) uri_get = #513;
-
-//DP_QC_URI_POST
-//idea: divVerent
-//darkplaces implementation: divVerent
-//loads text from an URL into a string after POSTing via HTTP
-//works like uri_get, but uri_post sends data with Content-Type: content_type to the server
-//and uri_post sends the string buffer buf, joined using the delimiter delim
-float(string url, float id, string content_type, string data) uri_post = #513;
-float(string url, float id, string content_type, string delim, float buf) uri_postbuf = #513;
-
-//DP_SKELETONOBJECTS
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//description:
-//this extension indicates that FTE_CSQC_SKELETONOBJECTS functionality is available in server QC (as well as CSQC).
-
-//DP_SV_SPAWNFUNC_PREFIX
-//idea: divVerent
-//darkplaces implementation: divVerent
-//Make functions whose name start with spawnfunc_ take precedence as spawn function for loading entities.
-//Useful if you have a field ammo_shells (required in any Quake mod) but want to support spawn functions called ammo_shells (like in Q3A).
-//Optionally, you can declare a global "float require_spawnfunc_prefix;" which will require ANY spawn function to start with that prefix.
-
-
-//DP_QUAKE2_MODEL
-//idea: quake community
-//darkplaces implementation: LordHavoc
-//description:
-//shows that the engine supports Quake2 .md2 files.
-
-//DP_QUAKE2_SPRITE
-//idea: LordHavoc
-//darkplaces implementation: Elric
-//description:
-//shows that the engine supports Quake2 .sp2 files.
-
-//DP_QUAKE3_MAP
-//idea: quake community
-//darkplaces implementation: LordHavoc
-//description:
-//shows that the engine supports Quake3 .bsp files.
-
-//DP_QUAKE3_MODEL
-//idea: quake community
-//darkplaces implementation: LordHavoc
-//description:
-//shows that the engine supports Quake3 .md3 files.
-
-//DP_REGISTERCVAR
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//builtin definitions:
-float(string name, string value) registercvar = #93;
-//description:
-//adds a new console cvar to the server console (in singleplayer this is the player's console), the cvar exists until the mod is unloaded or the game quits.
-//NOTE: DP_CON_SET is much better.
-
-//DP_SND_DIRECTIONLESSATTNNONE
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//description:
-//make sounds with ATTN_NONE have no spatialization (enabling easy use as music sources).
-
-//DP_SND_FAKETRACKS
-//idea: requested
-
-//darkplaces implementation: Elric
-//description:
-//the engine plays sound/cdtracks/track001.wav instead of cd track 1 and so on if found, this allows games and mods to have music tracks without using ambientsound.
-//Note: also plays .ogg with DP_SND_OGGVORBIS extension.
-
-//DP_SND_SOUND7_WIP1
-//DP_SND_SOUND7_WIP2
-//idea: divVerent
-//darkplaces implementation: divVerent
-//builtin definitions:
-void(entity e, float chan, string samp, float vol, float atten, float speed, float flags) sound7 = #8;
-float SOUNDFLAG_RELIABLE = 1;
-//description:
-//plays a sound, with some more flags
-//extensions to sound():
-//- channel may be in the range from -128 to 127; channels -128 to 0 are "auto",
-//  i.e. support multiple sounds at once, but cannot be stopped/restarted
-//- a value 0 in the speed parameter means no change; otherwise, it is a
-//  percentage of playback speed ("pitch shifting"). 100 is normal pitch, 50 is
-//  half speed, 200 is double speed, etc. (DP_SND_SOUND7_WIP2)
-//- the flag SOUNDFLAG_RELIABLE can be specified, which makes the sound send
-//  to MSG_ALL (reliable) instead of MSG_BROADCAST (unreliable, default);
-//  similarily, SOUNDFLAG_RELIABLE_TO_ONE sends to MSG_ONE
-//- channel 0 is controlled by snd_channel0volume; channel 1 and -1 by
-//  snd_channel1volume, etc. (so, a channel shares the cvar with its respective
-//  auto-channel); however, the mod MUST define snd_channel8volume and upwards
-//  in default.cfg if they are to be used, as the engine does not create them
-//  to not litter the cvar list
-//- this extension applies to CSQC as well; CSQC_Event_Sound will get speed and
-//  flags as extra 7th and 8th argument
-//- WIP2 ideas: SOUNDFLAG_RELIABLE_TO_ONE, SOUNDFLAG_NOPHS, SOUNDFLAG_FORCELOOP
-//- NOTE: to check for this, ALSO OR a check with DP_SND_SOUND7 to also support
-//  the finished extension once done
-
-//DP_SND_OGGVORBIS
-//idea: Transfusion
-//darkplaces implementation: Elric
-//description:
-//the engine supports loading Ogg Vorbis sound files.  Use either the .ogg filename directly, or a .wav of the same name (will try to load the .wav first and then .ogg).
-
-//DP_SND_STEREOWAV
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//description:
-//the engine supports stereo WAV files.  (useful with DP_SND_DIRECTIONLESSATTNNONE for music)
-
-//DP_SND_GETSOUNDTIME
-//idea: VorteX
-//darkplaces implementation: VorteX
-//constant definitions:
-float(entity e, float channel) getsoundtime = #533; // get currently sound playing position on entity channel, -1 if not playing or error
-float(string sample) soundlength = #534; // returns length of sound sample in seconds, -1 on error (sound not precached, sound system not initialized etc.)
-//description: provides opportunity to query length of sound samples and realtime tracking of sound playing on entities (similar to DP_GETTIME_CDTRACK)
-//note: beware dedicated server not running sound engine at all, so in dedicated mode this builtins will not work in server progs
-//note also: menu progs not supporting getsoundtime() (will give a warning) since it has no sound playing on entities
-//examples of use:
-//  - QC-driven looped sounds
-//  - QC events when sound playing is finished
-//  - toggleable ambientsounds
-//  - subtitles
-
-//DP_VIDEO_DPV
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//console commands:
-//  playvideo <videoname> - start playing video
-//  stopvideo - stops current video
-//description: indicated that engine support playing videos in DPV format
-
-//DP_VIDEO_SUBTITLES
-//idea: VorteX
-//darkplaces implementation: VorteX
-//cvars:
-//  cl_video_subtitles - toggles subtitles showing
-//  cl_video_subtitles_lines - how many lines to reserve for subtitles
-//  cl_video_subtitles_textsize - font size
-//console commands:
-//  playvideo <videoname> <custom_subtitles_file> - start playing video
-//  stopvideo - stops current video
-//description: indicates that engine support subtitles on videos
-//subtitles stored in external text files, each video file has it's default subtitles file ( <videoname>.dpsubs )
-//example: for video/act1.dpv default subtitles file will be video/act1.dpsubs
-//also video could be played with custom subtitles file by utilizing second parm of playvideo command
-//syntax of .dpsubs files: each line in .dpsubs file defines 1 subtitle, there are three tokens:
-//   <start> <end> "string"
-//   start: subtitle start time in seconds
-//     end: subtitle time-to-show in seconds, if 0 - subtitle will be showed until next subtitle is started, 
-//          if below 0 - show until next subtitles minus this number of seconds
-//    text: subtitle text, color codes (Q3-style and ^xRGB) are allowed
-//example of subtitle file:
-//   3 0       "Vengeance! Vengeance for my eternity of suffering!"
-//   9 0       "Whelp! As if you knew what eternity was!"
-//   13        0       "Grovel before your true master."
-//   17        0       "Never!" 
-//   18        7       "I'll hack you from crotch to gizzard and feed what's left of you to your brides..."
-
-//DP_SOLIDCORPSE
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//solid definitions:
-float SOLID_CORPSE = 5;
-//description:
-//the entity will not collide with SOLID_CORPSE and SOLID_SLIDEBOX entities (and likewise they will not collide with it), this is useful if you want dead bodies that are shootable but do not obstruct movement by players and monsters, note that if you traceline with a SOLID_SLIDEBOX entity as the ignoreent, it will ignore SOLID_CORPSE entities, this is desirable for visibility and movement traces, but not for bullets, for the traceline to hit SOLID_CORPSE you must temporarily force the player (or whatever) to SOLID_BBOX and then restore to SOLID_SLIDEBOX after the traceline.
-
-//DP_SPRITE32
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//description:
-//the engine supports .spr32 sprites.
-
-//DP_SV_BOTCLIENT
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//constants:
-float CLIENTTYPE_DISCONNECTED = 0;
-float CLIENTTYPE_REAL = 1;
-float CLIENTTYPE_BOT = 2;
-float CLIENTTYPE_NOTACLIENT = 3;
-//builtin definitions:
-entity() spawnclient = #454; // like spawn but for client slots (also calls relevant connect/spawn functions), returns world if no clients available
-float(entity clent) clienttype = #455; // returns one of the CLIENTTYPE_* constants
-//description:
-//spawns a client with no network connection, to allow bots to use client slots with no hacks.
-//How to use:
-/*
-       // to spawn a bot
-       local entity oldself;
-       oldself = self;
-       self = spawnclient();
-       if (!self)
-       {
-               bprint("Can not add bot, server full.\n");
-               self = oldself;
-               return;
-       }
-       self.netname = "Yoyobot";
-       self.clientcolors = 12 * 16 + 4; // yellow (12) shirt and red (4) pants
-       ClientConnect();
-       PutClientInServer();
-       self = oldself;
-
-       // to remove all bots
-       local entity head;
-       head = find(world, classname, "player");
-       while (head)
-       {
-               if (clienttype(head) == CLIENTTYPE_BOT)
-                       dropclient(head);
-               head = find(head, classname, "player");
-       }
-
-       // to identify if a client is a bot (for example in PlayerPreThink)
-       if (clienttype(self) == CLIENTTYPE_BOT)
-               botthink();
-*/
-//see also DP_SV_CLIENTCOLORS DP_SV_CLIENTNAME DP_SV_DROPCLIENT
-//How it works:
-//creates a new client, calls SetNewParms and stores the parms, and returns the client.
-//this intentionally does not call SV_SendServerinfo to allow the QuakeC a chance to set the netname and clientcolors fields before actually spawning the bot by calling ClientConnect and PutClientInServer manually
-//on level change ClientConnect and PutClientInServer are called by the engine to spawn in the bot (this is why clienttype() exists to tell you on the next level what type of client this is).
-//parms work the same on bot clients as they do on real clients, and do carry from level to level
-
-//DP_SV_BOUNCEFACTOR
-//idea: divVerent
-//darkplaces implementation: divVerent
-//field definitions:
-.float bouncefactor; // velocity multiplier after a bounce
-.float bouncestop; // bounce stops if velocity to bounce plane is < bouncestop * gravity AFTER the bounce
-//description:
-//allows qc to customize MOVETYPE_BOUNCE a bit
-
-//DP_SV_CLIENTCAMERA
-//idea: LordHavoc, others
-//darkplaces implementation: Black
-//field definitions:
-.entity clientcamera; // override camera entity
-//description:
-//allows another entity to be the camera for a client, for example a remote camera, this is similar to sending svc_setview manually except that it also changes the network culling appropriately.
-
-//DP_SV_CLIENTCOLORS
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//field definitions:
-.float clientcolors; // colors of the client (format: pants + shirt * 16)
-//description:
-//allows qc to read and modify the client colors associated with a client entity (not particularly useful on other entities), and automatically sends out any appropriate network updates if changed
-
-//DP_SV_CLIENTNAME
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//description:
-//allows qc to modify the client's .netname, and automatically sends out any appropriate network updates if changed
-
-//DP_SV_CUSTOMIZEENTITYFORCLIENT
-//idea: LordHavoc
-//darkplaces implementation: [515] and LordHavoc
-//field definitions:
-.float() customizeentityforclient; // self = this entity, other = client entity
-//description:
-//allows qc to modify an entity before it is sent to each client, the function returns true if it should send, false if it should not, and is fully capable of editing the entity's fields, this allows cloaked players to appear less transparent to their teammates, navigation markers to only show to their team, etc
-//tips on writing customize functions:
-//it is a good idea to return false early in the function if possible to reduce cpu usage, because this function may be called many thousands of times per frame if there are many customized entities on a 64+ player server.
-//you are free to change anything in self, but please do not change any other entities (the results may be very inconsistent).
-//example ideas for use of this extension:
-//making icons over teammates' heads which are only visible to teammates.  for exasmple: float() playericon_customizeentityforclient = {return self.owner.team == other.team;};
-//making cloaked players more visible to their teammates than their enemies.  for example: float() player_customizeentityforclient = {if (self.items & IT_CLOAKING) {if (self.team == other.team) self.alpha = 0.6;else self.alpha = 0.1;} return true;};
-//making explosion models that face the viewer (does not work well with chase_active).  for example: float() explosion_customizeentityforclient = {self.angles = vectoangles(other.origin + other.view_ofs - self.origin);self.angles_x = 0 - self.angles_x;};
-//implementation notes:
-//entity customization is done before per-client culling (visibility for instance) because the entity may be doing setorigin to display itself in different locations on different clients, may be altering its .modelindex, .effects and other fields important to culling, so customized entities increase cpu usage (non-customized entities can use all the early culling they want however, as they are not changing on a per client basis).
-
-//DP_SV_DISCARDABLEDEMO
-//idea: parasti
-//darkplaces implementation: parasti
-//field definitions:
-.float discardabledemo;
-//description:
-//when this field is set to a non-zero value on a player entity, a possibly recorded server-side demo for the player is discarded
-//Note that this extension only works if:
-//  auto demos are enabled (the cvar sv_autodemo_perclient is set)
-//  discarding demos is enabled (the cvar sv_autodemo_perclient_discardable is set)
-
-//DP_SV_DRAWONLYTOCLIENT
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//field definitions:
-.entity drawonlytoclient;
-//description:
-//the entity is only visible to the specified client.
-
-//DP_SV_DROPCLIENT
-//idea: FrikaC
-//darkplaces implementation: LordHavoc
-//builtin definitions:
-void(entity clent) dropclient = #453;
-//description:
-//causes the server to immediately drop the client, more reliable than stuffcmd(clent, "disconnect\n"); which could be intentionally ignored by the client engine
-
-//DP_SV_EFFECT
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//builtin definitions:
-void(vector org, string modelname, float startframe, float endframe, float framerate) effect = #404;
-//SVC definitions:
-//float svc_effect = #52; // [vector] org [byte] modelindex [byte] startframe [byte] framecount [byte] framerate
-//float svc_effect2 = #53; // [vector] org [short] modelindex [byte] startframe [byte] framecount [byte] framerate
-//description:
-//clientside playback of simple custom sprite effects (explosion sprites, etc).
-
-//DP_SV_ENTITYCONTENTSTRANSITION
-//idea: Dresk
-//darkplaces implementation: Dresk
-//field definitions:
-.void(float nOriginalContents, float nNewContents) contentstransition;
-//description:
-//This field function, when provided, is triggered on an entity when the contents (ie. liquid / water / etc) is changed.
-//The first parameter provides the entities original contents, prior to the transition.  The second parameter provides the new contents.
-//NOTE: If this field function is provided on an entity, the standard watersplash sound IS SUPPRESSED to allow for authors to create their own transition sounds.
-
-//DP_SV_MOVETYPESTEP_LANDEVENT
-//idea: Dresk
-//darkplaces implementation: Dresk
-//field definitions:
-.void(vector vImpactVelocity) movetypesteplandevent;
-//description:
-//This field function, when provided, is triggered on a MOVETYPE_STEP entity when it experiences  "land event".
-// The standard engine behavior for this event is to play the sv_sound_land CVar sound.
-//The parameter provides the velocity of the entity at the time of the impact.  The z value may therefore be used to calculate how "hard" the entity struck the surface.
-//NOTE: If this field function is provided on a MOVETYPE_STEP entity, the standard sv_sound_land sound IS SUPPRESSED to allow for authors to create their own feedback.
-
-//DP_SV_POINTSOUND
-//idea: Dresk
-//darkplaces implementation: Dresk
-//builtin definitions:
-void(vector origin, string sample, float volume, float attenuation) pointsound = #483;
-//description:
-//Similar to the standard QC sound function, this function takes an origin instead of an entity and omits the channel parameter.
-// This allows sounds to be played at arbitrary origins without spawning entities.
-
-//DP_SV_ONENTITYNOSPAWNFUNCTION
-//idea: Dresk
-//darkplaces implementation: Dresk
-//engine-called QC prototypes:
-//void() SV_OnEntityNoSpawnFunction;
-//description:
-// This function is called whenever an entity on the server has no spawn function, and therefore has no defined QC behavior.
-// You may as such dictate the behavior as to what happens to the entity.
-// To mimic the engine's default behavior, simply call remove(self).
-
-//DP_SV_ONENTITYPREPOSTSPAWNFUNCTION
-//idea: divVerent
-//darkplaces implementation: divVerent
-//engine-called QC prototypes:
-//void() SV_OnEntityPreSpawnFunction;
-//void() SV_OnEntityPostSpawnFunction;
-//description:
-// These functions are called BEFORE or AFTER an entity is spawned the regular way.
-// You may as such dictate the behavior as to what happens to the entity.
-// SV_OnEntityPreSpawnFunction is called before even looking for the spawn function, so you can even change its classname in there. If it remove()s the entity, the spawn function will not be looked for.
-// SV_OnEntityPostSpawnFunction is called ONLY after its spawn function or SV_OnEntityNoSpawnFunction was called, and skipped if the entity got removed by either.
-
-//DP_SV_MODELFLAGS_AS_EFFECTS
-//idea: LordHavoc, Dresk
-//darkplaces implementation: LordHavoc
-//field definitions:
-.int modelflags;
-//constant definitions:
-float EF_NOMODELFLAGS = 8388608; // ignore any effects in a model file and substitute your own
-float MF_ROCKET  =   1; // leave a trail
-float MF_GRENADE =   2; // leave a trail
-float MF_GIB     =   4; // leave a trail
-float MF_ROTATE  =   8; // rotate (bonus items)
-float MF_TRACER  =  16; // green split trail
-float MF_ZOMGIB  =  32; // small blood trail
-float MF_TRACER2 =  64; // orange split trail
-float MF_TRACER3 = 128; // purple trail
-//description:
-//this extension allows model flags to be specified on entities so you can add a rocket trail and glow to any entity, etc.
-//setting any of these will override the flags the model already has, to disable the model's flags without supplying any of your own you must use EF_NOMODELFLAGS.
-//
-//silly example modification #1 to W_FireRocket in weapons.qc:
-//missile.effects = EF_NOMODELFLAGS; // rocket without a glow/fire trail
-//silly example modification #2 to W_FireRocket in weapons.qc:
-//missile.modelflags = MF_GIB; // leave a blood trail instead of glow/fire trail
-//
-//note: you can not combine multiple kinds of trail, only one of them will be active, you can combine MF_ROTATE and the other MF_ flags however, and using EF_NOMODELFLAGS along with these does no harm.
-//
-//note to engine coders: they are internally encoded in the protocol as extra EF_ flags (shift the values left 24 bits and send them in the protocol that way), so no protocol change was required (however 32bit effects is a protocol extension itself), within the engine they are referred to as EF_ for the 24bit shifted values.
-
-//DP_SV_NETADDRESS
-//idea: Dresk
-//darkplaces implementation: Dresk
-//field definitions:
-.string netaddress;
-//description:
-// provides the netaddress of the associated entity (ie. 127.0.0.1) and "null/botclient" if the netconnection of the entity is invalid
-
-//DP_SV_NODRAWTOCLIENT
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//field definitions:
-.entity nodrawtoclient;
-//description:
-//the entity is not visible to the specified client.
-
-//DP_SV_PING
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//field definitions:
-.float ping;
-//description:
-//continuously updated field indicating client's ping (based on average of last 16 packet time differences).
-
-//DP_SV_PING_PACKETLOSS
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//field definitions:
-.float ping_packetloss;
-.float ping_movementloss;
-//description:
-//continuously updated field indicating client's packet loss, and movement loss (i.e. packet loss affecting player movement).
-
-//DP_SV_POINTPARTICLES
-//idea: Spike
-//darkplaces implementation: LordHavoc
-//function definitions:
-int(string effectname) particleeffectnum = #335; // same as in CSQC
-void(entity ent, float effectnum, vector start, vector end) trailparticles = #336; // same as in CSQC
-void(float effectnum, vector org, vector vel, float howmany) pointparticles = #337; // same as in CSQC
-//SVC definitions:
-//float svc_trailparticles = 60; // [short] entnum [short] effectnum [vector] start [vector] end
-//float svc_pointparticles = 61; // [short] effectnum [vector] start [vector] velocity [short] count
-//float svc_pointparticles1 = 62; // [short] effectnum [vector] start, same as svc_pointparticles except velocity is zero and count is 1
-//description:
-//provides the ability to spawn non-standard particle effects, typically these are defined in a particle effect information file such as effectinfo.txt in darkplaces.
-//this is a port of particle effect features from clientside QC (EXT_CSQC) to server QC, as these effects are potentially useful to all games even if they do not make use of EXT_CSQC.
-//warning: server must have same order of effects in effectinfo.txt as client does or the numbers would not match up, except for standard quake effects which are always the same numbers.
-
-//DP_SV_PUNCHVECTOR
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//field definitions:
-.vector punchvector;
-//description:
-//offsets client view in worldspace, similar to view_ofs but all 3 components are used and are sent with at least 8 bits of fraction, this allows the view to be kicked around by damage or hard landings or whatever else, note that unlike punchangle this is not faded over time, it is up to the mod to fade it (see also DP_SV_PLAYERPHYSICS).
-
-//DP_SV_PLAYERPHYSICS
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//field definitions:
-.vector movement;
-//cvar definitions:
-//"sv_playerphysicsqc" (0/1, default 1, allows user to disable qc player physics)
-//engine-called QC prototypes:
-//void() SV_PlayerPhysics;
-//description:
-//.movement vector contains the movement input from the player, allowing QC to do as it wishs with the input, and SV_PlayerPhysics will completely replace the player physics if present (works for all MOVETYPE's), see darkplaces mod source for example of this function (in playermovement.qc, adds HalfLife ladders support, as well as acceleration/deceleration while airborn (rather than the quake sudden-stop while airborn), and simplifies the physics a bit)
-
-//DP_PHYSICS_ODE
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//globals:
-//new movetypes:
-const float MOVETYPE_PHYSICS = 32; // need to be set before any physics_* builtins applied
-//new solid types (deprecated):
-const float SOLID_PHYSICS_BOX = 32;
-const float SOLID_PHYSICS_SPHERE = 33;
-const float SOLID_PHYSICS_CAPSULE = 34;
-const float SOLID_PHYSICS_TRIMESH = 35;
-const float SOLID_PHYSICS_CYLINDER = 36;
-//geometry types:
-const float GEOMTYPE_NONE = -1;       // entity will be entirely skipped by ODE
-const float GEOMTYPE_SOLID = 0;       // geometry type will be set based on .solid field
-const float GEOMTYPE_BOX = 1;         // entity bound box
-const float GEOMTYPE_SPHERE = 2;      // sphere with radius picked from x axis of entity bound box
-const float GEOMTYPE_CAPSULE = 3;     // with leading axis automatically determined from longest one, radius is picked as minimal of the rest 2 axes
-const float GEOMTYPE_TRIMESH = 4;     // triangle mesh
-const float GEOMTYPE_CYLINDER = 5;    // like capsule but not capped
-                                      // note that ODE's builtin cylinder support is experimental, somewhat bugged and unfinished (no cylinder-cylinder collision)
-                                                                         // to use properly working cylinder should build ODE with LIBCCD extension
-const float GEOMTYPE_CAPSULE_X = 6;   // capsule with fixed leading axis
-const float GEOMTYPE_CAPSULE_Y = 7;
-const float GEOMTYPE_CAPSULE_Z = 8;
-const float GEOMTYPE_CYLINDER_X        = 9;  // cylinder with fixed leading axis
-const float GEOMTYPE_CYLINDER_Y        = 10;
-const float GEOMTYPE_CYLINDER_Z        = 11;
-//joint types:
-const float JOINTTYPE_NONE = 0;
-const float JOINTTYPE_POINT = 1;
-const float JOINTTYPE_HINGE = 2;
-const float JOINTTYPE_SLIDER = 3;
-const float JOINTTYPE_UNIVERSAL = 4;
-const float JOINTTYPE_HINGE2 = 5;
-const float JOINTTYPE_FIXED = -1;
-//force types:
-const float FORCETYPE_NONE = 0;
-const float FORCETYPE_FORCE = 1; // applied at center of mass
-const float FORCETYPE_FORCEATPOS = 2;
-const float FORCETYPE_TORQUE = 3;
-// common joint properties:
-// .entity aiment; // connected objects
-// .entity enemy; // connected objects, forces
-// .vector movedir;
-//   for a spring:
-//     movedir_x = spring constant (force multiplier, must be > 0)
-//     movedir_y = spring dampening constant to prevent oscillation (must be > 0)
-//     movedir_z = spring stop position (+/-)
-//   for a motor:
-//     movedir_x = desired motor velocity
-//     movedir_y = -1 * max motor force to use
-//     movedir_z = stop position (+/-), set to 0 for no stop
-//   note that ODE does not support both in one anyway
-//   for a force:
-//     force vector to apply
-//field definitions:
-.float  geomtype;     // see GEOMTYPE_*, a more correct way to set collision shape, allows to set SOLID_CORPSE and trimesh collisions
-.float  maxcontacts;  // maximum number of contacts to make for this object, lesser = faster (but setting it too low will could make object pass though walls), default is 16, maximum is 32
-.float  mass;         // ODE mass, standart value is 1
-.vector massofs;      // offsets a mass center out of object center, if not set a center of model bounds is used
-.float  friction;     // a friction of object, get multiplied by second objects's friction on contact
-.float  bouncefactor;
-.float  bouncestop; 
-.float  jointtype;    // type of joint
-.float  forcetype;    // type of force
-.float  erp;          // error restitution parameter, makes ODE solver attempt to fix errors in contacts, 
-                      // bringing together 2 joints or fixing object being stuch in other object, 
-                                 // a value of 0.1 will fix slightly, a value of 1.0 attempts to fix whole error in one frame
-                                 // use with care as high values makes system unstable and likely to explode
-//builtin definitions:
-void(entity e, float physics_enabled) physics_enable = #540; // enable or disable physics on object
-void(entity e, vector force, vector force_pos) physics_addforce = #541; // deprecated, apply a force from certain origin, length of force vector is power of force
-void(entity e, vector torque) physics_addtorque = #542; // deprecated, add relative torque
-//description: provides Open Dynamics Engine support, requires extenal dll to be present or engine compiled with statical link option
-//be sure to checkextension for it to know if library is loaded and ready, also to enable physics set "physics_ode" cvar to 1
-//note: this extension is highly experimental and may be unstable
-
-//DP_SV_PRINT
-//idea: id Software (QuakeWorld Server)
-//darkplaces implementation: Black, LordHavoc
-void(string s, ...) print = #339; // same number as in EXT_CSQC
-//description:
-//this is identical to dprint except that it always prints regardless of the developer cvar.
-
-//DP_SV_PRECACHEANYTIME
-//idea: id Software (Quake2)
-//darkplaces implementation: LordHavoc
-//description:
-//this extension allows precache_model and precache_sound (and any variants) to be used during the game (with automatic messages to clients to precache the new model/sound indices), also setmodel/sound/ambientsound can be called without precaching first (they will cause an automatic precache).
-
-//DP_SV_QCSTATUS
-//idea: divVerent
-//darkplaces implementation: divVerent
-//1. A global variable
-string worldstatus;
-//Its content is set as "qcstatus" field in the rules.
-//It may be at most 255 characters, and must not contain newlines or backslashes.
-//2. A per-client field
-.string clientstatus;
-//It is sent instead of the "frags" in status responses.
-//It should always be set in a way so that stof(player.clientstatus) is a meaningful score value. Other info may be appended. If used this way, the cvar sv_status_use_qcstatus may be set to 1, and then this value will replace the frags in "status".
-//Currently, qstat does not support this and will not show player info if used and set to anything other than ftos(some integer).
-
-//DP_SV_ROTATINGBMODEL
-//idea: id Software
-//darkplaces implementation: LordHavoc
-//description:
-//this extension merely indicates that MOVETYPE_PUSH supports avelocity, allowing rotating brush models to be created, they rotate around their origin (needs rotation supporting qbsp/light utilities because id ones expected bmodel entity origins to be '0 0 0', recommend setting "origin" key in the entity fields in the map before compiling, there may be other methods depending on your qbsp, most are more complicated however).
-//tip: level designers can create a func_wall with an origin, and avelocity (for example "avelocity" "0 90 0"), and "nextthink" "99999999" to make a rotating bmodel without any qc modifications, such entities will be solid in stock quake but will not rotate)
-
-//DP_SV_SETCOLOR
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//builtin definitions:
-void(entity ent, float colors) setcolor = #401;
-//engine called QC functions (optional):
-//void(float color) SV_ChangeTeam;
-//description:
-//setcolor sets the color on a client and updates internal color information accordingly (equivalent to stuffing a "color" command but immediate)
-//SV_ChangeTeam is called by the engine whenever a "color" command is recieved, it may decide to do anything it pleases with the color passed by the client, including rejecting it (by doing nothing), or calling setcolor to apply it, preventing team changes is one use for this.
-//the color format is pants + shirt * 16 (0-255 potentially)
-
-//DP_SV_SLOWMO
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//cvars:
-//"slowmo" (0+, default 1)
-//description:
-//sets the time scale of the server, mainly intended for use in singleplayer by the player, however potentially useful for mods, so here's an extension for it.
-//range is 0 to infinite, recommended values to try are 0.1 (very slow, 10% speed), 1 (normal speed), 5 (500% speed).
-
-//DP_SV_WRITEPICTURE
-//idea: divVerent
-//darkplaces implementation: divVerent
-//builtin definitions:
-void(float to, string s, float sz) WritePicture = #501;
-//description:
-//writes a picture to the data stream so CSQC can read it using ReadPicture, which has the definition
-//  string(void) ReadPicture = #501;
-//The picture data is sent as at most sz bytes, by compressing to low quality
-//JPEG. The data being sent will be equivalent to:
-//  WriteString(to, s);
-//  WriteShort(to, imagesize);
-//  for(i = 0; i < imagesize; ++i)
-//    WriteByte(to, [the i-th byte of the compressed JPEG image]);
-
-//DP_SV_WRITEUNTERMINATEDSTRING
-//idea: FrikaC
-//darkplaces implementation: Sajt
-//builtin definitions:
-void(float to, string s) WriteUnterminatedString = #456;
-//description:
-//like WriteString, but does not write a terminating 0 after the string. This means you can include things like a player's netname in the middle of a string sent over the network. Just be sure to end it up with either a call to WriteString (which includes the trailing 0) or WriteByte(0) to terminate it yourself.
-//A historical note: this extension was suggested by FrikaC years ago, more recently Shadowalker has been badmouthing LordHavoc and Spike for stealing 'his' extension writestring2 which does exactly the same thing but uses a different builtin number and name and extension string, this argument hinges on the idea that it was his idea in the first place, which is incorrect as FrikaC first suggested it and used a rough equivalent of it in his FrikBot mod years ago involving WriteByte calls on each character.
-
-//DP_TE_BLOOD
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//builtin definitions:
-void(vector org, vector velocity, float howmany) te_blood = #405;
-//temp entity definitions:
-float TE_BLOOD = 50;
-//protocol:
-//vector origin
-//byte xvelocity (-128 to +127)
-//byte yvelocity (-128 to +127)
-//byte zvelocity (-128 to +127)
-//byte count (0 to 255, how much blood)
-//description:
-//creates a blood effect.
-
-//DP_TE_BLOODSHOWER
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//builtin definitions:
-void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower = #406;
-//temp entity definitions:
-//float TE_BLOODSHOWER = 52;
-//protocol:
-//vector mins (minimum corner of the cube)
-//vector maxs (maximum corner of the cube)
-//coord explosionspeed (velocity of blood particles flying out of the center)
-//short count (number of blood particles)
-//description:
-//creates an exploding shower of blood, for making gibbings more convincing.
-
-//DP_TE_CUSTOMFLASH
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//builtin definitions:
-void(vector org, float radius, float lifetime, vector color) te_customflash = #417;
-//temp entity definitions:
-//float TE_CUSTOMFLASH = 73;
-//protocol:
-//vector origin
-//byte radius ((MSG_ReadByte() + 1) * 8, meaning 8-2048 unit radius)
-//byte lifetime ((MSG_ReadByte() + 1) / 256.0, meaning approximately 0-1 second lifetime)
-//byte red (0.0 to 1.0 converted to 0-255)
-//byte green (0.0 to 1.0 converted to 0-255)
-//byte blue (0.0 to 1.0 converted to 0-255)
-//description:
-//creates a customized light flash.
-
-//DP_TE_EXPLOSIONRGB
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//builtin definitions:
-void(vector org, vector color) te_explosionrgb = #407;
-//temp entity definitions:
-//float TE_EXPLOSIONRGB = 53;
-//protocol:
-//vector origin
-//byte red (0.0 to 1.0 converted to 0 to 255)
-//byte green (0.0 to 1.0 converted to 0 to 255)
-//byte blue (0.0 to 1.0 converted to 0 to 255)
-//description:
-//creates a colored explosion effect.
-
-//DP_TE_FLAMEJET
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//builtin definitions:
-void(vector org, vector vel, float howmany) te_flamejet = #457;
-//temp entity definitions:
-//float TE_FLAMEJET = 74;
-//protocol:
-//vector origin
-//vector velocity
-//byte count (0 to 255, how many flame particles)
-//description:
-//creates a single puff of flame particles.  (not very useful really)
-
-//DP_TE_PARTICLECUBE
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//builtin definitions:
-void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube = #408;
-//temp entity definitions:
-//float TE_PARTICLECUBE = 54;
-//protocol:
-//vector mins (minimum corner of the cube)
-//vector maxs (maximum corner of the cube)
-//vector velocity
-//short count
-//byte color (palette color)
-//byte gravity (true or false, FIXME should this be a scaler instead?)
-//coord randomvel (how much to jitter the velocity)
-//description:
-//creates a cloud of particles, useful for forcefields but quite customizable.
-
-//DP_TE_PARTICLERAIN
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//builtin definitions:
-void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain = #409;
-//temp entity definitions:
-//float TE_PARTICLERAIN = 55;
-//protocol:
-//vector mins (minimum corner of the cube)
-//vector maxs (maximum corner of the cube)
-//vector velocity (velocity of particles)
-//short count (number of particles)
-//byte color (8bit palette color)
-//description:
-//creates a shower of rain, the rain will appear either at the top (if falling down) or bottom (if falling up) of the cube.
-
-//DP_TE_PARTICLESNOW
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//builtin definitions:
-void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow = #410;
-//temp entity definitions:
-//float TE_PARTICLERAIN = 56;
-//protocol:
-//vector mins (minimum corner of the cube)
-//vector maxs (maximum corner of the cube)
-//vector velocity (velocity of particles)
-//short count (number of particles)
-//byte color (8bit palette color)
-//description:
-//creates a shower of snow, the snow will appear either at the top (if falling down) or bottom (if falling up) of the cube, low velocities are advisable for convincing snow.
-
-//DP_TE_PLASMABURN
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//builtin definitions:
-void(vector org) te_plasmaburn = #433;
-//temp entity definitions:
-//float TE_PLASMABURN = 75;
-//protocol:
-//vector origin
-//description:
-//creates a small light flash (radius 200, time 0.2) and marks the walls.
-
-//DP_TE_QUADEFFECTS1
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//builtin definitions:
-void(vector org) te_gunshotquad = #412;
-void(vector org) te_spikequad = #413;
-void(vector org) te_superspikequad = #414;
-void(vector org) te_explosionquad = #415;
-//temp entity definitions:
-//float   TE_GUNSHOTQUAD  = 57; // [vector] origin
-//float   TE_SPIKEQUAD    = 58; // [vector] origin
-//float   TE_SUPERSPIKEQUAD = 59; // [vector] origin
-//float   TE_EXPLOSIONQUAD = 70; // [vector] origin
-//protocol:
-//vector origin
-//description:
-//all of these just take a location, and are equivalent in function (but not appearance :) to the original TE_GUNSHOT, etc.
-
-//DP_TE_SMALLFLASH
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//builtin definitions:
-void(vector org) te_smallflash = #416;
-//temp entity definitions:
-//float TE_SMALLFLASH = 72;
-//protocol:
-//vector origin
-//description:
-//creates a small light flash (radius 200, time 0.2).
-
-//DP_TE_SPARK
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//builtin definitions:
-void(vector org, vector vel, float howmany) te_spark = #411;
-//temp entity definitions:
-//float TE_SPARK = 51;
-//protocol:
-//vector origin
-//byte xvelocity (-128 to 127)
-//byte yvelocity (-128 to 127)
-//byte zvelocity (-128 to 127)
-//byte count (number of sparks)
-//description:
-//creates a shower of sparks and a smoke puff.
-
-//DP_TE_STANDARDEFFECTBUILTINS
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//builtin definitions:
-void(vector org) te_gunshot = #418;
-void(vector org) te_spike = #419;
-void(vector org) te_superspike = #420;
-void(vector org) te_explosion = #421;
-void(vector org) te_tarexplosion = #422;
-void(vector org) te_wizspike = #423;
-void(vector org) te_knightspike = #424;
-void(vector org) te_lavasplash = #425;
-void(vector org) te_teleport = #426;
-void(vector org, float color, float colorlength) te_explosion2 = #427;
-void(entity own, vector start, vector end) te_lightning1 = #428;
-void(entity own, vector start, vector end) te_lightning2 = #429;
-void(entity own, vector start, vector end) te_lightning3 = #430;
-void(entity own, vector start, vector end) te_beam = #431;
-//description:
-//to make life easier on mod coders.
-
-//DP_TRACE_HITCONTENTSMASK_SURFACEINFO
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//globals:
-.int dphitcontentsmask; // if non-zero on the entity passed to traceline/tracebox/tracetoss this will override the normal collidable contents rules and instead hit these contents values (for example AI can use tracelines that hit DONOTENTER if it wants to, by simply changing this field on the entity passed to traceline), this affects normal movement as well as trace calls
-int trace_dpstartcontents; // DPCONTENTS_ value at start position of trace
-int trace_dphitcontents; // DPCONTENTS_ value of impacted surface (not contents at impact point, just contents of the surface that was hit)
-int trace_dphitq3surfaceflags; // Q3SURFACEFLAG_ value of impacted surface
-string trace_dphittexturename; // texture name of impacted surface
-//constants:
-const int DPCONTENTS_SOLID = 1; // hit a bmodel, not a bounding box
-const int DPCONTENTS_WATER = 2;
-const int DPCONTENTS_SLIME = 4;
-const int DPCONTENTS_LAVA = 8;
-const int DPCONTENTS_SKY = 16;
-const int DPCONTENTS_BODY = 32; // hit a bounding box, not a bmodel
-const int DPCONTENTS_CORPSE = 64; // hit a SOLID_CORPSE entity
-const int DPCONTENTS_NODROP = 128; // an area where backpacks should not spawn
-const int DPCONTENTS_PLAYERCLIP = 256; // blocks player movement
-const int DPCONTENTS_MONSTERCLIP = 512; // blocks monster movement
-const int DPCONTENTS_DONOTENTER = 1024; // AI hint brush
-const int DPCONTENTS_LIQUIDSMASK = 14; // WATER | SLIME | LAVA
-const int DPCONTENTS_BOTCLIP = 2048; // AI hint brush
-const int DPCONTENTS_OPAQUE = 4096; // only fully opaque brushes get this (may be useful for line of sight checks)
-const int Q3SURFACEFLAG_NODAMAGE = 1;
-const int Q3SURFACEFLAG_SLICK = 2; // low friction surface
-const int Q3SURFACEFLAG_SKY = 4; // sky surface (also has NOIMPACT and NOMARKS set)
-const int Q3SURFACEFLAG_LADDER = 8; // climbable surface
-const int Q3SURFACEFLAG_NOIMPACT = 16; // projectiles should remove themselves on impact (this is set on sky)
-const int Q3SURFACEFLAG_NOMARKS = 32; // projectiles should not leave marks, such as decals (this is set on sky)
-const int Q3SURFACEFLAG_FLESH = 64; // projectiles should do a fleshy effect (blood?) on impact
-const int Q3SURFACEFLAG_NODRAW = 128; // compiler hint (not important to qc)
-//float Q3SURFACEFLAG_HINT = 256; // compiler hint (not important to qc)
-//float Q3SURFACEFLAG_SKIP = 512; // compiler hint (not important to qc)
-//float Q3SURFACEFLAG_NOLIGHTMAP = 1024; // compiler hint (not important to qc)
-//float Q3SURFACEFLAG_POINTLIGHT = 2048; // compiler hint (not important to qc)
-const int Q3SURFACEFLAG_METALSTEPS = 4096; // walking on this surface should make metal step sounds
-const int Q3SURFACEFLAG_NOSTEPS = 8192; // walking on this surface should not make footstep sounds
-const int Q3SURFACEFLAG_NONSOLID = 16384; // compiler hint (not important to qc)
-//float Q3SURFACEFLAG_LIGHTFILTER = 32768; // compiler hint (not important to qc)
-//float Q3SURFACEFLAG_ALPHASHADOW = 65536; // compiler hint (not important to qc)
-//float Q3SURFACEFLAG_NODLIGHT = 131072; // compiler hint (not important to qc)
-//float Q3SURFACEFLAG_DUST = 262144; // translucent 'light beam' effect (not important to qc)
-//description:
-//adds additional information after a traceline/tracebox/tracetoss call.
-//also (very important) sets trace_* globals before calling .touch functions,
-//this allows them to inspect the nature of the collision (for example
-//determining if a projectile hit sky), clears trace_* variables for the other
-//object in a touch event (that is to say, a projectile moving will see the
-//trace results in its .touch function, but the player it hit will see very
-//little information in the trace_ variables as it was not moving at the time)
-
-//DP_VIEWZOOM
-//idea: LordHavoc
-//darkplaces implementation: LordHavoc
-//field definitions:
-.float viewzoom;
-//description:
-//scales fov and sensitivity of player, valid range is 0 to 1 (intended for sniper rifle zooming, and such)
-
-//EXT_BITSHIFT
-//idea: Spike
-//darkplaces implementation: [515]
-//builtin definitions:
-float(float number, float quantity) bitshift = #218;
-//description:
-//multiplies number by a power of 2 corresponding to quantity (0 = *1, 1 = *2, 2 = *4, 3 = *8, -1 = /2, -2 = /4x, etc), and rounds down (due to integer math) like other bit operations do (& and | and the like).
-//note: it is faster to use multiply if you are shifting by a constant, avoiding the quakec function call cost, however that does not do a floor for you.
-
-//FRIK_FILE
-//idea: FrikaC
-//darkplaces implementation: LordHavoc
-//builtin definitions:
-float(string s) stof = #81; // get numerical value from a string
-float(string filename, float mode) fopen = #110; // opens a file inside quake/gamedir/data/ (mode is FILE_READ, FILE_APPEND, or FILE_WRITE), returns fhandle >= 0 if successful, or fhandle < 0 if unable to open file for any reason
-void(float fhandle) fclose = #111; // closes a file
-string(float fhandle) fgets = #112; // reads a line of text from the file and returns as a tempstring
-void(float fhandle, string s, ...) fputs = #113; // writes a line of text to the end of the file
-int(string s) strlen = #114; // returns how many characters are in a string
-string(string s1, string s2, ...) strcat = #115; // concatenates two or more strings (for example "abc", "def" would return "abcdef") and returns as a tempstring
-string(string s, float start, float length) substring = #116; // returns a section of a string as a tempstring - see FTE_STRINGS for enhanced version
-vector(string s) stov = #117; // returns vector value from a string
-string(string s, ...) strzone = #118; // makes a copy of a string into the string zone and returns it, this is often used to keep around a tempstring for longer periods of time (tempstrings are replaced often)
-void(string s) strunzone = #119; // removes a copy of a string from the string zone (you can not use that string again or it may crash!!!)
-//constants:
-float FILE_READ = 0;
-float FILE_APPEND = 1;
-float FILE_WRITE = 2;
-//cvars:
-//pr_zone_min_strings : default 64 (64k), min 64 (64k), max 8192 (8mb)
-//description:
-//provides text file access functions and string manipulation functions, note that you may want to set pr_zone_min_strings in the worldspawn function if 64k is not enough string zone space.
-//
-//NOTE: strzone functionality is partially superseded by
-//DP_QC_UNLIMITEDTEMPSTRINGS when longterm storage is not needed
-//NOTE: substring is upgraded by FTE_STRINGS extension with negative start/length handling identical to php 5.2.0
-
-//FTE_CSQC_SKELETONOBJECTS
-//idea: Spike, LordHavoc
-//darkplaces implementation: LordHavoc
-//builtin definitions:
-// all skeleton numbers are 1-based (0 being no skeleton)
-// all bone numbers are 1-based (0 being invalid)
-float(float modlindex) skel_create = #263; // create a skeleton (be sure to assign this value into .skeletonindex for use), returns skeleton index (1 or higher) on success, returns 0 on failure (for example if the modelindex is not skeletal), it is recommended that you create a new skeleton if you change modelindex, as the skeleton uses the hierarchy from the model.
-float(float skel, entity ent, float modlindex, float retainfrac, float firstbone, float lastbone) skel_build = #264; // blend in a percentage of standard animation, 0 replaces entirely, 1 does nothing, 0.5 blends half, etc, and this only alters the bones in the specified range for which out of bounds values like 0,100000 are safe (uses .frame, .frame2, .frame3, .frame4, .lerpfrac, .lerpfrac3, .lerpfrac4, .frame1time, .frame2time, .frame3time, .frame4time), returns skel on success, 0 on failure
-float(float skel) skel_get_numbones = #265; // returns how many bones exist in the created skeleton, 0 if skeleton does not exist
-string(float skel, float bonenum) skel_get_bonename = #266; // returns name of bone (as a tempstring), "" if invalid bonenum (< 1 for example) or skeleton does not exist
-int(float skel, float bonenum) skel_get_boneparent = #267; // returns parent num for supplied bonenum, 0 if bonenum has no parent or bone does not exist (returned value is always less than bonenum, you can loop on this)
-int(float skel, string tagname) skel_find_bone = #268; // get number of bone with specified name, 0 on failure, bonenum (1-based) on success, same as using gettagindex but takes modelindex instead of entity
-vector(float skel, float bonenum) skel_get_bonerel = #269; // get matrix of bone in skeleton relative to its parent - sets v_forward, v_right, v_up, returns origin (relative to parent bone)
-vector(float skel, float bonenum) skel_get_boneabs = #270; // get matrix of bone in skeleton in model space - sets v_forward, v_right, v_up, returns origin (relative to entity)
-void(float skel, float bonenum, vector org) skel_set_bone = #271; // set matrix of bone relative to its parent, reads v_forward, v_right, v_up, takes origin as parameter (relative to parent bone)
-void(float skel, float bonenum, vector org) skel_mul_bone = #272; // transform bone matrix (relative to its parent) by the supplied matrix in v_forward, v_right, v_up, takes origin as parameter (relative to parent bone)
-void(float skel, float startbone, float endbone, vector org) skel_mul_bones = #273; // transform bone matrices (relative to their parents) by the supplied matrix in v_forward, v_right, v_up, takes origin as parameter (relative to parent bones)
-void(float skeldst, float skelsrc, float startbone, float endbone) skel_copybones = #274; // copy bone matrices (relative to their parents) from one skeleton to another, useful for copying a skeleton to a corpse
-void(float skel) skel_delete = #275; // deletes skeleton at the beginning of the next frame (you can add the entity, delete the skeleton, renderscene, and it will still work)
-float(float modlindex, string framename) frameforname = #276; // finds number of a specified frame in the animation, returns -1 if no match found
-float(float modlindex, float framenum) frameduration = #277; // returns the intended play time (in seconds) of the specified framegroup, if it does not exist the result is 0, if it is a single frame it may be a small value around 0.1 or 0.
-//fields:
-.int skeletonindex; // active skeleton overriding standard animation on model
-.int frame; // primary framegroup animation (strength = 1 - lerpfrac - lerpfrac3 - lerpfrac4)
-.int frame2; // secondary framegroup animation (strength = lerpfrac)
-.float frame3; // tertiary framegroup animation (strength = lerpfrac3)
-.float frame4; // quaternary framegroup animation (strength = lerpfrac4)
-.float lerpfrac; // strength of framegroup blend
-.float lerpfrac3; // strength of framegroup blend
-.float lerpfrac4; // strength of framegroup blend
-.float frame1time; // start time of framegroup animation
-.float frame2time; // start time of framegroup animation
-.float frame3time; // start time of framegroup animation
-.float frame4time; // start time of framegroup animation
-//description:
-//this extension provides a way to do complex skeletal animation on an entity.
-//
-//see also DP_SKELETONOBJECTS (this extension implemented on server as well as client)
-//
-//notes:
-//each model contains its own skeleton, reusing a skeleton with incompatible models will yield garbage (or not render).
-//each model contains its own animation data, you can use animations from other model files (for example saving out all character animations as separate model files).
-//if an engine supports loading an animation-only file format such as .md5anim in FTEQW, it can be used to animate any model with a compatible skeleton.
-//proper use of this extension may require understanding matrix transforms (v_forward, v_right, v_up, origin), and you must keep in mind that v_right is negative for this purpose.
-//
-//features include:
-//multiple animations blended together.
-//animating a model with animations from another model with a compatible skeleton.
-//restricting animation blends to certain bones of a model - for example independent animation of legs, torso, head.
-//custom bone controllers - for example making eyes track a target location.
-//
-//
-//
-//example code follows...
-//
-//this helper function lets you identify (by parentage) what group a bone
-//belongs to - for example "torso", "leftarm", would return 1 ("torso") for
-//all children of the bone named "torso", unless they are children of
-//"leftarm" (which is a child of "torso") which would return 2 instead...
-float(float skel, float bonenum, string g1, string g2, string g3, string g4, string g5, string g6) example_skel_findbonegroup =
-{
-       while (bonenum >= 0)
-       {
-               string bonename = skel_get_bonename(skel, bonenum);
-               if (bonename == g1) return 1;
-               if (bonename == g2) return 2;
-               if (bonename == g3) return 3;
-               if (bonename == g4) return 4;
-               if (bonename == g5) return 5;
-               if (bonename == g6) return 6;
-               bonenum = skel_get_boneparent(skel, bonenum);
-       }
-       return 0;
-};
-// create a skeletonindex for our player using current modelindex
-void() example_skel_player_setup =
-{
-       self.skeletonindex = skel_create(self.modelindex);
-};
-// setup bones of skeleton based on an animation
-// note: animmodelindex can be a different model than self.modelindex
-void(float animmodelindex, float framegroup, float framegroupstarttime) example_skel_player_update_begin =
-{
-       // start with our standard animation
-       self.frame = framegroup;
-       self.frame2 = 0;
-       self.frame3 = 0;
-       self.frame4 = 0;
-       self.frame1time = framegroupstarttime;
-       self.frame2time = 0;
-       self.frame3time = 0;
-       self.frame4time = 0;
-       self.lerpfrac = 0;
-       self.lerpfrac3 = 0;
-       self.lerpfrac4 = 0;
-       skel_build(self.skeletonindex, self, animmodelindex, 0, 0, 100000);
-};
-// apply a different framegroup animation to bones with a specified parent
-void(float animmodelindex, float framegroup, float framegroupstarttime, float blendalpha, string groupbonename, string excludegroupname1, string excludegroupname2) example_skel_player_update_applyoverride =
-{
-       self.frame = framegroup;
-       self.frame2 = 0;
-       self.frame3 = 0;
-       self.frame4 = 0;
-       self.frame1time = framegroupstarttime;
-       self.frame2time = 0;
-       self.frame3time = 0;
-       self.frame4time = 0;
-       self.lerpfrac = 0;
-       self.lerpfrac3 = 0;
-       self.lerpfrac4 = 0;
-       float bonenum = 0;
-       float numbones = skel_get_numbones(self.skeletonindex);
-       while (bonenum < numbones)
-       {
-               if (example_skel_findbonegroup(self.skeletonindex, bonenum, groupbonename, excludegroupname1, excludegroupname2, "", "", "") == 1)
-                       skel_build(self.skeletonindex, self, animmodelindex, 1 - blendalpha, bonenum, bonenum + 1);
-               bonenum = bonenum + 1;
-       }
-};
-// make eyes point at a target location, be sure v_forward, v_right, v_up are set correctly before calling
-void(vector eyetarget, string bonename) example_skel_player_update_eyetarget =
-{
-       float bonenum = skel_find_bone(self.skeletonindex, bonename) - 1;
-       if (bonenum < 0)
-               return;
-       vector oldforward = v_forward;
-       vector oldright = v_right;
-       vector oldup = v_up;
-       vector v = eyetarget - self.origin;
-       vector modeleyetarget;
-       modeleyetarget.x =   v * v_forward;
-       modeleyetarget.y = 0-v * v_right;
-       modeleyetarget.z =   v * v_up;
-       // this is an eyeball, make it point at the target location
-       // first get all the data we can...
-       vector relorg = skel_get_bonerel(self.skeletonindex, bonenum);
-       vector relforward = v_forward;
-       vector relright = v_right;
-       vector relup = v_up;
-       vector boneorg = skel_get_boneabs(self.skeletonindex, bonenum);
-       vector boneforward = v_forward;
-       vector boneright = v_right;
-       vector boneup = v_up;
-       vector parentorg = skel_get_boneabs(self.skeletonindex, skel_get_boneparent(self.skeletonindex, bonenum));
-       vector parentforward = v_forward;
-       vector parentright = v_right;
-       vector parentup = v_up;
-       // get the vector from the eyeball to the target
-       vector u = modeleyetarget - boneorg;
-       // now transform it inversely by the parent matrix to produce new rel vectors
-       v.x = u * parentforward;
-       v.y = u * parentright;
-       v.z = u * parentup;
-       vector ang = vectoangles2(v, relup);
-       ang.x = 0 - ang.x;
-       makevectors(ang);
-       // set the relative bone matrix
-       skel_set_bone(self.skeletonindex, bonenum, relorg);
-       // restore caller's v_ vectors
-       v_forward = oldforward;
-       v_right = oldright;
-       v_up = oldup;
-};
-// delete skeleton when we're done with it
-// note: skeleton remains valid until next frame when it is really deleted
-void() example_skel_player_delete =
-{
-       skel_delete(self.skeletonindex);
-       self.skeletonindex = 0;
-};
-//
-// END OF EXAMPLES FOR FTE_CSQC_SKELETONOBJECTS
-//
-
-//KRIMZON_SV_PARSECLIENTCOMMAND
-//idea: KrimZon
-//darkplaces implementation: KrimZon, LordHavoc
-//engine-called QC prototypes:
-//void(string s) SV_ParseClientCommand;
-//builtin definitions:
-void(entity e, string s) clientcommand = #440;
-int(string s) tokenize = #441;
-string(float n) argv = #442;
-//description:
-//provides QC the ability to completely control server interpretation of client commands ("say" and "color" for example, clientcommand is necessary for this and substring (FRIK_FILE) is useful) as well as adding new commands (tokenize, argv, and stof (FRIK_FILE) are useful for this)), whenever a clc_stringcmd is received the QC function is called, and it is up to the QC to decide what (if anything) to do with it
-
-//NEH_CMD_PLAY2
-//idea: Nehahra
-//darkplaces implementation: LordHavoc
-//description:
-//shows that the engine supports the "play2" console command (plays a sound without spatialization).
-
-//NEH_RESTOREGAME
-//idea: Nehahra
-//darkplaces implementation: LordHavoc
-//engine-called QC prototypes:
-//void() RestoreGame;
-//description:
-//when a savegame is loaded, this function is called
-
-//NEXUIZ_PLAYERMODEL
-//idea: Nexuiz
-//darkplaces implementation: Black
-//console commands:
-//playermodel <name> - FIXME: EXAMPLE NEEDED
-//playerskin <name> - FIXME: EXAMPLE NEEDED
-//field definitions:
-.string playermodel; // name of player model sent by client
-.string playerskin; // name of player skin sent by client
-//description:
-//these client properties are used by Nexuiz.
-
-//NXQ_GFX_LETTERBOX
-//idea: nxQuake
-//darkplaces implementation: LordHavoc
-//description:
-//shows that the engine supports the "r_letterbox" console variable, set to values in the range 0-100 this restricts the view vertically (and turns off sbar and crosshair), value is a 0-100 percentage of how much to constrict the view, <=0 = normal view height, 25 = 75% of normal view height, 50 = 50%, 75 = 25%, >=100 = no view
-
-//PRYDON_CLIENTCURSOR
-//idea: FrikaC
-//darkplaces implementation: LordHavoc
-//effects bit:
-const int EF_SELECTABLE = 16384; // allows cursor to highlight entity (brighten)
-//field definitions:
-.float cursor_active; // true if cl_prydoncursor mode is on
-.vector cursor_screen; // screen position of cursor as -1 to +1 in _x and _y (_z unused)
-.vector cursor_trace_start; // position of camera
-.vector cursor_trace_endpos; // position of cursor in world (as traced from camera)
-.entity cursor_trace_ent; // entity the cursor is pointing at (server forces this to world if the entity is currently free at time of receipt)
-//cvar definitions:
-//cl_prydoncursor (0/1+, default 0, 1 and above use cursors named gfx/prydoncursor%03i.lmp - or .tga and such if DP_GFX_EXTERNALTEXTURES is implemented)
-//description:
-//shows that the engine supports the cl_prydoncursor cvar, this puts a clientside mouse pointer on the screen and feeds input to the server for the QuakeC to use as it sees fit.
-//the mouse pointer triggers button4 if cursor is at left edge of screen, button5 if at right edge of screen, button6 if at top edge of screen, button7 if at bottom edge of screen.
-//the clientside trace skips transparent entities (except those marked EF_SELECTABLE).
-//the selected entity highlights only if EF_SELECTABLE is set, a typical selection method would be doubling the brightness of the entity by some means (such as colormod[] *= 2).
-//intended to be used by Prydon Gate.
-
-//TENEBRAE_GFX_DLIGHTS
-//idea: Tenebrae
-//darkplaces implementation: LordHavoc
-//fields:
-.float light_lev; // radius (does not affect brightness), typical value 350
-.vector color; // color (does not affect radius), typical value '1 1 1' (bright white), can be up to '255 255 255' (nuclear blast)
-.float style; // light style (like normal light entities, flickering torches or switchable, etc)
-.float pflags; // flags (see PFLAGS_ constants)
-.vector angles; // orientation of the light
-.int skin; // cubemap filter number, can be 1-255 (0 is assumed to be none, and tenebrae only allows 16-255), this selects a projective light filter, a value of 1 loads cubemaps/1posx.tga and cubemaps/1negx.tga and posy, negy, posz, and negz, similar to skybox but some sides need to be rotated or flipped
-//constants:
-float PFLAGS_NOSHADOW = 1; // light does not cast shadows
-float PFLAGS_CORONA = 2; // light has a corona flare
-float PFLAGS_FULLDYNAMIC = 128; // light enable (without this set no light is produced!)
-//description:
-//more powerful dynamic light settings
-//warning: it is best not to use cubemaps on a light entity that has a model, as using a skin number that a model does not have will cause issues in glquake, and produce warnings in darkplaces (use developer 1 to see them)
-//changes compared to tenebrae (because they're too 'leet' for standards):
-//note: networking should send entities with PFLAGS_FULLDYNAMIC set even if they have no model (lights in general do not have a model, nor should they)
-//EF_FULLDYNAMIC effects flag replaced by PFLAGS_FULLDYNAMIC flag (EF_FULLDYNAMIC conflicts with EF_NODRAW)
-
-//TW_SV_STEPCONTROL
-//idea: Transfusion
-//darkplaces implementation: LordHavoc
-//cvars:
-//sv_jumpstep (0/1, default 1)
-//sv_stepheight (default 18)
-//description:
-//sv_jumpstep allows stepping up onto stairs while airborn, sv_stepheight controls how high a single step can be.
-
-//FTE_QC_CHECKPVS
-//idea: Urre
-//darkplaces implementation: divVerent
-//builtin definitions:
-float checkpvs(vector viewpos, entity viewee) = #240;
-//description:
-//returns true if viewee can be seen from viewpos according to PVS data
-
-//FTE_STRINGS
-//idea: many
-//darkplaces implementation: KrimZon
-//builtin definitions:
-int(string str, string sub, float startpos) strstrofs = #221; // returns the offset into a string of the matching text, or -1 if not found, case sensitive
-int(string str, float ofs) str2chr = #222; // returns the character at the specified offset as an integer, or 0 if an invalid index, or byte value - 256 if the engine supports UTF8 and the byte is part of an extended character
-string(int c, ...) chr2str = #223; // returns a string representing the character given, if the engine supports UTF8 this may be a multi-byte sequence (length may be more than 1) for characters over 127.
-string(float ccase, float calpha, float cnum, string s, ...) strconv = #224; // reformat a string with special color characters in the font, DO NOT USE THIS ON UTF8 ENGINES (if you are lucky they will emit ^4 and such color codes instead), the parameter values are 0=same/1=lower/2=upper for ccase, 0=same/1=white/2=red/5=alternate/6=alternate-alternate for redalpha, 0=same/1=white/2=red/3=redspecial/4=whitespecial/5=alternate/6=alternate-alternate for rednum.
-string(float chars, string s, ...) strpad = #225; // pad string with spaces to a specified length, < 0 = left padding, > 0 = right padding
-string(string info, string key, string value, ...) infoadd = #226; // sets or adds a key/value pair to an infostring - note: forbidden characters are \ and "
-string(string info, string key) infoget = #227; // gets a key/value pair in an infostring, returns value or null if not found
-int(string s1, string s2) strcmp = #228; // compare two strings
-int(string s1, string s2, float len) strncmp = #228; // compare two strings up to the specified number of characters, if their length differs and is within the specified limit the result will be negative, otherwise it is the difference in value of their first non-matching character.
-int(string s1, string s2) strcasecmp = #229; // compare two strings with case-insensitive matching, characters a-z are considered equivalent to the matching A-Z character, no other differences, and this does not consider special characters equal even if they look similar
-int(string s1, string s2, float len) strncasecmp = #230; // same as strcasecmp but with a length limit, see strncmp
-//string(string s, float start, float length) substring = #116; // see note below
-//description:
-//various string manipulation functions
-//note: substring also exists in FRIK_FILE but this extension adds negative start and length as valid cases (see note above), substring is consistent with the php 5.2.0 substr function (not 5.2.3 behavior)
-//substring returns a section of a string as a tempstring, if given negative
-// start the start is measured back from the end of the string, if given a
-// negative length the length is the offset back from the end of the string to
-// stop at, rather than being relative to start, if start is negative and
-// larger than length it is treated as 0.
-// examples of substring:
-// substring("blah", -3, 3) returns "lah"
-// substring("blah", 3, 3) returns "h"
-// substring("blah", -10, 3) returns "bla"
-// substring("blah", -10, -3) returns "b"
-
-//DP_CON_BESTWEAPON
-//idea: many
-//darkplaces implementation: divVerent
-//description:
-//allows QC to register weapon properties for use by the bestweapon command, for mods that change required ammo count or type for the weapons
-//it is done using console commands sent via stuffcmd:
-//  register_bestweapon quake
-//  register_bestweapon clear
-//  register_bestweapon <shortname> <impulse> <itemcode> <activeweaponcode> <ammostat> <ammomin>
-//for example, this is what Quake uses:
-//  register_bestweapon 1 1 4096 4096 6 0 // STAT_SHELLS is 6
-//  register_bestweapon 2 2    1    1 6 1
-//  register_bestweapon 3 3    2    2 6 1
-//  register_bestweapon 4 4    4    4 7 1 // STAT_NAILS is 7
-//  register_bestweapon 5 5    8    8 7 1
-//  register_bestweapon 6 6   16   16 8 1 // STAT_ROCKETS is 8
-//  register_bestweapon 7 7   32   32 8 1
-//  register_bestweapon 8 8   64   64 9 1 // STAT_CELLS is 9
-//after each map client initialization, this is reset back to Quake settings. So you should send these data in ClientConnect.
-//also, this extension introduces a new "cycleweapon" command to the user.
-
-//DP_QC_STRINGBUFFERS
-//idea: ??
-//darkplaces implementation: LordHavoc
-//functions to manage string buffer objects - that is, arbitrary length string arrays that are handled by the engine
-int() buf_create = #460;
-void(float bufhandle) buf_del = #461;
-float(float bufhandle) buf_getsize = #462;
-void(float bufhandle_from, float bufhandle_to) buf_copy = #463;
-void(float bufhandle, float sortpower, float backward) buf_sort = #464;
-string(float bufhandle, string glue) buf_implode = #465;
-string(float bufhandle, float string_index) bufstr_get = #466;
-void(float bufhandle, float string_index, string str) bufstr_set = #467;
-float(float bufhandle, string str, float order) bufstr_add = #468;
-void(float bufhandle, float string_index) bufstr_free = #469;
-
-//DP_QC_STRINGBUFFERS_CVARLIST
-//idea: divVerent
-//darkplaces implementation: divVerent
-//functions to list cvars and store their names into a stringbuffer
-//cvars that start with pattern but not with antipattern will be stored into the buffer
-void(float bufhandle, string pattern, string antipattern) buf_cvarlist = #517;
-
-//DP_QC_STRINGBUFFERS_EXT_WIP
-//idea: VorteX
-//darkplaces implementation: VorteX
-//constant definitions:
-const float MATCH_AUTO = 0;
-const float MATCH_WHOLE = 1;
-const float MATCH_LEFT = 2;
-const float MATCH_RIGHT = 3;
-const float MATCH_MIDDLE = 4;
-const float MATCH_PATTERN = 5;
-//builtin definitions:
-float(string filename, float bufhandle) buf_loadfile = #535; // append each line of file as new buffer string, return 1 if succesful
-float(float filehandle, float bufhandle, float startpos, float numstrings) buf_writefile = #536; // writes buffer strings as lines, returns 1 if succesful
-float(float bufhandle, string match, float matchrule, float startpos, float step) bufstr_find = #537; // returns string index
-float(string s, string pattern, float matchrule) matchpattern = #538; // returns 0/1
-float(string s, string pattern, float matchrule, float pos) matchpatternofs = #538;
-//description:
-//provides a set of functions to manipulate with string buffers
-//pattern wildcards: * - any character (or no characters), ? - any 1 character
-//Warning: This extension is work-in-progress, it may be changed/revamped/removed at any time, dont use it if you dont want any trouble
-//wip note: UTF8 is not supported yet
-
-//DP_QC_STRREPLACE
-//idea: Sajt
-//darkplaces implementation: Sajt
-//builtin definitions:
-string(string search, string replace, string subject) strreplace = #484;
-string(string search, string replace, string subject) strireplace = #485;
-//description:
-//strreplace replaces all occurrences of 'search' with 'replace' in the string 'subject', and returns the result as a tempstring.
-//strireplace does the same but uses case-insensitive matching of the 'search' term
-
-//DP_SV_SHUTDOWN
-//idea: divVerent
-//darkplaces implementation: divVerent
-//A function that gets called just before progs exit. To save persistent data from.
-//It is not called on a crash or error.
-//void SV_Shutdown();
-
-//EXT_CSQC
-// #232 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
-void(float index, float type, ...) addstat = #232;
-
-//ZQ_PAUSE
-//idea: ZQuake
-//darkplaces implementation: GreEn`mArine
-//builtin definitions:
-void(float pause) setpause = #531;
-//function definitions:
-//void(float elapsedtime) SV_PausedTic;
-//description:
-//during pause the world is not updated (time does not advance), SV_PausedTic is the only function you can be sure will be called at regular intervals during the pause, elapsedtime is the current system time in seconds since the pause started (not affected by slowmo or anything else).
-//
-//calling setpause(0) will end a pause immediately.
-//
-//Note: it is worth considering that network-related functions may be called during the pause (including customizeentityforclient for example), and it is also important to consider the continued use of the KRIMZON_SV_PARSECLIENTCOMMAND extension while paused (chatting players, etc), players may also join/leave during the pause.  In other words, the only things that are not called are think and other time-related functions.
-
-//DP_COVERAGE
-//idea: divVerent
-//darkplaces implementation: divVerent
-//function definitions:
-void coverage() = #642;  // Reports a coverage event. The engine counts for each of the calls to this builtin whether it has been called.
-
-
-// EXPERIMENTAL (not finalized) EXTENSIONS:
-
-//DP_CRYPTO
-//idea: divVerent
-//darkplaces implementation: divVerent
-//field definitions: (SVQC)
-.string crypto_keyfp; // fingerprint of CA key the player used to authenticate
-.string crypto_mykeyfp; // fingerprint of CA key the server used to authenticate to the player
-.string crypto_idfp; // fingerprint of ID used by the player entity, or string_null if not identified
-.float crypto_idfp_signed; // set if the player's ID has been signed
-.string crypto_encryptmethod; // the string "AES128" if encrypting, and string_null if plaintext
-.string crypto_signmethod; // the string "HMAC-SHA256" if signing, and string_null if plaintext
-// there is no field crypto_myidfp, as that info contains no additional information the QC may have a use for
-//builtin definitions: (SVQC)
-float(string url, float id, string content_type, string delim, float buf, float keyid) crypto_uri_postbuf = #513;
-//description:
-//use -1 as buffer handle to justs end delim as postdata
 #endif
index d7423083f8b43a2eb06a391e421e8df6fba65a0f..f4c49f143b5c119cd3dbb1a7c434a53d701bf681 100644 (file)
 
 #pragma noref 1
 
-///////////////////////////
-// key constants
+//#define float const int
 
-//
-// these are the key numbers that should be passed to Key_Event
-//
-int K_TAB                      = 9;
-int K_ENTER                = 13;
-int K_ESCAPE           = 27;
-int K_SPACE                = 32;
+#include "upstream/keycodes.qc"
 
-// normal keys should be passed as lowercased ascii
-
-int K_BACKSPACE            = 127;
-int K_UPARROW          = 128;
-int K_DOWNARROW            = 129;
-int K_LEFTARROW            = 130;
-int K_RIGHTARROW       = 131;
-
-int K_ALT                  = 132;
-int K_CTRL             = 133;
-int K_SHIFT            = 134;
-
-int K_F1                   = 135;
-int K_F2                   = 136;
-int K_F3                   = 137;
-int K_F4                   = 138;
-int K_F5                   = 139;
-int K_F6                   = 140;
-int K_F7                   = 141;
-int K_F8                   = 142;
-int K_F9                   = 143;
-int K_F10                  = 144;
-int K_F11                  = 145;
-int K_F12                  = 146;
-
-int K_INS                  = 147;
-int K_DEL                  = 148;
-int K_PGDN             = 149;
-int K_PGUP             = 150;
-int K_HOME             = 151;
-int K_END                  = 152;
-
-int K_NUMLOCK          = 154;
-int K_CAPSLOCK     = 155;
-int K_SCROLLLOCK       = 156;
-
-int K_KP_0             = 157;
-int K_KP_INS       = 157; // same as K_KP_0
-int K_KP_1             = 158;
-int K_KP_END       = 158; // same as K_KP_1
-int K_KP_2             = 159;
-int K_KP_DOWNARROW  = 159; // same as K_KP_2
-int K_KP_3             = 160;
-int K_KP_PGDN       = 160; // same as K_KP_3
-int K_KP_4             = 161;
-int K_KP_LEFTARROW  = 161; // same as K_KP_4
-int K_KP_5             = 162;
-int K_KP_6             = 163;
-int K_KP_RIGHTARROW = 163; // same as K_KP_6
-int K_KP_7             = 164;
-int K_KP_HOME       = 164; // same as K_KP_7
-int K_KP_8             = 165;
-int K_KP_UPARROW    = 165; // same as K_KP_8
-int K_KP_9             = 166;
-int K_KP_PGUP       = 166; // same as K_KP_9
-int K_KP_PERIOD     = 167;
-int K_KP_DEL        = 167; // same as K_KP_PERIOD
-int K_KP_DIVIDE     = 168;
-int K_KP_SLASH      = 168; // same as K_KP_DIVIDE
-int K_KP_MULTIPLY   = 169;
-int K_KP_MINUS     = 170;
-int K_KP_PLUS          = 171;
-int K_KP_ENTER     = 172;
-int K_KP_EQUALS            = 173;
-
-// mouse buttons generate virtual keys
-int K_PAUSE            = 153;
-
-//
-// joystick buttons
-//
-int K_JOY1          = 768;
-int K_JOY2          = 769;
-int K_JOY3          = 770;
-int K_JOY4          = 771;
-
-//
-//
-// aux keys are for multi-buttoned joysticks to generate so they can use
-// the normal binding process
-//
-int K_AUX1             = 772;
-int K_AUX2             = 773;
-int K_AUX3             = 774;
-int K_AUX4             = 775;
-int K_AUX5             = 776;
-int K_AUX6             = 777;
-int K_AUX7             = 778;
-int K_AUX8             = 779;
-int K_AUX9             = 780;
-int K_AUX10            = 781;
-int K_AUX11            = 782;
-int K_AUX12            = 783;
-int K_AUX13            = 784;
-int K_AUX14            = 785;
-int K_AUX15            = 786;
-int K_AUX16            = 787;
-int K_AUX17            = 788;
-int K_AUX18            = 789;
-int K_AUX19            = 790;
-int K_AUX20            = 791;
-int K_AUX21            = 792;
-int K_AUX22            = 793;
-int K_AUX23            = 794;
-int K_AUX24            = 795;
-int K_AUX25            = 796;
-int K_AUX26            = 797;
-int K_AUX27            = 798;
-int K_AUX28            = 799;
-int K_AUX29            = 800;
-int K_AUX30            = 801;
-int K_AUX31            = 802;
-int K_AUX32            = 803;
-
-//
-// mouse buttons generate virtual keys
-//
-int K_MOUSE1           = 512;
-int K_MOUSE2           = 513;
-int K_MOUSE3           = 514;
-int K_MWHEELUP     = 515;
-int K_MWHEELDOWN       = 516;
-int K_MOUSE4           = 517;
-int K_MOUSE5           = 518;
-int K_MOUSE6           = 519;
-int K_MOUSE7           = 520;
-int K_MOUSE8           = 521;
-int K_MOUSE9           = 522;
-int K_MOUSE10          = 523;
-int K_MOUSE11          = 524;
-int K_MOUSE12          = 525;
-int K_MOUSE13          = 526;
-int K_MOUSE14          = 527;
-int K_MOUSE15          = 528;
-int K_MOUSE16          = 529;
+//#undef float
 
 #pragma noref 0
 
index 853fa25f21cbd2be4bdb80f9fe3af24618911b79..dce99cde598cbba758d4c3cb36fdc3db325a66ba 100644 (file)
 
 #pragma noref 1
 
-//////////////////////////////////////////////////////////
-// sys globals
-
-entity self;
-
-/////////////////////////////////////////////////////////
-void           end_sys_globals;
-/////////////////////////////////////////////////////////
-// sys fields
-
-/////////////////////////////////////////////////////////
-void           end_sys_fields;
-/////////////////////////////////////////////////////////
-// sys functions
-
-void() m_init;
-void(float keynr, float ascii) m_keydown;
-void(float width, float height) m_draw;
-void(float mode) m_toggle;
-void() m_shutdown;
-// optional: float(float) m_gethostcachecategory;
-
-/////////////////////////////////////////////////////////
-// sys constants
-///////////////////////////
-// key dest constants
-
-float KEY_UNKNOWN      =       -1;
-float KEY_GAME                 =       0;
-float KEY_MENU         =       2;
-float KEY_MENU_GRABBED =       3;
-
-///////////////////////////
-// file constants
-
-float FILE_READ = 0;
-float FILE_APPEND = 1;
-float FILE_WRITE = 2;
-
-///////////////////////////
-// msg constants
-
-float MSG_BROADCAST            = 0;            // unreliable to all
-float MSG_ONE                  = 1;            // reliable to one (msg_entity)
-float MSG_ALL                  = 2;            // reliable to all
-float MSG_INIT                 = 3;            // write to the init string
-
-/////////////////////////////
-// mouse target constants
-
-float MT_MENU = 1;
-float MT_CLIENT = 2;
-
-/////////////////////////
-// client state constants
-
-float CS_DEDICATED             = 0;
-float CS_DISCONNECTED  = 1;
-float CS_CONNECTED             = 2;
-
-///////////////////////////
-// blend flags
-
-float DRAWFLAG_NORMAL          = 0;
-float DRAWFLAG_ADDITIVE        = 1;
-float DRAWFLAG_MODULATE        = 2;
-float DRAWFLAG_2XMODULATE   = 3;
-
-///////////////////////////
-// null entity (actually it is the same like the world entity)
-
-entity null_entity;
-
-///////////////////////////
-// error constants
-
-// file handling
-float ERR_CANNOTOPEN                   = -1; // fopen
-float ERR_NOTENOUGHFILEHANDLES         = -2; // fopen
-float ERR_INVALIDMODE                  = -3; // fopen
-float ERR_BADFILENAME                  = -4; // fopen
-
-// drawing functions
-
-float ERR_NULLSTRING                   = -1;
-float ERR_BADDRAWFLAG                  = -2;
-float ERR_BADSCALE                             = -3;
-float ERR_BADSIZE                              = -3; // same as ERR_BADSCALE
-float ERR_NOTCACHED                            = -4;
-
-// server list stuff
-float SLIST_HOSTCACHEVIEWCOUNT  = 0;
-float SLIST_HOSTCACHETOTALCOUNT = 1;
-float SLIST_MASTERQUERYCOUNT   = 2;
-float SLIST_MASTERREPLYCOUNT   = 3;
-float SLIST_SERVERQUERYCOUNT   = 4;
-float SLIST_SERVERREPLYCOUNT   = 5;
-float SLIST_SORTFIELD          = 6;
-float SLIST_SORTDESCENDING     = 7;
-float SLIST_LEGACY_LINE1       = 1024;
-float SLIST_LEGACY_LINE2       = 1025;
-float SLIST_TEST_CONTAINS      = 0;
-float SLIST_TEST_NOTCONTAIN    = 1;
-float SLIST_TEST_LESSEQUAL     = 2;
-float SLIST_TEST_LESS          = 3;
-float SLIST_TEST_EQUAL         = 4;
-float SLIST_TEST_GREATER       = 5;
-float SLIST_TEST_GREATEREQUAL  = 6;
-float SLIST_TEST_NOTEQUAL      = 7;
-float SLIST_TEST_STARTSWITH    = 8;
-float SLIST_TEST_NOTSTARTSWITH = 9;
-float SLIST_MASK_AND = 0;
-float SLIST_MASK_OR  = 512;
-
-// font stuff
-float FONT_DEFAULT     = 0;
-float FONT_CONSOLE     = 1;
-float FONT_SBAR        = 2;
-float FONT_NOTIFY      = 3;
-float FONT_CHAT        = 4;
-float FONT_CENTERPRINT = 5;
-float FONT_INFOBAR     = 6;
-float FONT_MENU        = 7;
-float FONT_USER        = 8; // add to this the index, like FONT_USER+3 = user3. At least 8 of them are supported.
-float drawfont;
-
-/* not supported at the moment
-///////////////////////////
-// os constants
-
-float OS_WINDOWS       = 0;
-float OS_LINUX         = 1;
-float OS_MAC           = 2;
-*/
-
-
-
-
-
-
-
-
-
-
-//////////////////////////////////////////////////
-// common cmd
-//////////////////////////////////////////////////
-// AK FIXME: Create perhaps a special builtin file for the common cmds
-
-void   checkextension(string ext)      = #1;
-
-// error cmds
-void   error(string err,...)           = #2;
-void   objerror(string err,...)        = #3;
-
-// print
-
-void   print(string text,...)                   = #4;
-void   bprint(string text,...)                  = #5;
-void   sprint(float clientnum, string text,...) = #6;
-void   centerprint(string text,...)             = #7;
-
-// vector stuff
-
-vector normalize(vector v)             = #8;
-float  vlen(vector v)                  = #9;
-float          vectoyaw(vector v)              = #10;
-vector         vectoangles(vector v)           = #11;
-
-float  random(void)  = #12;
-
-void   cmd(string command, ...) = #13;
-
-// cvar cmds
-
-float  cvar(string name)                       = #14;
-const string str_cvar(string name)             = #71;
-void   cvar_set(string name, string value)     = #15;
-
-void   dprint(string text,...) = #16;
-
-// conversion functions
-
-string ftos(float f)   = #17;
-float  fabs(float f)   = #18;
-string vtos(vector v)  = #19;
-string etos(entity e)  = #20;
-
-float  stof(string val,...)  = #21;
-
-entity spawn(void)             = #22;
-void   remove(entity e)        = #23;
-
-entity find(entity start, .string field, string match)         = #24;
-entity findfloat(entity start, .float field, float match)      = #25;
-entity findentity(entity start, .entity field, entity match)   = #25;
-
-entity findchainstring(.string field, string match)    = #26;
-entity findchainfloat(.float field, float match)       = #27;
-entity findchainentity(.entity field, entity match)    = #27;
-
-string precache_file(string file)      = #28;
-string precache_sound(string sample)   = #29;
-
-void   crash(void)     = #72;
-void   coredump(void)  = #30;
-void   stackdump(void) = #73;
-void   traceon(void)   = #31;
-void   traceoff(void)  = #32;
-
-void   eprint(entity e)        = #33;
-float  rint(float f)           = #34;
-float  floor(float f)          = #35;
-float  ceil(float f)           = #36;
-entity nextent(entity e)       = #37;
-float  sin(float f)            = #38;
-float  cos(float f)            = #39;
-float  sqrt(float f)           = #40;
-vector randomvec(void)         = #41;
-
-float  registercvar(string name, string value, float flags)  = #42; // returns 1 if success
-
-float  min(float f,...)  = #43;
-float  max(float f,...)  = #44;
-
-float  bound(float min,float value, float max)  = #45;
-float  pow(float a, float b)  = #46;
-
-void   copyentity(entity src, entity dst)  = #47;
-
-float  fopen(string filename, float mode)  = #48;
-void   fclose(float fhandle)  = #49;
-string fgets(float fhandle)  = #50;
-void   fputs(float fhandle, string s)  = #51;
-
-float  strlen(string s)  = #52;
-string strcat(string s1,string s2,...)  = #53;
-string substring(string s, float start, float length)  = #54;
-
-vector stov(string s)  = #55;
-
-string strzone(string s)  = #56;
-void   strunzone(string s) = #57;
-
-float  tokenize(string s)  = #58;
-string argv(float n)  = #59;
-
-float  isserver(void)  = #60;
-float  clientcount(void)  = #61;
-float  clientstate(void)  = #62;
-void   clientcommand(float client, string s)  = #63;
-void   changelevel(string map)  = #64;
-void   localsound(string sample)  = #65;
-vector getmousepos(void)       = #66;
-float  gettime(void)           = #67;
-void   loadfromdata(string data) = #68;
-void   loadfromfile(string file) = #69;
-
-float  mod(float val, float m) = #70;
-
-float  search_begin(string pattern, float caseinsensitive, float quiet) = #74;
-void   search_end(float handle) = #75;
-float  search_getsize(float handle) = #76;
-string search_getfilename(float handle, float num) = #77;
-
-string chr(float ascii) = #78;
-
-/////////////////////////////////////////////////
-// Write* Functions
-/////////////////////////////////////////////////
-void   WriteByte(float data, float dest, float desto)  = #401;
-void   WriteChar(float data, float dest, float desto)  = #402;
-void   WriteShort(float data, float dest, float desto) = #403;
-void   WriteLong(float data, float dest, float desto)  = #404;
-void   WriteAngle(float data, float dest, float desto) = #405;
-void   WriteCoord(float data, float dest, float desto) = #406;
-void   WriteString(string data, float dest, float desto)= #407;
-void   WriteEntity(entity data, float dest, float desto) = #408;
-
-//////////////////////////////////////////////////
-// Draw funtions
-//////////////////////////////////////////////////
-
-float  iscachedpic(string name)        = #451;
-string precache_pic(string name, ...)  = #452;
-void   freepic(string name)            = #453;
-
-float  drawcharacter(vector position, float character, vector scale, vector rgb, float alpha, float flag) = #454;
-
-float  drawstring(vector position, string text, vector scale, vector rgb, float alpha, float flag) = #455;
-
-float  drawcolorcodedstring(vector position, string text, vector scale, float alpha, float flag) = #467;
-
-vector drawcolorcodedstring2(vector position, string text, vector scale, vector rgb, float alpha, float flag) = #467;
-float  drawpic(vector position, string pic, vector size, vector rgb, float alpha, float flag) = #456;
-
-float  drawfill(vector position, vector size, vector rgb, float alpha, float flag) = #457;
-
-void   drawsetcliparea(float x, float y, float width, float height) = #458;
-
-void   drawresetcliparea(void) = #459;
-
-vector  drawgetimagesize(string pic) = #460;
-
-////////////////////////////////////////////////
-// Menu functions
-////////////////////////////////////////////////
-
-void   setkeydest(float dest)  = #601;
-float  getkeydest(void)        = #602;
-
-void   setmousetarget(float trg) = #603;
-float  getmousetarget(void)      = #604;
-
-float  isfunction(string function_name) = #607;
-void   callfunction(...) = #605;
-void   writetofile(float fhandle, entity ent) = #606;
-vector getresolution(float number) = #608;
-string keynumtostring(float keynum) = #609;
-
-float  gethostcachevalue(float type) = #611;
-string gethostcachestring(float type, float hostnr) = #612;
-
-//DP_CSQC_BINDMAPS
-//idea: daemon, motorsep
-//darkplaces implementation: divVerent
-//builtin definitions:
-string(float key, float bindmap) getkeybind_bindmap = #342;
-float(float key, string bind, float bindmap) setkeybind_bindmap = #630;
-vector(void) getbindmaps = #631;
-float(vector bm) setbindmaps = #632;
-string(string command, float bindmap) findkeysforcommand = #610;
-float(string key) stringtokeynum = #341;
-//<also allowed builtin number to match EXT_CSQC> string(float keynum) keynumtostring = #340;
-//description: key bind setting/getting including support for switchable
-//bindmaps.
-
-//DP_CRYPTO
-//idea: divVerent
-//darkplaces implementation: divVerent
-//field definitions: (MENUQC)
-string(string serveraddress) crypto_getkeyfp = #633; // retrieves the cached host key's CA fingerprint of a server given by IP address
-string(string serveraddress) crypto_getidfp = #634; // retrieves the cached host key fingerprint of a server given by IP address
-float(string serveraddress) crypto_getidstatus = #643; // retrieves the cached host key's key status. See below for CRYPTO_IDSTATUS_ defines.
-string(string serveraddress) crypto_getencryptlevel = #635; // 0 if never encrypting, 1 supported, 2 requested, 3 required, appended by list of allowed methods in order of preference ("AES128"), preceded by a space each
-string(float i) crypto_getmykeyfp = #636; // retrieves the CA key fingerprint of a given CA slot, or "" if slot is unused but more to come, or string_null if end of list
-string(float i) crypto_getmyidfp = #637; // retrieves the ID fingerprint of a given CA slot, or "" if slot is unused but more to come, or string_null if end of list
-float CRYPTO_IDSTATUS_OUTOFRANGE = -1;
-float CRYPTO_IDSTATUS_EMPTY = 0;
-float CRYPTO_IDSTATUS_UNSIGNED = 1;
-float CRYPTO_IDSTATUS_SIGNED = 2;
-float(float i) crypto_getmyidstatus = #641; // retrieves the ID's status of a given CA slot, or 0 if slot is unused but more to come, or -1 if end of list
-float(string url, float id, string content_type, string delim, float buf, float keyid) crypto_uri_postbuf = #513;
-//description:
-//use -1 as buffer handle to justs end delim as postdata
-
-//DP_GECKO_SUPPORT
-//idea: Res2k, BlackHC
-//darkplaces implementation: Res2k, BlackHC
-//constant definitions:
-float GECKO_BUTTON_DOWN         = 0;
-float GECKO_BUTTON_UP           = 1;
-// either use down and up or just press but not all of them!
-float GECKO_BUTTON_PRESS        = 2;
-// use this for mouse events if needed?
-float GECKO_BUTTON_DOUBLECLICK  = 3;
-//builtin definitions:
-float gecko_create( string name ) = #487;
-void gecko_destroy( string name ) = #488;
-void gecko_navigate( string name, string URI ) = #489;
-float gecko_keyevent( string name, float key, float eventtype ) = #490;
-void gecko_mousemove( string name, float x, float y ) = #491;
-void gecko_resize( string name, float w, float h ) = #492;
-vector gecko_get_texture_extent( string name ) = #493;
-//engine-called QC prototypes:
-//string(string name, string query) Qecko_Query;
-//description:
-//provides an interface to the offscreengecko library and allows for internet browsing in games
-
-//FTE_STRINGS
-//idea: many
-//darkplaces implementation: KrimZon
-//description:
-//various string manipulation functions
-int(string str, string sub, float startpos) strstrofs = #221;
-int(string str, float ofs) str2chr = #222;
-string(int c, ...) chr2str = #223;
-string(float ccase, float calpha, float cnum, string s, ...) strconv = #224;
-string(float chars, string s, ...) strpad = #225;
-string(string info, string key, string value, ...) infoadd = #226;
-string(string info, string key) infoget = #227;
-int(string s1, string s2) strcmp = #228;
-int(string s1, string s2, float len) strncmp = #228;
-int(string s1, string s2) strcasecmp = #229;
-int(string s1, string s2, float len) strncasecmp = #230;
-
-//DP_PRECACHE_PIC_FLAGS
-//idea: divVerent
-//darkplaces implementation: divVerent
-//constant definitions:
-float PRECACHE_PIC_FROMWAD = 1; // this one actually is part of EXT_CSQC
-float PRECACHE_PIC_NOTPERSISTENT = 2; // picture may get deallocated when unused
-float PRECACHE_PIC_MIPMAP = 8; // mipmap the texture for possibly better downscaling at memory expense
-//notes: these constants are given as optional second argument to precache_pic()
-
-//DP_QC_CRC16
-//idea: div0
-//darkplaces implementation: div0
-//Some hash function to build hash tables with. This has to be be the CRC-16-CCITT that is also required for the QuakeWorld download protocol.
-//When caseinsensitive is set, the CRC is calculated of the lower cased string.
-float(float caseinsensitive, string s, ...) crc16 = #494;
-
-//DP_QC_CVAR_TYPE
-float(string name) cvar_type = #495;
-float CVAR_TYPEFLAG_EXISTS = 1;
-float CVAR_TYPEFLAG_SAVED = 2;
-float CVAR_TYPEFLAG_PRIVATE = 4;
-float CVAR_TYPEFLAG_ENGINE = 8;
-float CVAR_TYPEFLAG_HASDESCRIPTION = 16;
-float CVAR_TYPEFLAG_READONLY = 32;
-
-//DP_QC_STRINGBUFFERS
-//idea: ??
-//darkplaces implementation: LordHavoc
-//functions to manage string buffer objects - that is, arbitrary length string arrays that are handled by the engine
-int() buf_create = #440;
-void(float bufhandle) buf_del = #441;
-float(float bufhandle) buf_getsize = #442;
-void(float bufhandle_from, float bufhandle_to) buf_copy = #443;
-void(float bufhandle, float sortpower, float backward) buf_sort = #444;
-string(float bufhandle, string glue) buf_implode = #445;
-string(float bufhandle, float string_index) bufstr_get = #446;
-void(float bufhandle, float string_index, string str) bufstr_set = #447;
-float(float bufhandle, string str, float order) bufstr_add = #448;
-void(float bufhandle, float string_index) bufstr_free = #449;
-void(float bufhandle, string pattern, string antipattern) buf_cvarlist = #517;
-
-//DP_QC_STRING_CASE_FUNCTIONS
-//idea: Dresk
-//darkplaces implementation: LordHavoc / Dresk
-//builtin definitions:
-string(string s) strtolower = #480; // returns the passed in string in pure lowercase form
-string(string s) strtoupper = #481; // returns the passed in string in pure uppercase form
-//description:
-//provides simple string uppercase and lowercase functions
-
-//DP_QC_CVAR_DESCRIPTION
-//idea: divVerent
-//DarkPlaces implementation: divVerent
-//builtin definitions:
-string(string name) cvar_description = #518;
-//description:
-//returns the description of a cvar
-
-//DP_QC_DIGEST
-//idea: motorsep, Spike
-//DarkPlaces implementation: divVerent
-//builtin definitions:
-string(string digest, string data, ...) digest_hex = #639;
-//description:
-//returns a given hex digest of given data
-//the returned digest is always encoded in hexadecimal
-//only the "MD4" digest is always supported!
-//if the given digest is not supported, string_null is returned
-//the digest string is matched case sensitively, use "MD4", not "md4"!
-
-//DP_QC_URI_ESCAPE
-//idea: div0
-//darkplaces implementation: div0
-//URI::Escape's functionality
-string(string in) uri_escape = #510;
-string(string in) uri_unescape = #511;
-
-//DP_QC_URI_GET
-//idea: divVerent
-//darkplaces implementation: divVerent
-//loads text from an URL into a string
-//returns 1 on success of initiation, 0 if there are too many concurrent
-//connections already or if the URL is invalid
-//the following callback will receive the data and MUST exist!
-//  void(float id, float status, string data) URI_Get_Callback;
-//status is either
-//  negative for an internal error,
-//  0 for success, or
-//  the HTTP response code on server error (e.g. 404)
-//if 1 is returned by uri_get, the callback will be called in the future
-float(string url, float id) uri_get = #513;
-//DP_QC_URI_POST
-//idea: divVerent
-//darkplaces implementation: divVerent
-//loads text from an URL into a string after POSTing via HTTP
-//works like uri_get, but uri_post sends data with Content-Type: content_type to the server
-//and uri_post sends the string buffer buf, joined using the delimiter delim
-float(string url, float id, string content_type, string data) uri_post = #513;
-float(string url, float id, string content_type, string delim, float buf) uri_postbuf = #513;
-
-//DP_QC_ENTITYDATA
-//idea: KrimZon
-//darkplaces implementation: KrimZon
-//builtin definitions:
-float() numentityfields = #496;
-string(float fieldnum) entityfieldname = #497;
-float(float fieldnum) entityfieldtype = #498;
-string(float fieldnum, entity ent) getentityfieldstring = #499;
-float(float fieldnum, entity ent, string s) putentityfieldstring = #500;
-//constants:
-//Returned by entityfieldtype
-float FIELD_STRING   = 1;
-float FIELD_FLOAT    = 2;
-float FIELD_VECTOR   = 3;
-float FIELD_ENTITY   = 4;
-float FIELD_FUNCTION = 6;
-//description:
-//Versatile functions intended for storing data from specific entities between level changes, but can be customized for some kind of partial savegame.
-//WARNING: .entity fields cannot be saved and restored between map loads as they will leave dangling pointers.
-//numentityfields returns the number of entity fields. NOT offsets. Vectors comprise 4 fields: v, v_x, v_y and v_z.
-//entityfieldname returns the name as a string, eg. "origin" or "classname" or whatever.
-//entityfieldtype returns a value that the constants represent, but the field may be of another type in more exotic progs.dat formats or compilers.
-//getentityfieldstring returns data as would be written to a savegame, eg... "0.05" (float), "0 0 1" (vector), or "Hello World!" (string). Function names can also be returned.
-//putentityfieldstring puts the data returned by getentityfieldstring back into the entity.
-
-//DP_COVERAGE
-//idea: divVerent
-//darkplaces implementation: divVerent
-//function definitions:
-void coverage() = #642;  // Reports a coverage event. The engine counts for each of the calls to this builtin whether it has been called.
-
-// assorted undocumented extensions
-string(string, float) netaddress_resolve = #625;
-string(string search, string replace, string subject) strreplace = #484;
-string(float uselocaltime, string format, ...) strftime = #478;
-float(string s) tokenize_console = #514;
-float(float i) argv_start_index = #515;
-float(float i) argv_end_index = #516;
-string(float, float) getgamedirinfo = #626;
-const float GETGAMEDIRINFO_NAME = 0;
-const float GETGAMEDIRINFO_DESCRIPTION = 1;
-float log(float f) = #532;
-string(string format, ...) sprintf = #627;
-string(string s) strdecolorize = #477;
-entity findflags(entity start, .float field, float match) = #87;
-entity findchainflags(.float field, float match) = #88;
-float(string s, string separator1, ...) tokenizebyseparator = #479;
-float  etof(entity ent) = #79;
-entity         ftoe(float num)  = #80;
-float   validstring(string str) = #81;
-float  altstr_count(string str) = #82;
-string  altstr_prepare(string str) = #83;
-string  altstr_get(string str, float num) = #84;
-string  altstr_set(string str, float num, string set) = #85;
-string         altstr_ins(string str, float num, string set) = #86;
-float  isdemo() = #349;
-float  drawsubpic(vector position, vector size, string pic, vector srcPosition, vector srcSize, vector rgb, float alpha, float flag) = #469;
-//vector       getresolution(float number, ...) = #608; // optional argument "isfullscreen"
-void   parseentitydata(entity ent, string data) = #613;
-void   resethostcachemasks(void) = #615;
-void   sethostcachemaskstring(float mask, float fld, string str, float op) = #616;
-void   sethostcachemasknumber(float mask, float fld, float num, float op) = #617;
-void   resorthostcache(void) = #618;
-float SLSF_DESCENDING = 1;
-float SLSF_FAVORITES = 2;
-float SLSF_CATEGORIES = 4;
-void   sethostcachesort(float fld, float slsf) = #619;
-void   refreshhostcache(...) = #620;  // optional boolean argument "clear_list"
-float  gethostcachenumber(float fld, float hostnr) = #621;
-float  gethostcacheindexforkey(string key) = #622;
-void   addwantedhostcachekey(string key) = #623;
-string getextresponse(void) = #624;
-const string cvar_string(string name) = #71;
-const string cvar_defstring(string name) = #89;
-float  stringwidth(string text, float handleColors, vector size) = #468;
+#define true _true
+#define false _false
+#define TRUE _TRUE
+#define FALSE _FALSE
+
+#include "upstream/menudefs.qc"
+
+#undef true
+#undef false
+#undef TRUE
+#undef FALSE
+
+int(string str, string sub, int startpos) _strstrofs = #221;
+#define strstrofs _strstrofs
+int(string str, int ofs) _str2chr = #222;
+#define str2chr _str2chr
+string(int c, ...) _chr2str = #223;
+#define chr2str _chr2str
+
+int(string s1, string s2) _strcmp = #228;
+#define strcmp _strcmp
+int(string s1, string s2, int len) _strncmp = #228;
+#define strncmp _strncmp
+int(string s1, string s2) _strcasecmp = #229;
+#define strcasecmp _strcasecmp
+int(string s1, string s2, int len) _strncasecmp = #230;
+#define strncasecmp _strncasecmp
+
+int() _buf_create = #440;
+#define buf_create _buf_create
 
 #pragma noref 0
 
index fe632ce8d97b8be2bc2aed7b87dc9581407f688a..bffacafddc59a928ac76441e89fe284579bb173a 100644 (file)
 #ifndef PROGSDEFS_H
 #define PROGSDEFS_H
 
-/*
-==============================================================================
+#pragma noref 1
 
-                       SOURCE FOR GLOBALVARS_T C STRUCTURE
-                       MUST NOT BE MODIFIED, OR CRC ERRORS WILL APPEAR
+#define true _true
+#define false _false
+#define TRUE _TRUE
+#define FALSE _FALSE
 
-==============================================================================
-*/
+#include "upstream/progsdefs.qc"
 
-//
-// system globals
-//
-entity         self;
-entity         other;
-entity         world;
-float          time;
-float          frametime;
+#undef true
+#undef false
+#undef TRUE
+#undef FALSE
 
-float          force_retouch;          // force all entities to touch triggers
-                                                               // next frame.  this is needed because
-                                                               // non-moving things don't normally scan
-                                                               // for triggers, and when a trigger is
-                                                               // created (like a teleport trigger), it
-                                                               // needs to catch everything.
-                                                               // decremented each frame, so set to 2
-                                                               // to guarantee everything is touched
-string         mapname;
+#pragma noref 0
 
-float          deathmatch;
-float          coop;
-float          teamplay;
-
-int                    serverflags;            // propagated from level to level, used to
-                                                               // keep track of completed episodes
-
-float          total_secrets;
-float          total_monsters;
-
-float          found_secrets;          // number of secrets found
-float          killed_monsters;        // number of monsters killed
-
-
-// spawnparms are used to encode information about clients across server
-// level changes
-float          parm1, parm2, parm3, parm4, parm5, parm6, parm7, parm8, parm9, parm10, parm11, parm12, parm13, parm14, parm15, parm16;
-
-//
-// global variables set by built in functions
-//
-vector         v_forward, v_up, v_right;       // set by makevectors()
-
-// set by traceline / tracebox
-float          trace_allsolid;
-float          trace_startsolid;
-float          trace_fraction;
-vector         trace_endpos;
-vector         trace_plane_normal;
-float          trace_plane_dist;
-entity         trace_ent;
-float          trace_inopen;
-float          trace_inwater;
-
-entity         msg_entity;                             // destination of single entity writes
-
-//
-// required prog functions
-//
-void()                 main;                                           // only for testing
-
-void()         StartFrame;
-
-void()                 PlayerPreThink;
-void()                 PlayerPostThink;
-
-void()         ClientKill;
-#ifdef DP_EXT_PRECONNECT
-void()         ClientPreConnect;
-#endif
-void()         ClientConnect;
-void()                 PutClientInServer;              // call after setting the parm1... parms
-void()         ClientDisconnect;
-
-void()         SetNewParms;                    // called when a client first connects to
-                                                                       // a server. sets parms so they can be
-                                                                       // saved off for restarts
-
-void()         SetChangeParms;                 // call to set parms for self so they can
-                                                                       // be saved for a level transition
-
-
-//================================================
-void           end_sys_globals;                // flag for structure dumping
-//================================================
-
-/*
-==============================================================================
-
-                       SOURCE FOR ENTVARS_T C STRUCTURE
-                       MUST NOT BE MODIFIED, OR CRC ERRORS WILL APPEAR
-
-==============================================================================
-*/
-
-//
-// system fields (*** = do not set in prog code, maintained by C code)
-//
-.int           modelindex;             // *** model index in the precached list
-.vector                absmin, absmax; // *** origin + mins / maxs
-
-.float         ltime;                  // local time for entity
-.float         movetype;
-.float         solid;
-
-.vector                origin;                 // ***
-.vector                oldorigin;              // ***
-.vector                velocity;
-.vector                angles;
-.vector                avelocity;
-
-.vector                punchangle;             // temp angle adjust from damage or recoil
-
-.string                classname;              // spawn function
-.string                model;
-.int           frame;
-.int           skin;
-.int           effects;
-
-.vector                mins, maxs;             // bounding box extents reletive to origin
-.vector                size;                   // maxs - mins
-
-.void()                touch;
-.void()                use;
-.void()                think;
-.void()                blocked;                // for doors or plats, called when can't push other
-
-.float         nextthink;
-.entity                groundentity;
-
-// stats
-.float         health;
-.float         frags;
-.int           weapon;                 // one of the IT_SHOTGUN, etc flags
-.string                weaponmodel;
-.float         weaponframe;
-.float         currentammo;
-.float         ammo_shells, ammo_nails, ammo_rockets, ammo_cells;
-
-.int           items;                  // bit flags
-
-.float         takedamage;
-.entity                chain;
-.float         deadflag;
-
-.vector                view_ofs;                       // add to origin to get eye point
-
-
-.float         button0;                // fire
-.float         button1;                // use
-.float         button2;                // jump
-
-.float         impulse;                // weapon changes
-
-.float         fixangle;
-.vector                v_angle;                // view / targeting angle for players
-.float         idealpitch;             // calculated pitch angle for lookup up slopes
-
-
-.string                netname;
-
-.entity        enemy;
-
-.int           flags;
-
-.int           colormap;
-.float         team;
-
-.float         max_health;             // players maximum health is stored here
-
-.float         teleport_time;  // don't back up
-
-.float         armortype;              // save this fraction of incoming damage
-.float         armorvalue;
-
-.float         waterlevel;             // 0 = not in, 1 = feet, 2 = wast, 3 = eyes
-.float         watertype;              // a contents value
-
-.float         ideal_yaw;
-.float         yaw_speed;
-
-.entity                aiment;
-
-.entity        goalentity;             // a movetarget or an enemy
-
-.int           spawnflags;
-
-.string                target;
-.string                targetname;
-
-// damage is accumulated through a frame. and sent as one single
-// message, so the super shotgun doesn't generate huge messages
-.float         dmg_take;
-.float         dmg_save;
-.entity                dmg_inflictor;
-
-.entity                owner;          // who launched a missile
-.vector                movedir;        // mostly for doors, but also used for waterjump
-
-.string                message;                // trigger messages
-
-.float         sounds;         // either a cd track number or sound number
-
-.string                noise, noise1, noise2, noise3;  // contains names of wavs to play
-
-//================================================
-void           end_sys_fields;                 // flag for structure dumping
-//================================================
-
-/*
-==============================================================================
-
-                               CONSTANT DEFINITIONS
-
-==============================================================================
-*/
-
-
-//
-// constants
-//
-
-// edict.flags
-const int FL_FLY                               = 1;
-const int FL_SWIM                              = 2;
-const int FL_CLIENT                            = 8;    // set for all client edicts
-const int FL_INWATER                   = 16;   // for enter / leave water splash
-const int FL_MONSTER                   = 32;
-const int FL_GODMODE                   = 64;   // player cheat
-const int FL_NOTARGET                  = 128;  // player cheat
-const int FL_ITEM                              = 256;  // extra wide size for bonus items
-const int FL_ONGROUND                  = 512;  // standing on something
-const int FL_PARTIALGROUND             = 1024; // not all corners are valid
-const int FL_WATERJUMP                 = 2048; // player jumping out of water
-const int FL_JUMPRELEASED              = 4096; // for jump debouncing
-
-// edict.movetype values
-const int MOVETYPE_NONE                        = 0;    // never moves
-//const int    MOVETYPE_ANGLENOCLIP= 1;
-//const int    MOVETYPE_ANGLECLIP      = 2;
-const int MOVETYPE_WALK                        = 3;    // players only
-const int MOVETYPE_STEP                        = 4;    // discrete, not real time unless fall
-const int MOVETYPE_FLY                 = 5;
-const int MOVETYPE_TOSS                        = 6;    // gravity
-const int MOVETYPE_PUSH                        = 7;    // no clip to world, push and crush
-const int MOVETYPE_NOCLIP              = 8;
-const int MOVETYPE_FLYMISSILE  = 9;    // fly with extra size against monsters
-const int MOVETYPE_BOUNCE              = 10;
-const int MOVETYPE_BOUNCEMISSILE= 11;  // bounce with extra size
-
-// edict.solid values
-const int SOLID_NOT                            = 0;    // no interaction with other objects
-const int SOLID_TRIGGER                        = 1;    // touch on edge, but not blocking
-const int SOLID_BBOX                   = 2;    // touch on edge, block
-const int SOLID_SLIDEBOX               = 3;    // touch on edge, but not an onground
-const int SOLID_BSP                            = 4;    // bsp clip, touch on edge, block
-
-// range values
-const int RANGE_MELEE                  = 0;
-const int RANGE_NEAR                   = 1;
-const int RANGE_MID                            = 2;
-const int RANGE_FAR                            = 3;
-
-// deadflag values
-
-const int DEAD_NO                              = 0;
-const int DEAD_DYING                   = 1;
-const int DEAD_DEAD                            = 2;
-const int DEAD_RESPAWNABLE             = 3;
-const int DEAD_RESPAWNING              = 4; // dead, waiting for buttons to be released
-
-// takedamage values
-
-const int DAMAGE_NO                            = 0;
-const int DAMAGE_YES                   = 1;
-const int DAMAGE_AIM                   = 2;
-
-// items
-const int IT_AXE                               = 4096;
-const int IT_SHOTGUN                   = 1;
-const int IT_SUPER_SHOTGUN             = 2;
-const int IT_NAILGUN                   = 4;
-const int IT_SUPER_NAILGUN             = 8;
-const int IT_GRENADE_LAUNCHER  = 16;
-const int IT_ROCKET_LAUNCHER   = 32;
-const int IT_LIGHTNING                 = 64;
-const int IT_EXTRA_WEAPON              = 128;
-
-//const int IT_SHELLS                  = 256;
-//const int IT_NAILS                   = 512;
-//const int IT_ROCKETS                 = 1024;
-//const int IT_CELLS                   = 2048;
-
-const int IT_ARMOR1                            = 8192;
-const int IT_ARMOR2                            = 16384;
-const int IT_ARMOR3                            = 32768;
-const int IT_SUPERHEALTH               = 65536;
-
-//const int IT_KEY1                            = 131072;
-//const int IT_KEY2                            = 262144;
-
-const int IT_INVISIBILITY              = 524288;
-const int IT_INVULNERABILITY   = 1048576;
-const int IT_SUIT                              = 2097152;
-const int IT_QUAD                              = 4194304;
-
-// point content values
-
-const int CONTENT_EMPTY                        = -1;
-const int CONTENT_SOLID                        = -2;
-const int CONTENT_WATER                        = -3;
-const int CONTENT_SLIME                        = -4;
-const int CONTENT_LAVA                 = -5;
-const int CONTENT_SKY                  = -6;
-
-const int STATE_TOP                            = 0;
-const int STATE_BOTTOM                 = 1;
-const int STATE_UP                             = 2;
-const int STATE_DOWN                   = 3;
-
-const vector VEC_ORIGIN                = '0 0 0';
-const vector VEC_HULL_MIN              = '-16 -16 -24';
-const vector VEC_HULL_MAX              = '16 16 32';
-
-const vector VEC_HULL2_MIN             = '-32 -32 -24';
-const vector VEC_HULL2_MAX             = '32 32 64';
-
-// protocol bytes
-const int SVC_TEMPENTITY               = 23;
-const int SVC_KILLEDMONSTER            = 27;
-const int SVC_FOUNDSECRET              = 28;
-const int SVC_INTERMISSION             = 30;
-const int SVC_FINALE                   = 31;
-const int SVC_CDTRACK                  = 32;
-const int SVC_SELLSCREEN               = 33;
-
-
-const int TE_SPIKE                             = 0;
-const int TE_SUPERSPIKE                        = 1;
-const int TE_GUNSHOT                   = 2;
-const int TE_EXPLOSION                 = 3;
-const int TE_TAREXPLOSION              = 4;
-const int TE_LIGHTNING1                        = 5;
-const int TE_LIGHTNING2                        = 6;
-const int TE_WIZSPIKE                  = 7;
-const int TE_KNIGHTSPIKE               = 8;
-const int TE_LIGHTNING3                        = 9;
-const int TE_LAVASPLASH                        = 10;
-const int TE_TELEPORT                  = 11;
-
-// sound channels
-// channel 0 never willingly overrides
-// other channels (1-7) allways override a playing sound on that channel
-const int CHAN_AUTO                            = 0;
-const int CHAN_WEAPON                  = 1;
-const int CHAN_VOICE                   = 2;
-const int CHAN_ITEM                            = 3;
-const int CHAN_BODY                            = 4;
-
-const int ATTN_NONE                            = 0;
-const int ATTN_NORM                            = 1;
-const int ATTN_IDLE                            = 2;
-const int ATTN_STATIC                  = 3;
-
-// update types
-
-const int UPDATE_GENERAL               = 0;
-const int UPDATE_STATIC                        = 1;
-const int UPDATE_BINARY                        = 2;
-const int UPDATE_TEMP                  = 3;
-
-// entity effects
-
-const int EF_BRIGHTFIELD               = 1;
-const int EF_MUZZLEFLASH               = 2;
-const int EF_BRIGHTLIGHT               = 4;
-const int EF_DIMLIGHT                  = 8;
-
-
-// messages
-const int MSG_BROADCAST                        = 0;            // unreliable to all
-const int MSG_ONE                              = 1;            // reliable to one (msg_entity)
-const int MSG_ALL                              = 2;            // reliable to all
-const int MSG_INIT                             = 3;            // write to the init string
-
-//===========================================================================
-
-//
-// builtin functions
-//
-
-void(vector ang)       makevectors             = #1;           // sets v_forward, etc globals
-void(entity e, vector o) setorigin     = #2;
-void(entity e, string m) setmodel      = #3;           // set movetype and solid first
-void(entity e, vector min, vector max) setsize = #4;
-// #5 was removed
-void() break_to_debugger                                               = #6;
-float() random                                         = #7;           // returns 0 - 1
-void(entity e, float chan, string samp, float vol, float atten) sound = #8;
-vector(vector v) normalize                     = #9;
-void(string e, ...) error                              = #10;
-void(string e, ...) objerror                           = #11;
-float(vector v) vlen                           = #12;
-float(vector v) vectoyaw                       = #13;
-entity() spawn                                         = #14;
-void(entity e) remove                          = #15;
-
-// sets trace_* globals
-// nomonsters can be:
-// An entity will also be ignored for testing if forent == test,
-// forent->owner == test, or test->owner == forent
-// a forent of world is ignored
-void(vector v1, vector v2, float nomonsters, entity forent) traceline = #16;
-
-entity() checkclient                           = #17;  // returns a client to look for
-entity(entity start, .string fld, string match) find = #18;
-string(string s) precache_sound                = #19;
-string(string s) precache_model                = #20;
-void(entity client, string s, ...)stuffcmd = #21;
-entity(vector org, float rad) findradius = #22;
-void(string s, ...) bprint                             = #23;
-void(entity client, string s, ...) sprint = #24;
-void(string s, ...) dprint                             = #25;
-string(float f) ftos                           = #26;
-string(vector v) vtos                          = #27;
-void() coredump                                                = #28;          // prints all edicts
-void() traceon                                         = #29;          // turns statment trace on
-void() traceoff                                                = #30;
-void(entity e) eprint                          = #31;          // prints an entire edict
-float(float yaw, float dist) walkmove  = #32;  // returns true or false
-// #33 was removed
-float() droptofloor= #34;      // true if landed on floor
-void(float style, string value) lightstyle = #35;
-float(float v) rint                                    = #36;          // round to nearest int
-float(float v) floor                           = #37;          // largest integer <= v
-float(float v) ceil                                    = #38;          // smallest integer >= v
-// #39 was removed
-float(entity e) checkbottom                    = #40;          // true if self is on ground
-float(vector v) pointcontents          = #41;          // returns a CONTENT_*
-// #42 was removed
-float(float f) fabs = #43;
-vector(entity e, float speed) aim = #44;               // returns the shooting vector
-float(string s) cvar = #45;                                            // return cvar.value
-void(string s, ...) localcmd = #46;                                    // put string into local que
-entity(entity e) nextent = #47;                                        // for looping through all ents
-void(vector o, vector d, float color, float count) particle = #48;// start a particle effect
-void() ChangeYaw = #49;                                                // turn towards self.ideal_yaw
-                                                                                       // at self.yaw_speed
-// #50 was removed
-vector(vector v) vectoangles                   = #51;
-
-//
-// direct client message generation
-//
-void(float to, float f) WriteByte              = #52;
-void(float to, float f) WriteChar              = #53;
-void(float to, float f) WriteShort             = #54;
-void(float to, float f) WriteLong              = #55;
-void(float to, float f) WriteCoord             = #56;
-void(float to, float f) WriteAngle             = #57;
-void(float to, string s, ...) WriteString      = #58;
-void(float to, entity s) WriteEntity   = #59;
-
-//
-// broadcast client message generation
-//
-
-// void(float f) bWriteByte            = #59;
-// void(float f) bWriteChar            = #60;
-// void(float f) bWriteShort           = #61;
-// void(float f) bWriteLong            = #62;
-// void(float f) bWriteCoord           = #63;
-// void(float f) bWriteAngle           = #64;
-// void(string s) bWriteString = #65;
-// void(entity e) bWriteEntity = #66;
-
-void(float step) movetogoal                            = #67;
-
-string(string s) precache_file         = #68;  // no effect except for -copy
-void(entity e) makestatic              = #69;
-void(string s) changelevel = #70;
-
-//#71 was removed
-
-void(string name, string value) cvar_set = #72;        // sets cvar.value
-
-void(entity client, string s, ...) centerprint = #73;  // sprint, but in middle
-
-void(vector pos, string samp, float vol, float atten) ambientsound = #74;
-
-string(string s) precache_model2       = #75;          // registered version only
-string(string s) precache_sound2       = #76;          // registered version only
-string(string s) precache_file2                = #77;          // registered version only
-
-void(entity e) setspawnparms           = #78;          // set parm1... to the
-                                                                                               // values at level start
-                                                                                               // for coop respawn
-
-//============================================================================
 #endif
diff --git a/qcsrc/dpdefs/upstream/csprogsdefs.qc b/qcsrc/dpdefs/upstream/csprogsdefs.qc
new file mode 100644 (file)
index 0000000..21b7c54
--- /dev/null
@@ -0,0 +1,1467 @@
+/*
+==============================================================================
+
+                       SOURCE FOR GLOBALVARS_T C STRUCTURE
+                       MUST NOT BE MODIFIED, OR CRC ERRORS WILL APPEAR
+
+==============================================================================
+*/
+
+//
+// system globals
+//
+entity         self;
+entity         other;
+entity         world;
+float          time;
+float          frametime;
+
+float          player_localentnum;     //the entnum
+float          player_localnum;        //the playernum
+float          maxclients;     //a constant filled in by the engine. gah, portability eh?
+
+float          clientcommandframe;     //player movement
+float          servercommandframe;     //clientframe echoed off the server
+
+string         mapname;
+
+//
+// global variables set by built in functions
+//
+vector         v_forward, v_up, v_right;       // set by makevectors()
+
+// set by traceline / tracebox
+float          trace_allsolid;
+float          trace_startsolid;
+float          trace_fraction;
+vector         trace_endpos;
+vector         trace_plane_normal;
+float          trace_plane_dist;
+entity         trace_ent;
+float          trace_inopen;
+float          trace_inwater;
+
+//
+// required prog functions
+//
+void()         CSQC_Init;
+void()         CSQC_Shutdown;
+float(float f, float t, float n)       CSQC_InputEvent;
+void(float w, float h)         CSQC_UpdateView;
+float(string s)        CSQC_ConsoleCommand;
+
+//these fields are read and set by the default player physics
+vector         pmove_org;
+vector         pmove_vel;
+vector         pmove_mins;
+vector         pmove_maxs;
+//retrieved from the current movement commands (read by player physics)
+float          input_timelength;
+vector         input_angles;
+vector         input_movevalues;       //forwards, right, up.
+float          input_buttons;          //attack, use, jump (default physics only uses jump)
+
+float          movevar_gravity;
+float          movevar_stopspeed;
+float          movevar_maxspeed;
+float          movevar_spectatormaxspeed;      //used by NOCLIP movetypes.
+float          movevar_accelerate;
+float          movevar_airaccelerate;
+float          movevar_wateraccelerate;
+float          movevar_friction;
+float          movevar_waterfriction;
+float          movevar_entgravity;     //the local player's gravity field. Is a multiple (1 is the normal value)
+
+//================================================
+void           end_sys_globals;                // flag for structure dumping
+//================================================
+
+/*
+==============================================================================
+
+                       SOURCE FOR ENTVARS_T C STRUCTURE
+                       MUST NOT BE MODIFIED, OR CRC ERRORS WILL APPEAR
+
+==============================================================================
+*/
+
+//
+// system fields (*** = do not set in prog code, maintained by C code)
+//
+.float         modelindex;             // *** model index in the precached list
+.vector                absmin, absmax; // *** origin + mins / maxs
+
+.float         entnum; // *** the ent number as on the server
+.float         drawmask;
+.void()                predraw;
+
+.float         movetype;
+.float         solid;
+
+.vector                origin;                 // ***
+.vector                oldorigin;              // ***
+.vector                velocity;
+.vector                angles;
+.vector                avelocity;
+
+.string                classname;              // spawn function
+.string                model;
+.float         frame;
+.float         skin;
+.float         effects;
+
+.vector                mins, maxs;             // bounding box extents reletive to origin
+.vector                size;                   // maxs - mins
+
+.void()                touch;
+.void()                use;
+.void()                think;
+.void()                blocked;                // for doors or plats, called when can't push other
+
+.float         nextthink;
+
+.entity                chain;
+
+.string                netname;
+
+.entity        enemy;
+
+.float         flags;
+
+.float         colormap;
+
+.entity                owner;          // who launched a missile
+
+//================================================
+void           end_sys_fields;                 // flag for structure dumping
+//================================================
+
+/*
+==============================================================================
+
+                       OPTIONAL FIELDS AND GLOBALS
+
+==============================================================================
+*/
+
+// Additional OPTIONAL Fields and Globals
+float          intermission; // indicates intermission state (0 = normal, 1 = scores, 2 = finale text)
+
+vector         view_angles; // same as input_angles
+vector         view_punchangle; // from server
+vector         view_punchvector; // from server
+
+/*
+==============================================================================
+
+                       CONSTANT DEFINITIONS
+
+==============================================================================
+*/
+
+const float MASK_ENGINE                        = 1;
+const float MASK_ENGINEVIEWMODELS      = 2;
+const float MASK_NORMAL                        = 4;
+
+const float RF_VIEWMODEL       = 1;
+const float RF_EXTERNALMODEL   = 2;
+const float RF_DEPTHHACK       = 4;
+const float RF_ADDITIVE                = 8;
+const float RF_USEAXIS         = 16;
+
+const float VF_MIN             = 1;    //(vector)
+const float VF_MIN_X           = 2;    //(float)
+const float VF_MIN_Y           = 3;    //(float)
+const float VF_SIZE            = 4;    //(vector) (viewport size)
+const float VF_SIZE_Y          = 5;    //(float)
+const float VF_SIZE_X          = 6;    //(float)
+const float VF_VIEWPORT                = 7;    //(vector, vector)
+const float VF_FOV             = 8;    //(vector)
+const float VF_FOVX            = 9;    //(float)
+const float VF_FOVY            = 10;   //(float)
+const float VF_ORIGIN          = 11;   //(vector)
+const float VF_ORIGIN_X                = 12;   //(float)
+const float VF_ORIGIN_Y                = 13;   //(float)
+const float VF_ORIGIN_Z                = 14;   //(float)
+const float VF_ANGLES          = 15;   //(vector)
+const float VF_ANGLES_X                = 16;   //(float)
+const float VF_ANGLES_Y                = 17;   //(float)
+const float VF_ANGLES_Z                = 18;   //(float)
+const float VF_DRAWWORLD       = 19;   //(float)
+const float VF_DRAWENGINESBAR  = 20;   //(float)
+const float VF_DRAWCROSSHAIR   = 21;   //(float)
+
+const float VF_CL_VIEWANGLES   = 33;   //(vector)
+const float VF_CL_VIEWANGLES_X = 34;   //(float)
+const float VF_CL_VIEWANGLES_Y = 35;   //(float)
+const float VF_CL_VIEWANGLES_Z = 36;   //(float)
+
+const float VF_PERSPECTIVE      = 200;
+
+const float STAT_HEALTH                = 0;
+const float STAT_WEAPONMODEL   = 2;
+const float STAT_AMMO          = 3;
+const float STAT_ARMOR         = 4;
+const float STAT_WEAPONFRAME   = 5;
+const float STAT_SHELLS                = 6;
+const float STAT_NAILS         = 7;
+const float STAT_ROCKETS       = 8;
+const float STAT_CELLS         = 9;
+const float STAT_ACTIVEWEAPON  = 10;
+const float STAT_TOTALSECRETS  = 11;
+const float STAT_TOTALMONSTERS = 12;
+const float STAT_SECRETS               = 13;
+const float STAT_MONSTERS              = 14;
+const float STAT_ITEMS         = 15;
+const float STAT_VIEWHEIGHT    = 16;
+
+// Quake Sound Constants
+const float CHAN_AUTO                  = 0;
+const float CHAN_WEAPON                        = 1;
+const float CHAN_VOICE                 = 2;
+const float CHAN_ITEM                  = 3;
+const float CHAN_BODY                  = 4;
+
+const float ATTN_NONE                  = 0;
+const float ATTN_NORM                  = 1;
+const float ATTN_IDLE                  = 2;
+const float ATTN_STATIC                        = 3;
+
+// Frik File Constants
+const float FILE_READ                  = 0;
+const float FILE_APPEND                        = 1;
+const float FILE_WRITE                 = 2;
+
+// Quake Point Contents
+const float CONTENT_EMPTY                                      = -1;
+const float CONTENT_SOLID                                      = -2;
+const float CONTENT_WATER                                      = -3;
+const float CONTENT_SLIME                                      = -4;
+const float CONTENT_LAVA                                       = -5;
+const float CONTENT_SKY                                                = -6;
+
+// Quake Solid Constants
+const float SOLID_NOT                                          = 0;
+const float SOLID_TRIGGER                                      = 1;
+const float SOLID_BBOX                                         = 2;
+const float SOLID_SLIDEBOX                                     = 3;
+const float SOLID_BSP                                          = 4;
+const float SOLID_CORPSE                                       = 5;
+
+// Quake Move Constants
+const float MOVE_NORMAL                                                = 0;
+const float MOVE_NOMONSTERS                                    = 1;
+const float MOVE_MISSILE                                       = 2;
+
+// Boolean Constants
+const float true       = 1;
+const float false      = 0;
+const float TRUE       = 1;
+const float FALSE      = 0;
+
+const float EXTRA_LOW = -99999999;
+const float EXTRA_HIGH = 99999999;
+
+const vector VEC_1     = '1 1 1';
+const vector VEC_0     = '0 0 0';
+const vector VEC_M1    = '-1 -1 -1';
+
+const float M_PI = 3.14159265358979323846;
+
+vector VEC_HULL_MIN = '-16 -16 -24';
+vector VEC_HULL_MAX = '16 16 32';
+
+// Quake Temporary Entity Constants
+const float TE_SPIKE                                           = 0;
+const float TE_SUPERSPIKE                                      = 1;
+const float TE_GUNSHOT                                         = 2;
+const float TE_EXPLOSION                                       = 3;
+const float TE_TAREXPLOSION                                    = 4;
+const float TE_LIGHTNING1                                      = 5;
+const float TE_LIGHTNING2                                      = 6;
+const float TE_WIZSPIKE                                                = 7;
+const float TE_KNIGHTSPIKE                                     = 8;
+const float TE_LIGHTNING3                                      = 9;
+const float TE_LAVASPLASH                                      = 10;
+const float TE_TELEPORT                                                = 11;
+const float TE_EXPLOSION2                                      = 12;
+       // Darkplaces Additions
+       const float TE_EXPLOSIONRGB                                     = 53;
+       const float TE_GUNSHOTQUAD                                      = 57;
+       const float TE_EXPLOSIONQUAD                            = 70;
+       const float TE_SPIKEQUAD                                        = 58;
+       const float TE_SUPERSPIKEQUAD                           = 59;
+
+// PFlags for Dynamic Lights
+const float PFLAGS_NOSHADOW                                    = 1;
+const float PFLAGS_CORONA                                      = 2;
+const float PFLAGS_FULLDYNAMIC                         = 128;
+
+const float EF_ADDITIVE                = 32;
+const float EF_BLUE            = 64;
+const float EF_FLAME           = 1024;
+const float EF_FULLBRIGHT      = 512;
+const float EF_NODEPTHTEST     = 8192;
+const float EF_NODRAW          = 16;
+const float EF_NOSHADOW                = 4096;
+const float EF_RED             = 128;
+const float EF_STARDUST                = 2048;
+const float EF_SELECTABLE      = 16384;
+
+const float PFL_ONGROUND       = 1;
+const float PFL_CROUCH         = 2;
+const float PFL_DEAD           = 4;
+const float PFL_GIBBED         = 8;
+
+// draw flags
+const float DRAWFLAG_NORMAL = 0;
+const float DRAWFLAG_ADDITIVE = 1;
+const float DRAWFLAG_MODULATE = 2;
+const float DRAWFLAG_2XMODULATE = 3;
+const float DRAWFLAG_SCREEN = 4;
+const float DRAWFLAG_MIPMAP = 0x100; // only for R_BeginPolygon
+
+/*
+==============================================================================
+
+                       BUILTIN DEFINITIONS
+                       EXTENSIONS ARE NOT ADDED HERE, BUT BELOW!
+
+==============================================================================
+*/
+
+void(vector ang) makevectors = #1;
+void(entity e, vector o) setorigin = #2;
+void(entity e, string m) setmodel = #3;
+void(entity e, vector min, vector max) setsize = #4;
+
+void() break_to_debugger = #6;
+float() random = #7;
+void(entity e, float chan, string samp) sound = #8;
+vector(vector v) normalize = #9;
+void(string e) error = #10;
+void(string e) objerror = #11;
+float(vector v) vlen = #12;
+float(vector v) vectoyaw = #13;
+entity() spawn = #14;
+void(entity e) remove = #15;
+float(vector v1, vector v2, float tryents, entity ignoreentity) traceline = #16;
+
+entity(entity start, .string fld, string match) find = #18;
+void(string s) precache_sound = #19;
+void(string s) precache_model = #20;
+
+entity(vector org, float rad) findradius = #22;
+
+void(string s, ...) dprint = #25;
+string(float f) ftos = #26;
+string(vector v) vtos = #27;
+void() coredump = #28;
+void() traceon = #29;
+void() traceoff = #30;
+void(entity e) eprint = #31;
+// settrace optional
+float(float yaw, float dist, float settrace) walkmove = #32;
+
+float() droptofloor = #34;
+void(float style, string value) lightstyle = #35;
+float(float v) rint = #36;
+float(float v) floor = #37;
+float(float v) ceil = #38;
+
+float(entity e) checkbottom = #40;
+float(vector v) pointcontents = #41;
+
+float(float f) fabs = #43;
+
+float(string s) cvar = #45;
+void(string s, ...) localcmd = #46;
+entity(entity e) nextent = #47;
+void(vector o, vector d, float color, float count) particle = #48;
+void() ChangeYaw = #49;
+
+vector(vector v) vectoangles = #51;
+vector(vector v, vector w) vectoangles2 = #51;
+
+float(float f) sin = #60;
+float(float f) cos = #61;
+float(float f) sqrt = #62;
+void(entity ent) changepitch = #63;
+void(entity e, entity ignore) tracetoss = #64;
+string(entity ent) etos = #65;
+
+string(string s) precache_file = #68;
+void(entity e) makestatic = #69;
+
+void(string var, string val) cvar_set = #72;
+
+void(vector pos, string samp, float vol, float atten) ambientsound = #74;
+string(string s) precache_model2 = #75;
+string(string s) precache_sound2 = #76;
+string(string s) precache_file2 = #77;
+
+float(string s) stof = #81;
+
+
+void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox = #90;
+vector() randomvec = #91;
+vector(vector org) getlight = #92;
+vector(vector org, float lpflags) getlight2 = #92;
+vector getlight_dir;
+vector getlight_ambient;
+vector getlight_diffuse;
+const float LP_LIGHTMAP        = 1;
+const float LP_RTWORLD = 2;
+const float LP_DYNLIGHT = 4;
+const float LP_COMPLETE = 7;
+
+float(string name, string value) registercvar = #93;
+float( float a, ... ) min = #94;
+float( float b, ... ) max = #95;
+float(float minimum, float val, float maximum) bound = #96;
+float(float f, float f) pow = #97;
+entity(entity start, .float fld, float match) findfloat = #98;
+entity(entity start, .entity fld, entity match) findentity = #98;
+float(string s) checkextension = #99;
+// FrikaC and Telejano range #100-#199
+
+float(string filename, float mode) fopen = #110;
+void(float fhandle) fclose = #111;
+string(float fhandle) fgets = #112;
+void(float fhandle, string s) fputs = #113;
+float(string s) strlen = #114;
+string(...) strcat = #115;
+string(string s, float start, float length) substring = #116;
+vector(string) stov = #117;
+string(string s) strzone = #118;
+void(string s) strunzone = #119;
+
+// FTEQW range #200-#299
+
+float(float number, float quantity) bitshift = #218;
+
+//float(string str, string sub[, float startpos]) strstrofs = #221;
+float(string str, string sub, float startpos) strstrofs = #221;
+float(string str, float ofs) str2chr = #222;
+string(float c, ...) chr2str = #223;
+string(float ccase, float calpha, float cnum, string s, ...) strconv = #224;
+string(float chars, string s, ...) strpad = #225;
+string(string info, string key, string value, ...) infoadd = #226;
+string(string info, string key) infoget = #227;
+float(string s1, string s2) strcmp = #228;
+float(string s1, string s2, float len) strncmp = #228;
+float(string s1, string s2) strcasecmp = #229;
+float(string s1, string s2, float len) strncasecmp = #230;
+
+// CSQC range #300-#399
+void() clearscene = #300;
+void(float mask) addentities = #301;
+void(entity ent) addentity = #302;
+float(float property, ...) setproperty = #303;
+float(float property) getproperty = #309;
+vector(float property) getpropertyvec = #309;
+void() renderscene = #304;
+void(vector org, float radius, vector lightcolours) adddynamiclight = #305;
+void(vector org, float radius, vector lightcolours, float style, string cubemapname, float pflags) adddynamiclight2 = #305;
+//void(string texturename, float flag[, float is2d, float lines]) R_BeginPolygon = #306;
+void(string texturename, float flag, ...) R_BeginPolygon = #306;
+void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex = #307;
+void() R_EndPolygon = #308;
+vector (vector v) cs_unproject = #310;
+vector (vector v) cs_project = #311;
+
+void(float width, vector pos1, vector pos2, float flag) drawline = #315;
+float(string name) iscachedpic = #316;
+string(string name, ...) precache_pic = #317;
+string(string name) precache_cubemap = #317;
+vector(string picname) draw_getimagesize = #318;
+void(string name) freepic = #319;
+float(vector position, float character, vector scale, vector rgb, float alpha, float flag) drawcharacter = #320;
+float(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawstring = #321;
+float(vector position, string pic, vector size, vector rgb, float alpha, float flag) drawpic = #322;
+float(vector position, vector size, vector rgb, float alpha, float flag) drawfill = #323;
+void(float x, float y, float width, float height) drawsetcliparea = #324;
+void(void) drawresetcliparea = #325;
+float(vector position, string text, vector scale, float alpha, float flag) drawcolorcodedstring = #326;
+vector(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawcolorcodedstring2 = #326;
+
+float(float stnum) getstatf = #330;
+float(float stnum, ...) getstati = #331; // can optionally take first bit and count
+string(float firststnum) getstats = #332;
+void(entity e, float mdlindex) setmodelindex = #333;
+string(float mdlindex) modelnameforindex = #334;
+float(string effectname) particleeffectnum = #335;
+void(entity ent, float effectnum, vector start, vector end) trailparticles = #336;
+//void(float effectnum, vector origin [, vector dir, float count]) pointparticles = #337;
+void(float effectnum, vector origin , vector dir, float count) pointparticles = #337;
+void(string s, ...) centerprint = #338;
+void(string s, ...) print = #339;
+string(float keynum) keynumtostring = #340;
+float(string keyname) stringtokeynum = #341;
+string(float keynum) getkeybind = #342;
+void(float usecursor) setcursormode = #343;
+vector() getmousepos = #344;
+float(float framenum) getinputstate = #345;
+void(float sens) setsensitivityscale = #346;
+void(...) runstandardplayerphysics = #347; // this may or may not take a player ent
+string(float playernum, string keyname) getplayerkeyvalue = #348;
+float() isdemo = #349;
+float() isserver = #350;
+void(vector origin, vector forward, vector right, vector up) SetListener = #351;
+void(string cmdname) registercommand = #352;
+float(entity ent) wasfreed = #353;
+string(string key) serverkey = #354;
+
+// Use proper case; refer to the id1 Write* functions!
+float() ReadByte = #360;
+float() ReadChar = #361;
+float() ReadShort = #362;
+float() ReadLong = #363;
+float() ReadCoord = #364;
+float() ReadAngle = #365;
+string() ReadString = #366;
+float() ReadFloat = #367;
+
+// LordHavoc's range #400-#499
+void(entity from, entity to) copyentity = #400;
+
+entity(.string fld, string match) findchain = #402;
+entity(.float fld, float match) findchainfloat = #403;
+void(vector org, string modelname, float startframe, float endframe, float framerate) effect = #404;
+void(vector org, vector velocity, float howmany) te_blood = #405;
+void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower = #406;
+void(vector org, vector color) te_explosionrgb = #407;
+void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube = #408;
+void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain = #409;
+void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow = #410;
+void(vector org, vector vel, float howmany) te_spark = #411;
+void(vector org) te_gunshotquad = #412;
+void(vector org) te_spikequad = #413;
+void(vector org) te_superspikequad = #414;
+void(vector org) te_explosionquad = #415;
+void(vector org) te_smallflash = #416;
+void(vector org, float radius, float lifetime, vector color) te_customflash = #417;
+void(vector org) te_gunshot = #418;
+void(vector org) te_spike = #419;
+void(vector org) te_superspike = #420;
+void(vector org) te_explosion = #421;
+void(vector org) te_tarexplosion = #422;
+void(vector org) te_wizspike = #423;
+void(vector org) te_knightspike = #424;
+void(vector org) te_lavasplash = #425;
+void(vector org) te_teleport = #426;
+void(vector org, float colorstart, float colorlength) te_explosion2 = #427;
+void(entity own, vector start, vector end) te_lightning1 = #428;
+void(entity own, vector start, vector end) te_lightning2 = #429;
+void(entity own, vector start, vector end) te_lightning3 = #430;
+void(entity own, vector start, vector end) te_beam = #431;
+void(vector dir) vectorvectors = #432;
+void(vector org) te_plasmaburn = #433;
+float(entity e, float s) getsurfacenumpoints = #434;
+vector(entity e, float s, float n) getsurfacepoint = #435;
+vector(entity e, float s) getsurfacenormal = #436;
+string(entity e, float s) getsurfacetexture = #437;
+float(entity e, vector p) getsurfacenearpoint = #438;
+vector(entity e, float s, vector p) getsurfaceclippedpoint = #439;
+
+float(string s) tokenize = #441;
+string(float n) argv = #442;
+void(entity e, entity tagentity, string tagname) setattachment = #443;
+float(string pattern, float caseinsensitive, float quiet) search_begin = #444;
+void(float handle) search_end = #445;
+float(float handle) search_getsize = #446;
+string(float handle, float num) search_getfilename = #447;
+string(string s) cvar_string = #448;
+entity(entity start, .float fld, float match) findflags = #449;
+entity(.float fld, float match) findchainflags = #450;
+float(entity ent, string tagname) gettagindex = #451;
+vector(entity ent, float tagindex) gettaginfo = #452;
+
+void(vector org, vector vel, float howmany) te_flamejet = #457;
+
+entity(float num) entitybyindex = #459;
+float() buf_create = #460;
+void(float bufhandle) buf_del = #461;
+float(float bufhandle) buf_getsize = #462;
+void(float bufhandle_from, float bufhandle_to) buf_copy = #463;
+void(float bufhandle, float sortpower, float backward) buf_sort = #464;
+string(float bufhandle, string glue) buf_implode = #465;
+string(float bufhandle, float string_index) bufstr_get = #466;
+void(float bufhandle, float string_index, string str) bufstr_set = #467;
+float(float bufhandle, string str, float order) bufstr_add = #468;
+void(float bufhandle, float string_index) bufstr_free = #469;
+
+float(float s) asin = #471;
+float(float c) acos = #472;
+float(float t) atan = #473;
+float(float c, float s) atan2 = #474;
+float(float a) tan = #475;
+float(string s) strippedstringlen = #476;
+float(string s) strlennocol = #476; // This is the correct name for the function, but not removing the decolorizedstring mapping.
+string(string s) decolorizedstring = #477;
+string(string s) strdecolorize = #477; // This is the correct name for the function, but not removing the decolorizedstring mapping.
+string(float uselocaltime, string format, ...) strftime = #478;
+string(string s) strtolower = #480;
+string(string s) strtoupper = #481;
+string(string s) cvar_defstring = #482;
+void(vector origin, string sample, float volume, float attenuation) pointsound = #483;
+string(string search, string replace, string subject) strreplace = #484;
+string(string search, string replace, string subject) strireplace = #485;
+vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
+#ifdef SUPPORT_GECKO
+float gecko_create( string name ) = #487;
+void gecko_destroy( string name ) = #488;
+void gecko_navigate( string name, string URI ) = #489;
+float gecko_keyevent( string name, float key, float eventtype ) = #490;
+void gecko_mousemove( string name, float x, float y ) = #491;
+void gecko_resize( string name, float w, float h ) = #492;
+vector gecko_get_texture_extent( string name ) = #493;
+#else
+
+#endif
+
+/*
+==============================================================================
+
+                       EXTENSION DEFINITIONS
+
+==============================================================================
+*/
+
+// DP_CSQC_SPAWNPARTICLE
+// idea: VorteX
+// darkplaces implementation: VorteX
+// constant definitions:
+// particle base behavior:
+float PT_ALPHASTATIC = 1;
+float PT_STATIC = 2;
+float PT_SPARK = 3;
+float PT_BEAM = 4;
+float PT_RAIN = 5;
+float PT_RAINDECAL = 6;
+float PT_SNOW = 7;
+float PT_BUBBLE = 8;
+float PT_BLOOD = 9;
+float PT_SMOKE = 10;
+float PT_DECAL = 11;
+float PT_ENTITYPARTICLE = 12;
+// particle blendtypes:
+float PBLEND_ALPHA = 0;
+float PBLEND_ADD = 1;
+float PBLEND_INVMOD = 2;
+// particle orientation:
+float PARTICLE_BILLBOARD = 0;
+float PARTICLE_SPARK = 1;
+float PARTICLE_ORIENTED_DOUBLESIDED = 2;
+float PARTICLE_BEAM = 3;
+// global definitions:
+float particle_type; // one of PT_
+float particle_blendmode; // one of PBLEND_ values
+float particle_orientation; // one of PARTICLE_ values
+vector particle_color1;
+vector particle_color2;
+float particle_tex; // number of chunk in particlefont
+float particle_size;
+float particle_sizeincrease;
+float particle_alpha;
+float particle_alphafade;
+float particle_time;
+float particle_gravity;
+float particle_bounce;
+float particle_airfriction;
+float particle_liquidfriction;
+float particle_originjitter;
+float particle_velocityjitter;
+float particle_qualityreduction; // enable culling of this particle when FPS is low
+float particle_stretch;
+vector particle_staincolor1;
+vector particle_staincolor2;
+float particle_staintex;
+float particle_stainalpha;
+float particle_stainsize;
+float particle_delayspawn;
+float particle_delaycollision;
+float particle_angle;
+float particle_spin;
+// builtin definitions:
+float(float max_themes) initparticlespawner = #522; // check fields/globals for integration and enable particle spawner, return 1 is succeded, otherwise returns 0
+void() resetparticle = #523; // reset p_ globals to default theme #0
+void(float theme) particletheme = #524; // restore p_ globals from saved theme
+float() particlethemesave = #525; // save p_ globals to new particletheme and return it's index
+void(float theme) particlethemeupdate = #525; // save p_ globals to new particletheme and return it's index
+void(float theme) particlethemefree = #526; // delete a particle theme
+float(vector org, vector vel) spawnparticle = #527; // returns 0 when failed, 1 when spawned
+float(vector org, vector vel, float theme) quickparticle = #527; // not reading globals, just theme, returns 0 when failed, 1 when spawned
+float(vector org, vector vel, float delay, float collisiondelay) delayedparticle = #528;
+float(vector org, vector vel, float delay, float collisiondelay, float theme) quickdelayedparticle = #528;
+// description: this builtin provides an easy and flexible way to spawn particles,
+// it is not created as replace for DP_SV_POINTPARTICLES but as an addition to it.
+// With this extension you can create a specific particles like rain particles, or entity particles
+// notes:
+// 1) 0 is default particle template, it could be changed
+// 2) color vectors could have value 0-255 of each component
+// restrictions: max themes could be between 4 and 2048
+// warning: you should call initparticlespawner() at very beginning BEFORE all other particle spawner functions
+// function to query particle info
+// don't remove this function as it protects all particle_ globals from FTEQCC/FRIKQCC non-referenced removal optimisation
+void() printparticle =
+{
+       // vortex: this also protects from 'non-referenced' optimisation on some compilers
+       print("PARTICLE:\n");
+       print(strcat("  type: ", ftos(particle_type), "\n"));
+       print(strcat("  blendmode: ", ftos(particle_blendmode), "\n"));
+       print(strcat("  orientation: ", ftos(particle_orientation), "\n"));
+       print(strcat("  color1: ", vtos(particle_color1), "\n"));
+       print(strcat("  color2: ", vtos(particle_color2), "\n"));
+       print(strcat("  tex: ", ftos(particle_tex), "\n"));
+       print(strcat("  size: ", ftos(particle_size), "\n"));
+       print(strcat("  sizeincrease: ", ftos(particle_sizeincrease), "\n"));
+       print(strcat("  alpha: ", ftos(particle_alpha), "\n"));
+       print(strcat("  alphafade: ", ftos(particle_alphafade), "\n"));
+       print(strcat("  time: ", ftos(particle_time), "\n"));
+       print(strcat("  gravity: ", ftos(particle_gravity), "\n"));
+       print(strcat("  bounce: ", ftos(particle_bounce), "\n"));
+       print(strcat("  airfriction: ", ftos(particle_airfriction), "\n"));
+       print(strcat("  liquidfriction: ", ftos(particle_liquidfriction), "\n"));
+       print(strcat("  originjitter: ", ftos(particle_originjitter), "\n"));
+       print(strcat("  velocityjitter: ", ftos(particle_velocityjitter), "\n"));
+       print(strcat("  qualityreduction: ", ftos(particle_qualityreduction), "\n"));
+       print(strcat("  stretch: ", ftos(particle_stretch), "\n"));
+       print(strcat("  staincolor1: ", vtos(particle_staincolor1), "\n"));
+       print(strcat("  staincolor2: ", vtos(particle_staincolor2), "\n"));
+       print(strcat("  staintex: ", ftos(particle_staintex), "\n"));
+       print(strcat("  stainalpha: ", ftos(particle_stainalpha), "\n"));
+       print(strcat("  stainsize: ", ftos(particle_stainsize), "\n"));
+       print(strcat("  delayspawn: ", ftos(particle_delayspawn), "\n"));
+       print(strcat("  delaycollision: ", ftos(particle_delaycollision), "\n"));
+       print(strcat("  angle: ", ftos(particle_angle), "\n"));
+       print(strcat("  spin: ", ftos(particle_spin), "\n"));
+}
+
+// DP_CSQC_ENTITYTRANSPARENTSORTING_OFFSET
+// idea: VorteX
+// darkplaces implementation: VorteX
+float RF_USETRANSPARENTOFFSET = 64; // enables transparent origin offsetting
+// global definitions
+float transparent_offset; // should be set before entity is added
+// description: offset a model's meshes origin used for transparent sorting. Could be used to tweak sorting bugs on very large transparent entities or hacking transparent sorting order for certain objects
+// example: transparent_offset = 1000000; // entity always appear on background of other transparents
+// note: offset is done in view forward axis
+
+// DP_CSQC_ENTITYWORLDOBJECT
+// idea: VorteX
+// darkplaces implementation: VorteX
+const float RF_WORLDOBJECT = 128;
+// description: when renderflag is set, engine will not use culling methods for this entity, e.g. it will always be drawn
+// useful for large outdoor objects (like asteroids on sky horizon or sky models)
+
+// DP_CSQC_ENTITYMODELLIGHT
+// idea: VorteX
+// darkplaces implementation: VorteX
+const float RF_MODELLIGHT = 4096;
+.vector modellight_ambient;
+.vector modellight_diffuse;
+.vector modellight_dir;
+// description: allows CSQC to override directional model lightning on entity
+
+// DP_CSQC_SETPAUSE
+// idea: VorteX
+// darkplaces implementation: VorteX
+// builtin definitions:
+void(float ispaused) setpause = #531;
+// description: provides ability to set pause in local games (similar to one set once console is activated)
+// not stopping sound/cd track, useful for inventory screens, ingame menus with input etc.
+
+// DP_CSQC_QUERYRENDERENTITY
+// idea: VorteX
+// darkplaces implementation: VorteX
+// constant definitions:
+// render entity fields:
+float E_ACTIVE             = 0; // float 0/1
+float E_ORIGIN      = 1; // vector
+float E_FORWARD     = 2; // vector
+float E_RIGHT       = 3; // vector
+float E_UP          = 4; // vector
+float E_SCALE       = 5; // float
+float E_ORIGINANDVECTORS = 6; // returns origin, + sets v_* vectors to orientation
+float E_ALPHA       = 7; // float
+float E_COLORMOD    = 8; // vector
+float E_PANTSCOLOR  = 9; // vector
+float E_SHIRTCOLOR  = 10; // vector
+float E_SKIN        = 11; // float
+float E_MINS        = 12; // vector
+float E_MAXS        = 13; // vector
+float E_ABSMIN      = 14; // vector
+float E_ABSMAX      = 15; // vector
+float E_LIGHT       = 16; // vector - modellight
+// builtin definitions:
+float(float entitynum, float fldnum) getentity = #504;
+vector(float entitynum, float fldnum) getentityvec = #504;
+// description: allows to query parms from render entities, especially useful with attaching CSQC ents to
+// server entities networked and interpolated by engine (monsters, players), number of entity is it's SVQC number
+// you can send it via tempentity/CSQC entity message. Note that this builtin doesnt know about entity removing/reallocating
+// so it's meaning to work for short period of time, dont use it on missiles/grenades whatever will be removed next five seconds
+
+//DP_GFX_FONTS
+//idea: Blub\0, divVerent
+//darkplaces implementation: Blub\0
+//console commands:
+//  loadfont fontname fontmaps size1 size2 ...
+//   A font can simply be gfx/tgafile (freetype fonts doent need extension),
+//   or alternatively you can specify multiple fonts and faces
+//   Like this: gfx/vera-sans:2,gfx/fallback:1
+//   to load face 2 of the font gfx/vera-sans and use face 1
+//   of gfx/fallback as fallback font
+//   You can also specify a list of font sizes to load, like this:
+//   loadfont console gfx/conchars,gfx/fallback 8 12 16 24 32
+//   In many cases, 8 12 16 24 32 should be a good choice.
+//   for slots see:
+//constant definitions:
+float drawfont;            // set it before drawstring()/drawchar() calls
+float FONT_DEFAULT = 0;    // 'default'
+float FONT_CONSOLE = 1;    // 'console', REALLY should be fixed width (ls!)
+float FONT_SBAR = 2;       // 'sbar', used on hud, must be fixed width
+float FONT_NOTIFY = 3;     // 'notify', used on sprint/bprint
+float FONT_CHAT = 4;       // 'chat'
+float FONT_CENTERPRINT = 5;// 'centerprint'
+float FONT_INFOBAR = 6;    // 'infobar'
+float FONT_MENU = 7;       // 'menu', should be fixed width
+float FONT_USER0 = 8;      // 'user0', userdefined fonts
+float FONT_USER1 = 9;      // 'user1', userdefined fonts
+float FONT_USER2 = 10;     // 'user2', userdefined fonts
+float FONT_USER3 = 11;     // 'user3', userdefined fonts
+float FONT_USER4 = 12;     // 'user4', userdefined fonts
+float FONT_USER5 = 13;     // 'user5', userdefined fonts
+float FONT_USER6 = 14;     // 'user6', userdefined fonts
+float FONT_USER7 = 15;     // 'user7' slot, userdefined fonts
+//builtin definitions:
+float findfont(string s) = #356; // find font by fontname and return it's index
+float loadfont(string fontname, string fontmaps, string sizes, float slot, float fix_scale, float fix_voffset) = #357;
+// loads font immediately so stringwidth() function can be used just after builtin call
+// returns a font slotnum (which is used to set drawfont to)
+// first 3 parms are identical to "loadfont" console command ones
+// slot could be one of FONT_ constants or result of findfont() or -1 to not use it
+// if slot is given, font will be loaded to this slotnum and fontname become new title for it
+// this way you can rename user* fonts to something more usable
+// fix_* parms let you fix badly made fonts by applying some transformations to them
+// fix_scale : per-character center-oriented scale (doesn't change line height at all)
+// fix_voffset : vertical offset for each character, it's a multiplier to character height
+float stringwidth(string text, float allowColorCodes, vector size) = #327; // get a width of string with given font and char size
+float stringwidth_menu(string text, float allowColorCodes, vector size) = #468; // in menu.dat it has different builtin #
+//description: engine support for custom fonts in console, hud, qc etc.
+// limits:
+//  max 128 chars for font name
+//  max 3 font fallbacks
+//  max 8 sizes per font
+
+//DP_GFX_FONTS_FREETYPE
+//idea: Blub\0, divVerent
+//darkplaces implementation: Blub\0
+//cvar definitions:
+//   r_font_disable_freetype 0/1 : disable freetype fonts loading (uttetly disables freetype library initialization)
+//   r_font_antialias 0/1 : antialiasing when loading font
+//   r_font_hint 0/1/2/3  : hinting when loading font, 0 is no hinting, 1 light autohinting , 2 full autohinting, 3 full hinting
+//   r_font_postprocess_blur X      : font outline blur amount
+//   r_font_postprocess_outline X   : font outline width
+//   r_font_postprocess_shadow_x X  : font outline shadow x shift amount, applied during outlining
+//   r_font_postprocess_shadow_y X  : font outline shadow y shift amount, applied during outlining
+//   r_font_postprocess_shadow_z X  : font outline shadow z shift amount, applied during blurring
+//description: engine support for truetype/freetype fonts
+//so .AFM+.PFB/.OTF/.TTF files could be stuffed as fontmaps in loadfont()
+//(console command version will support them as well)
+
+//DP_CSQC_BINDMAPS
+//idea: daemon, motorsep
+//darkplaces implementation: divVerent
+//builtin definitions:
+string(float key, float bindmap) getkeybind_bindmap = #342;
+float(float key, string bind, float bindmap) setkeybind_bindmap = #630;
+vector(void) getbindmaps = #631;
+float(vector bm) setbindmaps = #632;
+string(string command, float bindmap) findkeysforcommand = #610;
+//<already in EXT_CSQC> float(string key) stringtokeynum = #341;
+//<already in EXT_CSQC> string(float keynum) keynumtostring = #340;
+//description: key bind setting/getting including support for switchable
+//bindmaps.
+
+//DP_CRYPTO
+//idea: divVerent
+//darkplaces implementation: divVerent
+//builtin definitions: (CSQC)
+float(string url, float id, string content_type, string delim, float buf, float keyid) crypto_uri_postbuf = #513;
+//description:
+//use -1 as buffer handle to justs end delim as postdata
+
+//DP_CSQC_MAINVIEW
+//idea: divVerent
+//darkplaces implementation: divVerent
+//constant definitions:
+const float VF_MAINVIEW         = 400;
+//use setproperty(VF_MAINVIEW, 1); before calling R_RenderView for the render
+//that shall become the "main" view, which is e.g. used by PRYDON_CLIENTCURSOR
+//this flag is set for the first scene, and not cleared by R_ClearScene
+//this flag is automatically cleared by R_RenderView
+//so when not using this extension, the first view rendered is the main view
+
+//DP_CSQC_MINFPS_QUALITY
+//idea: divVerent
+//darkplaces implementation: divVerent
+//constant definitions:
+const float VF_MINFPS_QUALITY   = 401;
+//use getproperty(VF_MINFPS_QUALITY); to do CSQC based LOD based on cl_minfps
+//1 should lead to an unmodified view
+
+//DP_CSQC_V_CALCREFDEF_WIP1
+//DP_CSQC_V_CALCREFDEF_WIP2
+//idea: divVerent
+//darkplaces implementation: divVerent
+//builtin definitions:
+void(entity e, float refdefflags) V_CalcRefdef = #640;
+//constant definitions:
+float PMF_DUCKED = 4;
+float PMF_ONGROUND = 8;
+float REFDEFFLAG_TELEPORTED = 1;
+float REFDEFFLAG_JUMPING = 2;
+float REFDEFFLAG_DEAD = 4;
+float REFDEFFLAG_INTERMISSION = 8;
+//- use this on the player entity after performing prediction
+//- pass REFDEFFLAG_TELEPORTED if the player teleported since last frame
+//- pass REFDEFFLAG_JUMPING if jump button is pressed
+//- pass REFDEFFLAG_DEAD if dead (DP_CSQC_V_CALCREFDEF_WIP2)
+//- pass REFDEFFLAG_INTERMISSION if in intermission (DP_CSQC_V_CALCREFDEF_WIP2)
+//- the player entity needs to have origin, velocity, pmove_flags set according
+//  to prediction (the above two PMF_ flags are used in the player's pmove_flags)
+//- NOTE: to check for this, ALSO OR a check with DP_CSQC_V_CALCREFDEF to also support
+//  the finished extension once done
+
+// assorted builtins
+float  drawsubpic(vector position, vector size, string pic, vector srcPosition, vector srcSize, vector rgb, float alpha, float flag) = #328;
+vector drawgetimagesize(string pic) = #318;
+#define SPA_POSITION 0
+#define SPA_S_AXIS 1
+#define SPA_T_AXIS 2
+#define SPA_R_AXIS 3
+#define SPA_TEXCOORDS0 4
+#define SPA_LIGHTMAP0_TEXCOORDS 5
+#define SPA_LIGHTMAP_COLOR 6
+// float (entity e, float s)                                           getsurfacenumpoints = #434;
+// vector (entity e, float s, float n)                                 getsurfacepoint = #435;
+// vector (entity e, float s)                                          getsurfacenormal = #436;
+// string (entity e, float s)                                          getsurfacetexture = #437;
+// float (entity e, vector p)                                          getsurfacenearpoint = #438;
+// vector (entity e, float s, vector p)                                        getsurfaceclippedpoint = #439;
+// vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
+float(entity e, float s) getsurfacenumtriangles = #628;
+vector(entity e, float s, float n) getsurfacetriangle = #629;
+
+//DP_QC_ASINACOSATANATAN2TAN
+//idea: Urre
+//darkplaces implementation: LordHavoc
+//constant definitions:
+float DEG2RAD = 0.0174532925199432957692369076848861271344287188854172545609719144;
+float RAD2DEG = 57.2957795130823208767981548141051703324054724665643215491602438612;
+float PI      = 3.1415926535897932384626433832795028841971693993751058209749445923;
+//builtin definitions:
+/* -Wdouble-declaration
+float(float s) asin = #471; // returns angle in radians for a given sin() value, the result is in the range -PI*0.5 to PI*0.5
+float(float c) acos = #472; // returns angle in radians for a given cos() value, the result is in the range 0 to PI
+float(float t) atan = #473; // returns angle in radians for a given tan() value, the result is in the range -PI*0.5 to PI*0.5
+float(float c, float s) atan2 = #474; // returns angle in radians for a given cos() and sin() value pair, the result is in the range -PI to PI (this is identical to vectoyaw except it returns radians rather than degrees)
+float(float a) tan = #475; // returns tangent value (which is simply sin(a)/cos(a)) for the given angle in radians, the result is in the range -infinity to +infinity
+*/
+//description:
+//useful math functions for analyzing vectors, note that these all use angles in radians (just like the cos/sin functions) not degrees unlike makevectors/vectoyaw/vectoangles, so be sure to do the appropriate conversions (multiply by DEG2RAD or RAD2DEG as needed).
+//note: atan2 can take unnormalized vectors (just like vectoyaw), and the function was included only for completeness (more often you want vectoyaw or vectoangles), atan2(v_x,v_y) * RAD2DEG gives the same result as vectoyaw(v)
+
+//DP_QC_SPRINTF
+//idea: divVerent
+//darkplaces implementation: divVerent
+//builtin definitions:
+string(string format, ...) sprintf = #627;
+//description:
+//you know sprintf :P
+//supported stuff:
+//  %
+//  optional: <argpos>$ for the argument to format (the arg counter then is not increased)
+//  flags: #0- +
+//  optional: <width>, *, or *<argpos>$ for the field width (width is read before value and precision)
+//  optional: .<precision>, .*, or .*<argpos>$ for the precision (precision is read before value)
+//  length modifiers: h for forcing a float, l for forcing an int/entity (by default, %d etc. cast a float to int)
+//  conversions:
+//    d takes a float if no length is specified or h is, and an int/entity if l is specified as length, and cast it to an int
+//    i takes an int/entity if no length is specified or i is, and a float if h is specified as length, and cast it to an int
+//    ouxXc take a float if no length is specified or h is, and an int/entity if l is specified as length, and cast it to an unsigned int
+//    eEfFgG take a float if no length is specified or h is, and an int/entity if l is specified as length, and cast it to a double
+//    s takes a string
+//    vV takes a vector, and processes the three components as if it were a gG for all three components, separated by space
+//    For conversions s and c, the flag # makes precision and width interpreted
+//      as byte count, by default it is interpreted as character count in UTF-8
+//      enabled engines. No other conversions can create wide characters, and #
+//      has another meaning in these.
+
+//DP_QC_GETTIME
+//idea: tZork
+//darkplaces implementation: tZork, divVerent
+//constant definitions:
+float GETTIME_FRAMESTART = 0; // time of start of frame
+float GETTIME_REALTIME = 1; // current time (may be OS specific)
+float GETTIME_HIRES = 2; // like REALTIME, but may reset between QC invocations and thus can be higher precision
+float GETTIME_UPTIME = 3; // time since start of the engine
+//builtin definitions:
+float(float tmr) gettime = #519;
+//description:
+//some timers to query...
+
+//DP_QC_GETTIME_CDTRACK
+//idea: divVerent
+//darkplaces implementation: divVerent
+//constant definitions:
+float GETTIME_CDTRACK = 4;
+//description:
+//returns the playing time of the current cdtrack when passed to gettime()
+//see DP_END_GETSOUNDTIME for similar functionality but for entity sound channels
+
+//DP_QC_TOKENIZEBYSEPARATOR
+//idea: Electro, SavageX, LordHavoc
+//darkplaces implementation: LordHavoc
+//builtin definitions:
+float(string s, string separator1, ...) tokenizebyseparator = #479;
+//description:
+//this function returns tokens separated by any of the supplied separator strings, example:
+//numnumbers = tokenizebyseparator("10.2.3.4", ".");
+//returns 4 and the tokens are "10" "2" "3" "4"
+//possibly useful for parsing IPv4 addresses (such as "1.2.3.4") and IPv6 addresses (such as "[1234:5678:9abc:def0:1234:5678:9abc:def0]:26000")
+
+//DP_QC_TOKENIZE_CONSOLE
+//idea: divVerent
+//darkplaces implementation: divVerent
+//builtin definitions:
+float(string s) tokenize_console = #514;
+float(float i) argv_start_index = #515;
+float(float i) argv_end_index = #516;
+//description:
+//this function returns tokens separated just like the console does
+//also, functions are provided to get the index of the first and last character of each token in the original string
+//Passing negative values to them, or to argv, will be treated as indexes from the LAST token (like lists work in Perl). So argv(-1) will return the LAST token.
+
+//DP_SND_SOUND7_WIP1
+//DP_SND_SOUND7_WIP2
+//idea: divVerent
+//darkplaces implementation: divVerent
+//builtin definitions:
+void(entity e, float chan, string samp, float vol, float atten, float speed, float flags) sound7 = #8;
+float SOUNDFLAG_RELIABLE = 1;
+//description:
+//plays a sound, with some more flags
+//extensions to sound():
+//- channel may be in the range from -128 to 127; channels -128 to 0 are "auto",
+//  i.e. support multiple sounds at once, but cannot be stopped/restarted
+//- a value 0 in the speed parameter means no change; otherwise, it is a
+//  percentage of playback speed ("pitch shifting"). 100 is normal pitch, 50 is
+//  half speed, 200 is double speed, etc. (DP_SND_SOUND7_WIP2)
+//- the flag SOUNDFLAG_RELIABLE can be specified, which makes the sound send
+//  to MSG_ALL (reliable) instead of MSG_BROADCAST (unreliable, default);
+//  similarily, SOUNDFLAG_RELIABLE_TO_ONE sends to MSG_ONE
+//- channel 0 is controlled by snd_channel0volume; channel 1 and -1 by
+//  snd_channel1volume, etc. (so, a channel shares the cvar with its respective
+//  auto-channel); however, the mod MUST define snd_channel8volume and upwards
+//  in default.cfg if they are to be used, as the engine does not create them
+//  to not litter the cvar list
+//- this extension applies to CSQC as well; CSQC_Event_Sound will get speed and
+//  flags as extra 7th and 8th argument
+//- WIP2 ideas: SOUNDFLAG_RELIABLE_TO_ONE, SOUNDFLAG_NOPHS, SOUNDFLAG_FORCELOOP
+//- NOTE: to check for this, ALSO OR a check with DP_SND_SOUND7 to also support
+//  the finished extension once done
+
+//DP_PRECACHE_PIC_FLAGS
+//idea: divVerent
+//darkplaces implementation: divVerent
+//constant definitions:
+float PRECACHE_PIC_FROMWAD = 1; // this one actually is part of EXT_CSQC
+float PRECACHE_PIC_NOTPERSISTENT = 2; // picture may get deallocated when unused
+float PRECACHE_PIC_MIPMAP = 8; // mipmap the texture for possibly better downscaling at memory expense
+//notes: these constants are given as optional second argument to precache_pic()
+
+//DP_QC_TRACE_MOVETYPE_WORLDONLY
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//constant definitions:
+float MOVE_WORLDONLY = 3;
+//description:
+//allows traces to hit only world (ignoring all entities, unlike MOVE_NOMONSTERS which hits all bmodels), use as the nomonsters parameter to trace functions
+
+//DP_SND_GETSOUNDTIME
+//idea: VorteX
+//darkplaces implementation: VorteX
+//constant definitions:
+float(entity e, float channel) getsoundtime = #533; // get currently sound playing position on entity channel, -1 if not playing or error
+float(string sample) soundlength = #534; // returns length of sound sample in seconds, -1 on error (sound not precached, sound system not initialized etc.)
+//description: provides opportunity to query length of sound samples and realtime tracking of sound playing on entities (similar to DP_GETTIME_CDTRACK)
+//note: beware dedicated server not running sound engine at all, so in dedicated mode this builtins will not work in server progs
+//note also: menu progs not supporting getsoundtime() (will give a warning) since it has no sound playing on entities
+//examples of use:
+//  - QC-driven looped sounds
+//  - QC events when sound playing is finished
+//  - toggleable ambientsounds
+//  - subtitles
+
+//DP_QC_NUM_FOR_EDICT
+//idea: Blub\0
+//darkplaces implementation: Blub\0
+//Function to get the number of an entity - a clean way.
+float(entity num) num_for_edict = #512;
+
+//DP_TRACE_HITCONTENTSMASK_SURFACEINFO
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//globals:
+.float dphitcontentsmask; // if non-zero on the entity passed to traceline/tracebox/tracetoss this will override the normal collidable contents rules and instead hit these contents values (for example AI can use tracelines that hit DONOTENTER if it wants to, by simply changing this field on the entity passed to traceline), this affects normal movement as well as trace calls
+float trace_dpstartcontents; // DPCONTENTS_ value at start position of trace
+float trace_dphitcontents; // DPCONTENTS_ value of impacted surface (not contents at impact point, just contents of the surface that was hit)
+float trace_dphitq3surfaceflags; // Q3SURFACEFLAG_ value of impacted surface
+string trace_dphittexturename; // texture name of impacted surface
+//constants:
+float DPCONTENTS_SOLID = 1; // hit a bmodel, not a bounding box
+float DPCONTENTS_WATER = 2;
+float DPCONTENTS_SLIME = 4;
+float DPCONTENTS_LAVA = 8;
+float DPCONTENTS_SKY = 16;
+float DPCONTENTS_BODY = 32; // hit a bounding box, not a bmodel
+float DPCONTENTS_CORPSE = 64; // hit a SOLID_CORPSE entity
+float DPCONTENTS_NODROP = 128; // an area where backpacks should not spawn
+float DPCONTENTS_PLAYERCLIP = 256; // blocks player movement
+float DPCONTENTS_MONSTERCLIP = 512; // blocks monster movement
+float DPCONTENTS_DONOTENTER = 1024; // AI hint brush
+float DPCONTENTS_LIQUIDSMASK = 14; // WATER | SLIME | LAVA
+float DPCONTENTS_BOTCLIP = 2048; // AI hint brush
+float DPCONTENTS_OPAQUE = 4096; // only fully opaque brushes get this (may be useful for line of sight checks)
+float Q3SURFACEFLAG_NODAMAGE = 1;
+float Q3SURFACEFLAG_SLICK = 2; // low friction surface
+float Q3SURFACEFLAG_SKY = 4; // sky surface (also has NOIMPACT and NOMARKS set)
+float Q3SURFACEFLAG_LADDER = 8; // climbable surface
+float Q3SURFACEFLAG_NOIMPACT = 16; // projectiles should remove themselves on impact (this is set on sky)
+float Q3SURFACEFLAG_NOMARKS = 32; // projectiles should not leave marks, such as decals (this is set on sky)
+float Q3SURFACEFLAG_FLESH = 64; // projectiles should do a fleshy effect (blood?) on impact
+float Q3SURFACEFLAG_NODRAW = 128; // compiler hint (not important to qc)
+//float Q3SURFACEFLAG_HINT = 256; // compiler hint (not important to qc)
+//float Q3SURFACEFLAG_SKIP = 512; // compiler hint (not important to qc)
+//float Q3SURFACEFLAG_NOLIGHTMAP = 1024; // compiler hint (not important to qc)
+//float Q3SURFACEFLAG_POINTLIGHT = 2048; // compiler hint (not important to qc)
+float Q3SURFACEFLAG_METALSTEPS = 4096; // walking on this surface should make metal step sounds
+float Q3SURFACEFLAG_NOSTEPS = 8192; // walking on this surface should not make footstep sounds
+float Q3SURFACEFLAG_NONSOLID = 16384; // compiler hint (not important to qc)
+//float Q3SURFACEFLAG_LIGHTFILTER = 32768; // compiler hint (not important to qc)
+//float Q3SURFACEFLAG_ALPHASHADOW = 65536; // compiler hint (not important to qc)
+//float Q3SURFACEFLAG_NODLIGHT = 131072; // compiler hint (not important to qc)
+//float Q3SURFACEFLAG_DUST = 262144; // translucent 'light beam' effect (not important to qc)
+//description:
+//adds additional information after a traceline/tracebox/tracetoss call.
+//also (very important) sets trace_* globals before calling .touch functions,
+//this allows them to inspect the nature of the collision (for example
+//determining if a projectile hit sky), clears trace_* variables for the other
+//object in a touch event (that is to say, a projectile moving will see the
+//trace results in its .touch function, but the player it hit will see very
+//little information in the trace_ variables as it was not moving at the time)
+
+//DP_QC_CVAR_TYPE
+//idea: divVerent
+//DarkPlaces implementation: divVerent
+//builtin definitions:
+float(string name) cvar_type = #495;
+float CVAR_TYPEFLAG_EXISTS = 1;
+float CVAR_TYPEFLAG_SAVED = 2;
+float CVAR_TYPEFLAG_PRIVATE = 4;
+float CVAR_TYPEFLAG_ENGINE = 8;
+float CVAR_TYPEFLAG_HASDESCRIPTION = 16;
+float CVAR_TYPEFLAG_READONLY = 32;
+
+//DP_QC_CRC16
+//idea: divVerent
+//darkplaces implementation: divVerent
+//Some hash function to build hash tables with. This has to be be the CRC-16-CCITT that is also required for the QuakeWorld download protocol.
+//When caseinsensitive is set, the CRC is calculated of the lower cased string.
+float(float caseinsensitive, string s, ...) crc16 = #494;
+
+//DP_QC_URI_ESCAPE
+//idea: divVerent
+//darkplaces implementation: divVerent
+//URI::Escape's functionality
+string(string in) uri_escape = #510;
+string(string in) uri_unescape = #511;
+
+//DP_QC_DIGEST
+//idea: motorsep, Spike
+//DarkPlaces implementation: divVerent
+//builtin definitions:
+string(string digest, string data, ...) digest_hex = #639;
+//description:
+//returns a given hex digest of given data
+//the returned digest is always encoded in hexadecimal
+//only the "MD4" digest is always supported!
+//if the given digest is not supported, string_null is returned
+//the digest string is matched case sensitively, use "MD4", not "md4"!
+
+//DP_QC_DIGEST_SHA256
+//idea: motorsep, Spike
+//DarkPlaces implementation: divVerent
+//description:
+//"SHA256" is also an allowed digest type
+
+//DP_QC_LOG
+//darkplaces implementation: divVerent
+//builtin definitions:
+float log(float f) = #532;
+//description:
+//logarithm
+
+//FTE_CSQC_SKELETONOBJECTS
+//idea: Spike, LordHavoc
+//darkplaces implementation: LordHavoc
+//builtin definitions:
+// all skeleton numbers are 1-based (0 being no skeleton)
+// all bone numbers are 1-based (0 being invalid)
+float(float modlindex) skel_create = #263; // create a skeleton (be sure to assign this value into .skeletonindex for use), returns skeleton index (1 or higher) on success, returns 0 on failure (for example if the modelindex is not skeletal), it is recommended that you create a new skeleton if you change modelindex, as the skeleton uses the hierarchy from the model.
+float(float skel, entity ent, float modlindex, float retainfrac, float firstbone, float lastbone) skel_build = #264; // blend in a percentage of standard animation, 0 replaces entirely, 1 does nothing, 0.5 blends half, etc, and this only alters the bones in the specified range for which out of bounds values like 0,100000 are safe (uses .frame, .frame2, .frame3, .frame4, .lerpfrac, .lerpfrac3, .lerpfrac4, .frame1time, .frame2time, .frame3time, .frame4time), returns skel on success, 0 on failure
+float(float skel) skel_get_numbones = #265; // returns how many bones exist in the created skeleton, 0 if skeleton does not exist
+string(float skel, float bonenum) skel_get_bonename = #266; // returns name of bone (as a tempstring), "" if invalid bonenum (< 1 for example) or skeleton does not exist
+float(float skel, float bonenum) skel_get_boneparent = #267; // returns parent num for supplied bonenum, 0 if bonenum has no parent or bone does not exist (returned value is always less than bonenum, you can loop on this)
+float(float skel, string tagname) skel_find_bone = #268; // get number of bone with specified name, 0 on failure, bonenum (1-based) on success, same as using gettagindex but takes modelindex instead of entity
+vector(float skel, float bonenum) skel_get_bonerel = #269; // get matrix of bone in skeleton relative to its parent - sets v_forward, v_right, v_up, returns origin (relative to parent bone)
+vector(float skel, float bonenum) skel_get_boneabs = #270; // get matrix of bone in skeleton in model space - sets v_forward, v_right, v_up, returns origin (relative to entity)
+void(float skel, float bonenum, vector org) skel_set_bone = #271; // set matrix of bone relative to its parent, reads v_forward, v_right, v_up, takes origin as parameter (relative to parent bone)
+void(float skel, float bonenum, vector org) skel_mul_bone = #272; // transform bone matrix (relative to its parent) by the supplied matrix in v_forward, v_right, v_up, takes origin as parameter (relative to parent bone)
+void(float skel, float startbone, float endbone, vector org) skel_mul_bones = #273; // transform bone matrices (relative to their parents) by the supplied matrix in v_forward, v_right, v_up, takes origin as parameter (relative to parent bones)
+void(float skeldst, float skelsrc, float startbone, float endbone) skel_copybones = #274; // copy bone matrices (relative to their parents) from one skeleton to another, useful for copying a skeleton to a corpse
+void(float skel) skel_delete = #275; // deletes skeleton at the beginning of the next frame (you can add the entity, delete the skeleton, renderscene, and it will still work)
+float(float modlindex, string framename) frameforname = #276; // finds number of a specified frame in the animation, returns -1 if no match found
+float(float modlindex, float framenum) frameduration = #277; // returns the intended play time (in seconds) of the specified framegroup, if it does not exist the result is 0, if it is a single frame it may be a small value around 0.1 or 0.
+//fields:
+.float skeletonindex; // active skeleton overriding standard animation on model
+.float frame; // primary framegroup animation (strength = 1 - lerpfrac - lerpfrac3 - lerpfrac4)
+.float frame2; // secondary framegroup animation (strength = lerpfrac)
+.float frame3; // tertiary framegroup animation (strength = lerpfrac3)
+.float frame4; // quaternary framegroup animation (strength = lerpfrac4)
+.float lerpfrac; // strength of framegroup blend
+.float lerpfrac3; // strength of framegroup blend
+.float lerpfrac4; // strength of framegroup blend
+.float frame1time; // start time of framegroup animation
+.float frame2time; // start time of framegroup animation
+.float frame3time; // start time of framegroup animation
+.float frame4time; // start time of framegroup animation
+//description:
+//this extension provides a way to do complex skeletal animation on an entity.
+//
+//see also DP_SKELETONOBJECTS (this extension implemented on server as well as client)
+//
+//notes:
+//each model contains its own skeleton, reusing a skeleton with incompatible models will yield garbage (or not render).
+//each model contains its own animation data, you can use animations from other model files (for example saving out all character animations as separate model files).
+//if an engine supports loading an animation-only file format such as .md5anim in FTEQW, it can be used to animate any model with a compatible skeleton.
+//proper use of this extension may require understanding matrix transforms (v_forward, v_right, v_up, origin), and you must keep in mind that v_right is negative for this purpose.
+//
+//features include:
+//multiple animations blended together.
+//animating a model with animations from another model with a compatible skeleton.
+//restricting animation blends to certain bones of a model - for example independent animation of legs, torso, head.
+//custom bone controllers - for example making eyes track a target location.
+//
+//
+//
+//example code follows...
+//
+//this helper function lets you identify (by parentage) what group a bone
+//belongs to - for example "torso", "leftarm", would return 1 ("torso") for
+//all children of the bone named "torso", unless they are children of
+//"leftarm" (which is a child of "torso") which would return 2 instead...
+float(float skel, float bonenum, string g1, string g2, string g3, string g4, string g5, string g6) example_skel_findbonegroup =
+{
+       local string bonename;
+       while (bonenum >= 0)
+       {
+               bonename = skel_get_bonename(skel, bonenum);
+               if (bonename == g1) return 1;
+               if (bonename == g2) return 2;
+               if (bonename == g3) return 3;
+               if (bonename == g4) return 4;
+               if (bonename == g5) return 5;
+               if (bonename == g6) return 6;
+               bonenum = skel_get_boneparent(skel, bonenum);
+       }
+       return 0;
+};
+// create a skeletonindex for our player using current modelindex
+void() example_skel_player_setup =
+{
+       self.skeletonindex = skel_create(self.modelindex);
+};
+// setup bones of skeleton based on an animation
+// note: animmodelindex can be a different model than self.modelindex
+void(float animmodelindex, float framegroup, float framegroupstarttime) example_skel_player_update_begin =
+{
+       // start with our standard animation
+       self.frame = framegroup;
+       self.frame2 = 0;
+       self.frame3 = 0;
+       self.frame4 = 0;
+       self.frame1time = framegroupstarttime;
+       self.frame2time = 0;
+       self.frame3time = 0;
+       self.frame4time = 0;
+       self.lerpfrac = 0;
+       self.lerpfrac3 = 0;
+       self.lerpfrac4 = 0;
+       skel_build(self.skeletonindex, self, animmodelindex, 0, 0, 100000);
+};
+// apply a different framegroup animation to bones with a specified parent
+void(float animmodelindex, float framegroup, float framegroupstarttime, float blendalpha, string groupbonename, string excludegroupname1, string excludegroupname2) example_skel_player_update_applyoverride =
+{
+       local float bonenum;
+       local float numbones;
+       self.frame = framegroup;
+       self.frame2 = 0;
+       self.frame3 = 0;
+       self.frame4 = 0;
+       self.frame1time = framegroupstarttime;
+       self.frame2time = 0;
+       self.frame3time = 0;
+       self.frame4time = 0;
+       self.lerpfrac = 0;
+       self.lerpfrac3 = 0;
+       self.lerpfrac4 = 0;
+       bonenum = 0;
+       numbones = skel_get_numbones(self.skeletonindex);
+       while (bonenum < numbones)
+       {
+               if (example_skel_findbonegroup(self.skeletonindex, bonenum, groupbonename, excludegroupname1, excludegroupname2, "", "", "") == 1)
+                       skel_build(self.skeletonindex, self, animmodelindex, 1 - blendalpha, bonenum, bonenum + 1);
+               bonenum = bonenum + 1;
+       }
+};
+// make eyes point at a target location, be sure v_forward, v_right, v_up are set correctly before calling
+void(vector eyetarget, string bonename) example_skel_player_update_eyetarget =
+{
+       local float bonenum;
+       local vector ang;
+       local vector oldforward, oldright, oldup;
+       local vector relforward, relright, relup, relorg;
+       local vector boneforward, boneright, boneup, boneorg;
+       local vector parentforward, parentright, parentup, parentorg;
+       local vector u, v;
+       local vector modeleyetarget;
+       bonenum = skel_find_bone(self.skeletonindex, bonename) - 1;
+       if (bonenum < 0)
+               return;
+       oldforward = v_forward;
+       oldright = v_right;
+       oldup = v_up;
+       v = eyetarget - self.origin;
+       modeleyetarget_x =   v * v_forward;
+       modeleyetarget_y = 0-v * v_right;
+       modeleyetarget_z =   v * v_up;
+       // this is an eyeball, make it point at the target location
+       // first get all the data we can...
+       relorg = skel_get_bonerel(self.skeletonindex, bonenum);
+       relforward = v_forward;
+       relright = v_right;
+       relup = v_up;
+       boneorg = skel_get_boneabs(self.skeletonindex, bonenum);
+       boneforward = v_forward;
+       boneright = v_right;
+       boneup = v_up;
+       parentorg = skel_get_boneabs(self.skeletonindex, skel_get_boneparent(self.skeletonindex, bonenum));
+       parentforward = v_forward;
+       parentright = v_right;
+       parentup = v_up;
+       // get the vector from the eyeball to the target
+       u = modeleyetarget - boneorg;
+       // now transform it inversely by the parent matrix to produce new rel vectors
+       v_x = u * parentforward;
+       v_y = u * parentright;
+       v_z = u * parentup;
+       ang = vectoangles2(v, relup);
+       ang_x = 0 - ang_x;
+       makevectors(ang);
+       // set the relative bone matrix
+       skel_set_bone(self.skeletonindex, bonenum, relorg);
+       // restore caller's v_ vectors
+       v_forward = oldforward;
+       v_right = oldright;
+       v_up = oldup;
+};
+// delete skeleton when we're done with it
+// note: skeleton remains valid until next frame when it is really deleted
+void() example_skel_player_delete =
+{
+       skel_delete(self.skeletonindex);
+       self.skeletonindex = 0;
+};
+//
+// END OF EXAMPLES FOR FTE_CSQC_SKELETONOBJECTS
+//
+
+//DP_QC_ENTITYDATA
+//idea: KrimZon
+//darkplaces implementation: KrimZon
+//builtin definitions:
+float() numentityfields = #496;
+string(float fieldnum) entityfieldname = #497;
+float(float fieldnum) entityfieldtype = #498;
+string(float fieldnum, entity ent) getentityfieldstring = #499;
+float(float fieldnum, entity ent, string s) putentityfieldstring = #500;
+//constants:
+//Returned by entityfieldtype
+float FIELD_STRING   = 1;
+float FIELD_FLOAT    = 2;
+float FIELD_VECTOR   = 3;
+float FIELD_ENTITY   = 4;
+float FIELD_FUNCTION = 6;
+//description:
+//Versatile functions intended for storing data from specific entities between level changes, but can be customized for some kind of partial savegame.
+//WARNING: .entity fields cannot be saved and restored between map loads as they will leave dangling pointers.
+//numentityfields returns the number of entity fields. NOT offsets. Vectors comprise 4 fields: v, v_x, v_y and v_z.
+//entityfieldname returns the name as a string, eg. "origin" or "classname" or whatever.
+//entityfieldtype returns a value that the constants represent, but the field may be of another type in more exotic progs.dat formats or compilers.
+//getentityfieldstring returns data as would be written to a savegame, eg... "0.05" (float), "0 0 1" (vector), or "Hello World!" (string). Function names can also be returned.
+//putentityfieldstring puts the data returned by getentityfieldstring back into the entity.
+
+//DP_QC_ENTITYSTRING
+void(string s) loadfromdata = #529;
+void(string s) loadfromfile = #530;
+void(string s) callfunction = #605;
+void(float fh, entity e) writetofile = #606;
+float(string s) isfunction = #607;
+void(entity e, string s) parseentitydata = #608;
+
+//DP_COVERAGE
+//idea: divVerent
+//darkplaces implementation: divVerent
+//function definitions:
+void coverage() = #642;  // Reports a coverage event. The engine counts for each of the calls to this builtin whether it has been called.
+
+// assorted builtins
+const float            STAT_MOVEVARS_TICRATE           = 240;
+const float            STAT_MOVEVARS_TIMESCALE         = 241;
+const float            STAT_FRAGLIMIT                                  = 235;
+const float            STAT_TIMELIMIT                                  = 236;
+const float     STAT_MOVEVARS_GRAVITY           = 242;
+string(void)                                           ReadPicture = #501;
+float PARTICLES_USEALPHA = 1;
+float particles_alphamin, particles_alphamax;
+float PARTICLES_USECOLOR = 2;
+vector particles_colormin, particles_colormax;
+float PARTICLES_USEFADE = 4;  // fades the COUNT (fade alpha using alphamin/alphamax)
+float particles_fade;
+float PARTICLES_DRAWASTRAIL = 128;
+void(float effectindex, entity own, vector org_from, vector org_to, vector dir_from, vector dir_to, float countmultiplier, float flags) boxparticles = #502;
+float trace_networkentity;
+const float RF_FULLBRIGHT      = 256;
+const float RF_NOSHADOW        = 512;
+float RF_DYNAMICMODELLIGHT = 8192;
+
+float gettaginfo_parent;
+string gettaginfo_name;
+vector gettaginfo_offset;
+vector gettaginfo_forward;
+vector gettaginfo_right;
+vector gettaginfo_up;
+float checkpvs(vector viewpos, entity viewee) = #240;
diff --git a/qcsrc/dpdefs/upstream/dpextensions.qc b/qcsrc/dpdefs/upstream/dpextensions.qc
new file mode 100644 (file)
index 0000000..07142e9
--- /dev/null
@@ -0,0 +1,2573 @@
+
+//DarkPlaces supported extension list, draft version 1.04
+
+//things that don't have extensions yet:
+.float disableclientprediction;
+
+//definitions that id Software left out:
+//these are passed as the 'nomonsters' parameter to traceline/tracebox (yes really this was supported in all quake engines, nomonsters is misnamed)
+float MOVE_NORMAL = 0; // same as FALSE
+float MOVE_NOMONSTERS = 1; // same as TRUE
+float MOVE_MISSILE = 2; // save as movement with .movetype == MOVETYPE_FLYMISSILE
+
+//checkextension function
+//idea: expected by almost everyone
+//darkplaces implementation: LordHavoc
+float(string s) checkextension = #99;
+//description:
+//check if (cvar("pr_checkextension")) before calling this, this is the only
+//guaranteed extension to be present in the extension system, it allows you
+//to check if an extension is available, by name, to check for an extension
+//use code like this:
+//// (it is recommended this code be placed in worldspawn or a worldspawn called function somewhere)
+//if (cvar("pr_checkextension"))
+//if (checkextension("DP_SV_SETCOLOR"))
+//     ext_setcolor = TRUE;
+//from then on you can check ext_setcolor to know if that extension is available
+
+//BX_WAL_SUPPORT
+//idea: id Software
+//darkplaces implementation: LordHavoc
+//description:
+//indicates the engine supports .wal textures for filenames in the textures/ directory
+//(note: DarkPlaces has supported this since 2001 or 2002, but did not advertise it as an extension, then I noticed Betwix was advertising it and added the extension accordingly)
+
+//DP_BUTTONCHAT
+//idea: Vermeulen
+//darkplaces implementation: LordHavoc
+//field definitions:
+.float buttonchat;
+//description:
+//true if the player is currently chatting (in messagemode, menus or console)
+
+//DP_BUTTONUSE
+//idea: id Software
+//darkplaces implementation: LordHavoc
+//field definitions:
+.float buttonuse;
+//client console commands:
+//+use
+//-use
+//description:
+//made +use and -use commands work, they now control the .buttonuse field (.button1 was used by many mods for other purposes).
+
+//DP_CL_LOADSKY
+//idea: Nehahra, LordHavoc
+//darkplaces implementation: LordHavoc
+//client console commands:
+//"loadsky" (parameters: "basename", example: "mtnsun_" would load "mtnsun_up.tga" and "mtnsun_rt.tga" and similar names, use "" to revert to quake sky, note: this is the same as Quake2 skybox naming)
+//description:
+//sets global skybox for the map for this client (can be stuffed to a client by QC), does not hurt much to repeatedly execute this command, please don't use this in mods if it can be avoided (only if changing skybox is REALLY needed, otherwise please use DP_GFX_SKYBOX).
+
+//DP_CON_SET
+//idea: id Software
+//darkplaces implementation: LordHavoc
+//description:
+//indicates this engine supports the "set" console command which creates or sets a non-archived cvar (not saved to config.cfg on exit), it is recommended that set and seta commands be placed in default.cfg for mod-specific cvars.
+
+//DP_CON_SETA
+//idea: id Software
+//darkplaces implementation: LordHavoc
+//description:
+//indicates this engine supports the "seta" console command which creates or sets an archived cvar (saved to config.cfg on exit), it is recommended that set and seta commands be placed in default.cfg for mod-specific cvars.
+
+//DP_CON_ALIASPARAMETERS
+//idea: many
+//darkplaces implementation: Black
+//description:
+//indicates this engine supports aliases containing $1 through $9 parameter macros (which when called will expand to the parameters passed to the alias, for example alias test "say $2 $1", then you can type test hi there and it will execute say there hi), as well as $0 (name of the alias) and $* (all parameters $1 onward).
+
+//DP_CON_EXPANDCVAR
+//idea: many, PHP
+//darkplaces implementation: Black
+//description:
+//indicates this engine supports console commandlines containing $cvarname which will expand to the contents of that cvar as a parameter, for instance say my fov is $fov, will say "my fov is 90", or similar.
+
+//DP_CON_STARTMAP
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//description:
+//adds two engine-called aliases named startmap_sp and startmap_dm which are called when the engine tries to start a singleplayer game from the menu (startmap_sp) or the -listen or -dedicated options are used or the engine is a dedicated server (uses startmap_dm), these allow a mod or game to specify their own map instead of start, and also distinguish between singleplayer and -listen/-dedicated, also these need not be a simple "map start" command, they can do other things if desired, startmap_sp and startmap_dm both default to "map start".
+
+//DP_EF_ADDITIVE
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//effects bit:
+float   EF_ADDITIVE     = 32;
+//description:
+//additive blending when this object is rendered
+
+//DP_EF_BLUE
+//idea: id Software
+//darkplaces implementation: LordHavoc
+//effects bit:
+float   EF_BLUE         = 64;
+//description:
+//entity emits blue light (used for quad)
+
+//DP_EF_DOUBLESIDED
+//idea: LordHavoc
+//darkplaces implementation: [515] and LordHavoc
+//effects bit:
+float EF_DOUBLESIDED = 32768;
+//description:
+//render entity as double sided (backfaces are visible, I.E. you see the 'interior' of the model, rather than just the front), can be occasionally useful on transparent stuff.
+
+//DP_EF_DYNAMICMODELLIGHT
+//idea: C.Brutail, divVerent, maikmerten
+//darkplaces implementation: divVerent
+//effects bit:
+float   EF_DYNAMICMODELLIGHT     = 131072;
+//description:
+//force dynamic model light on the entity, even if it's a BSP model (or anything else with lightmaps or light colors)
+
+//DP_EF_FLAME
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//effects bit:
+float   EF_FLAME        = 1024;
+//description:
+//entity is on fire
+
+//DP_EF_FULLBRIGHT
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//effects bit:
+float   EF_FULLBRIGHT   = 512;
+//description:
+//entity is always brightly lit
+
+//DP_EF_NODEPTHTEST
+//idea: Supa
+//darkplaces implementation: LordHavoc
+//effects bit:
+float   EF_NODEPTHTEST       = 8192;
+//description:
+//makes entity show up to client even through walls, useful with EF_ADDITIVE for special indicators like where team bases are in a map, so that people don't get lost
+
+//DP_EF_NODRAW
+//idea: id Software
+//darkplaces implementation: LordHavoc
+//effects bit:
+float   EF_NODRAW       = 16;
+//description:
+//prevents server from sending entity to client (forced invisible, even if it would have been a light source or other such things)
+
+//DP_EF_NOGUNBOB
+//idea: Chris Page, Dresk
+//darkplaces implementation: LordHAvoc
+//effects bit:
+float   EF_NOGUNBOB     = 256;
+//description:
+//this has different meanings depending on the entity it is used on:
+//player entity - prevents gun bobbing on player.viewmodel
+//viewmodelforclient entity - prevents gun bobbing on an entity attached to the player's view
+//other entities - no effect
+//uses:
+//disabling gun bobbing on a diving mask or other model used as a .viewmodel.
+//disabling gun bobbing on view-relative models meant to be part of the heads up display.  (note: if fov is changed these entities may be off-screen, or too near the center of the screen, so use fov 90 in this case)
+
+//DP_EF_NOSHADOW
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//effects bit:
+float   EF_NOSHADOW     = 4096;
+//description:
+//realtime lights will not cast shadows from this entity (but can still illuminate it)
+
+//DP_EF_RED
+//idea: id Software
+//darkplaces implementation: LordHavoc
+//effects bit:
+float   EF_RED          = 128;
+//description:
+//entity emits red light (used for invulnerability)
+
+//DP_EF_RESTARTANIM_BIT
+//idea: id software
+//darkplaces implementation: divVerent
+//effects bit:
+float   EF_RESTARTANIM_BIT = 1048576;
+//description:
+//when toggled, the current animation is restarted. Useful for weapon animation.
+//to toggle this bit in QC, you can do:
+//  self.effects += (EF_RESTARTANIM_BIT - 2 * (self.effects & EF_RESTARTANIM_BIT));
+
+//DP_EF_STARDUST
+//idea: MythWorks Inc
+//darkplaces implementation: LordHavoc
+//effects bit:
+float   EF_STARDUST     = 2048;
+//description:
+//entity emits bouncing sparkles in every direction
+
+//DP_EF_TELEPORT_BIT
+//idea: id software
+//darkplaces implementation: divVerent
+//effects bit:
+float   EF_TELEPORT_BIT = 2097152;
+//description:
+//when toggled, interpolation of the entity is skipped for one frame. Useful for teleporting.
+//to toggle this bit in QC, you can do:
+//  self.effects += (EF_TELEPORT_BIT - 2 * (self.effects & EF_TELEPORT_BIT));
+
+//DP_ENT_ALPHA
+//idea: Nehahra
+//darkplaces implementation: LordHavoc
+//fields:
+.float alpha;
+//description:
+//controls opacity of the entity, 0.0 is forced to be 1.0 (otherwise everything would be invisible), use -1 if you want to make something invisible, 1.0 is solid (like normal).
+
+//DP_ENT_COLORMOD
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//field definition:
+.vector colormod;
+//description:
+//controls color of the entity, '0 0 0', is forced to be '1 1 1' (otherwise everything would be black), used for tinting objects, for instance using '1 0.6 0.4' on an ogre would give you an orange ogre (order is red green blue), note the colors can go up to '8 8 8' (8x as bright as normal).
+
+//DP_ENT_CUSTOMCOLORMAP
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//description:
+//if .colormap is set to 1024 + pants + shirt * 16, those colors will be used for colormapping the entity, rather than looking up a colormap by player number.
+
+/*
+//NOTE: no longer supported by darkplaces because all entities are delta compressed now
+//DP_ENT_DELTACOMPRESS // no longer supported
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//effects bit:
+float EF_DELTA = 8388608;
+//description:
+//(obsolete) applies delta compression to the network updates of the entity, making updates smaller, this might cause some unreliable behavior in packet loss situations, so it should only be used on numerous (nails/plasma shots/etc) or unimportant objects (gibs/shell casings/bullet holes/etc).
+*/
+
+//DP_ENT_EXTERIORMODELTOCLIENT
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//fields:
+.entity exteriormodeltoclient;
+//description:
+//the entity is visible to all clients with one exception: if the specified client is using first person view (not using chase_active) the entity will not be shown.  Also if tag attachments are supported any entities attached to the player entity will not be drawn in first person.
+
+//DP_ENT_GLOW
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//field definitions:
+.float glow_color;
+.float glow_size;
+.float glow_trail;
+//description:
+//customizable glowing light effect on the entity, glow_color is a paletted (8bit) color in the range 0-255 (note: 0 and 254 are white), glow_size is 0 or higher (up to the engine what limit to cap it to, darkplaces imposes a 1020 limit), if glow_trail is true it will leave a trail of particles of the same color as the light.
+
+//DP_ENT_GLOWMOD
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//field definition:
+.vector glowmod;
+//description:
+//controls color of the entity's glow texture (fullbrights), '0 0 0', is forced to be '1 1 1' (otherwise everything would be black), used for tinting objects, see colormod (same color restrictions apply).
+
+//DP_ENT_LOWPRECISION
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//effects bit:
+float EF_LOWPRECISION = 4194304;
+//description:
+//uses low quality origin coordinates, reducing network traffic compared to the default high precision, intended for numerous objects (projectiles/gibs/bullet holes/etc).
+
+//DP_ENT_SCALE
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//field definitions:
+.float scale;
+//description:
+//controls rendering scale of the object, 0 is forced to be 1, darkplaces uses 1/16th accuracy and a limit of 15.9375, can be used to make an object larger or smaller.
+
+//DP_ENT_TRAILEFFECTNUM
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//field definitions:
+.float traileffectnum;
+//description:
+//use a custom effectinfo.txt effect on this entity, assign it like this:
+//self.traileffectnum = particleeffectnum("mycustomeffect");
+//this will do both the dlight and particle trail as described in the effect, basically equivalent to trailparticles() in CSQC but performed on a server entity.
+
+//DP_ENT_VIEWMODEL
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//field definitions:
+.entity viewmodelforclient;
+//description:
+//this is a very special capability, attachs the entity to the view of the client specified, origin and angles become relative to the view of that client, all effects can be used (multiple skins on a weapon model etc)...  the entity is not visible to any other client.
+
+//DP_GFX_EXTERNALTEXTURES
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//description:
+//loads external textures found in various directories (tenebrae compatible)...
+/*
+in all examples .tga is merely the base texture, it can be any of these:
+.tga (base texture)
+_glow.tga (fullbrights or other glowing overlay stuff, NOTE: this is done using additive blend, not alpha)
+_pants.tga (pants overlay for colormapping on models, this should be shades of grey (it is tinted by pants color) and black wherever the base texture is not black, as this is an additive blend)
+_shirt.tga (same idea as pants, but for shirt color)
+_diffuse.tga (this may be used instead of base texture for per pixel lighting)
+_gloss.tga (specular texture for per pixel lighting, note this can be in color (tenebrae only supports greyscale))
+_norm.tga (normalmap texture for per pixel lighting)
+_bump.tga (bumpmap, converted to normalmap at load time, supported only for reasons of tenebrae compatibility)
+_luma.tga (same as _glow but supported only for reasons of tenebrae compatibility)
+
+due to glquake's incomplete Targa(r) loader, this section describes
+required Targa(r) features support:
+types:
+type 1 (uncompressed 8bit paletted with 24bit/32bit palette)
+type 2 (uncompressed 24bit/32bit true color, glquake supported this)
+type 3 (uncompressed 8bit greyscale)
+type 9 (RLE compressed 8bit paletted with 24bit/32bit palette)
+type 10 (RLE compressed 24bit/32bit true color, glquake supported this)
+type 11 (RLE compressed 8bit greyscale)
+attribute bit 0x20 (Origin At Top Left, top to bottom, left to right)
+
+image formats guaranteed to be supported: tga, pcx, lmp
+image formats that are optional: png, jpg
+
+mdl/spr/spr32 examples:
+skins are named _A (A being a number) and skingroups are named like _A_B
+these act as suffixes on the model name...
+example names for skin _2_1 of model "progs/armor.mdl":
+game/override/progs/armor.mdl_2_1.tga
+game/textures/progs/armor.mdl_2_1.tga
+game/progs/armor.mdl_2_1.tga
+example names for skin _0 of the model "progs/armor.mdl":
+game/override/progs/armor.mdl_0.tga
+game/textures/progs/armor.mdl_0.tga
+game/progs/armor.mdl_0.tga
+note that there can be more skins files (of the _0 naming) than the mdl
+contains, this is only useful to save space in the .mdl file if classic quake
+compatibility is not a concern.
+
+bsp/md2/md3 examples:
+example names for the texture "quake" of model "maps/start.bsp":
+game/override/quake.tga
+game/textures/quake.tga
+game/quake.tga
+
+sbar/menu/console textures: for example the texture "conchars" (console font) in gfx.wad
+game/override/gfx/conchars.tga
+game/textures/gfx/conchars.tga
+game/gfx/conchars.tga
+*/
+
+//DP_GFX_EXTERNALTEXTURES_PERMAPTEXTURES
+//idea: Fuh?
+//darkplaces implementation: LordHavoc
+//description:
+//Q1BSP and HLBSP map loading loads external textures found in textures/<mapname>/ as well as textures/.
+//Where mapname is the bsp filename minus the extension (typically .bsp) and minus maps/ if it is in maps/ (any other path is not removed)
+//example:
+//maps/e1m1.bsp uses textures in the directory textures/e1m1/ and falls back to textures/
+//maps/b_batt0.bsp uses textures in the directory textures/b_batt0.bsp and falls back to textures/
+//as a more extreme example:
+//progs/something/blah.bsp uses textures in the directory textures/progs/something/blah/ and falls back to textures/
+
+//DP_GFX_FOG
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//worldspawn fields:
+//"fog" (parameters: "density red green blue", example: "0.1 0.3 0.3 0.3")
+//description:
+//global fog for the map, can not be changed by QC
+
+//DP_GFX_QUAKE3MODELTAGS
+//idea: id Software
+//darkplaces implementation: LordHavoc
+//field definitions:
+.entity tag_entity; // entity this is attached to (call setattachment to set this)
+.float tag_index; // which tag on that entity (0 is relative to the entity, > 0 is an index into the tags on the model if it has any) (call setattachment to set this)
+//builtin definitions:
+void(entity e, entity tagentity, string tagname) setattachment = #443; // attachs e to a tag on tagentity (note: use "" to attach to entity origin/angles instead of a tag)
+//description:
+//allows entities to be visually attached to model tags (which follow animations perfectly) on other entities, for example attaching a weapon to a player's hand, or upper body attached to lower body, allowing it to change angles and frame separately (note: origin and angles are relative to the tag, use '0 0 0' for both if you want it to follow exactly, this is similar to viewmodelforclient's behavior).
+//note 2: if the tag is not found, it defaults to "" (attach to origin/angles of entity)
+//note 3: attaching to world turns off attachment
+//note 4: the entity that this is attached to must be visible for this to work
+//note 5: if an entity is attached to the player entity it will not be drawn in first person.
+
+//DP_GFX_SKINFILES
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//description:
+//alias models (mdl, md2, md3) can have .skin files to replace conventional texture naming, these have a naming format such as:
+//progs/test.md3_0.skin
+//progs/test.md3_1.skin
+//...
+//
+//these files contain replace commands (replace meshname shadername), example:
+//replace "helmet" "progs/test/helmet1.tga" // this is a mesh shader replacement
+//replace "teamstripes" "progs/test/redstripes.tga"
+//replace "visor" "common/nodraw" // this makes the visor mesh invisible
+////it is not possible to rename tags using this format
+//
+//Or the Quake3 syntax (100% compatible with Quake3's .skin files):
+//helmet,progs/test/helmet1.tga // this is a mesh shader replacement
+//teamstripes,progs/test/redstripes.tga
+//visor,common/nodraw // this makes the visor mesh invisible
+//tag_camera, // this defines that the first tag in the model is called tag_camera
+//tag_test, // this defines that the second tag in the model is called tag_test
+//
+//any names that are not replaced are automatically show up as a grey checkerboard to indicate the error status, and "common/nodraw" is a special case that is invisible.
+//this feature is intended to allow multiple skin sets on md3 models (which otherwise only have one skin set).
+//other commands might be added someday but it is not expected.
+
+//DP_GFX_SKYBOX
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//worldspawn fields:
+//"sky" (parameters: "basename", example: "mtnsun_" would load "mtnsun_up.tga" and "mtnsun_rt.tga" and similar names, note: "sky" is also used the same way by Quake2)
+//description:
+//global skybox for the map, can not be changed by QC
+
+//DP_UTF8
+//idea: Blub\0, divVerent
+//darkplaces implementation: Blub\0
+//cvar definitions:
+//   utf8_enable: enable utf8 encoding
+//description: utf8 characters are allowed inside cvars, protocol strings, files, progs strings, etc., 
+//and count as 1 char for string functions like strlen, substring, etc.
+// note: utf8_enable is run-time cvar, could be changed during execution
+// note: beware that str2chr() could return value bigger than 255 once utf8 is enabled
+
+//DP_HALFLIFE_MAP
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//description:
+//simply indicates that the engine supports HalfLife maps (BSP version 30, NOT the QER RGBA ones which are also version 30).
+
+//DP_HALFLIFE_MAP_CVAR
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//cvars:
+//halflifebsp 0/1
+//description:
+//engine sets this cvar when loading a map to indicate if it is halflife format or not.
+
+//DP_HALFLIFE_SPRITE
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//description:
+//simply indicates that the engine supports HalfLife sprites.
+
+//DP_INPUTBUTTONS
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//field definitions:
+.float button3;
+.float button4;
+.float button5;
+.float button6;
+.float button7;
+.float button8;
+.float button9;
+.float button10;
+.float button11;
+.float button12;
+.float button13;
+.float button14;
+.float button15;
+.float button16;
+//description:
+//set to the state of the +button3, +button4, +button5, +button6, +button7, and +button8 buttons from the client, this does not involve protocol changes (the extra 6 button bits were simply not used).
+//the exact mapping of protocol button bits on the server is:
+//self.button0 = (bits & 1) != 0;
+///* button1 is skipped because mods abuse it as a variable, and accordingly it has no bit */
+//self.button2 = (bits & 2) != 0;
+//self.button3 = (bits & 4) != 0;
+//self.button4 = (bits & 8) != 0;
+//self.button5 = (bits & 16) != 0;
+//self.button6 = (bits & 32) != 0;
+//self.button7 = (bits & 64) != 0;
+//self.button8 = (bits & 128) != 0;
+
+// DP_LIGHTSTYLE_STATICVALUE
+// idea: VorteX
+// darkplaces implementation: VorteX
+// description: allows alternative 'static' lightstyle syntax : "=value"
+// examples: "=0.5", "=2.0", "=2.75"
+// could be used to control switchable lights or making styled lights with brightness > 2
+// Warning: this extension is experimental. It safely works in CSQC, but SVQC use is limited by the fact 
+// that other engines (which do not support this extension) could connect to a game and misunderstand this kind of lightstyle syntax
+
+//DP_LITSPRITES
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//description:
+//indicates this engine supports lighting on sprites, any sprite with ! in its filename (both on disk and in the qc) will be lit rather than having forced EF_FULLBRIGHT (EF_FULLBRIGHT on the entity can still force these sprites to not be lit).
+
+//DP_LITSUPPORT
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//description:
+//indicates this engine loads .lit files for any quake1 format .bsp files it loads to enhance maps with colored lighting.
+//implementation description: these files begin with the header QLIT followed by version number 1 (as little endian 32bit), the rest of the file is a replacement lightmaps lump, except being 3x as large as the lightmaps lump of the map it matches up with (and yes the between-lightmap padding is expanded 3x to keep this consistent), so the lightmap offset in each surface is simply multiplied by 3 during loading to properly index the lit data, and the lit file is loaded instead of the lightmap lump, other renderer changes are needed to display these of course...  see the litsupport.zip sample code (almost a tutorial) at http://icculus.org/twilight/darkplaces for more information.
+
+//DP_MONSTERWALK
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//description:
+//MOVETYPE_WALK is permitted on non-clients, so bots can move smoothly, run off ledges, etc, just like a real player.
+
+//DP_MOVETYPEBOUNCEMISSILE
+//idea: id Software
+//darkplaces implementation: id Software
+//movetype definitions:
+//float MOVETYPE_BOUNCEMISSILE = 11; // already in defs.qc
+//description:
+//MOVETYPE_BOUNCE but without gravity, and with full reflection (no speed loss like grenades have), in other words - bouncing laser bolts.
+
+//DP_MOVETYPEFLYWORLDONLY
+//idea: Samual
+//darkplaces implementation: Samual
+//movetype definitions:
+float MOVETYPE_FLY_WORLDONLY = 33;
+//description:
+//like MOVETYPE_FLY, but does all traces with MOVE_WORLDONLY, and is ignored by MOVETYPE_PUSH. Should only be combined with SOLID_NOT and SOLID_TRIGGER.
+
+//DP_NULL_MODEL
+//idea: Chris
+//darkplaces implementation: divVerent
+//definitions:
+//string dp_null_model = "null";
+//description:
+//setmodel(e, "null"); makes an entity invisible, have a zero bbox, but
+//networked. useful for shared CSQC entities.
+
+//DP_MOVETYPEFOLLOW
+//idea: id Software, LordHavoc (redesigned)
+//darkplaces implementation: LordHavoc
+//movetype definitions:
+float MOVETYPE_FOLLOW = 12;
+//description:
+//MOVETYPE_FOLLOW implemented, this uses existing entity fields in unusual ways:
+//aiment - the entity this is attached to.
+//punchangle - the original angles when the follow began.
+//view_ofs - the relative origin (note that this is un-rotated by punchangle, and that is actually the only purpose of punchangle).
+//v_angle - the relative angles.
+//here's an example of how you would set a bullet hole sprite to follow a bmodel it was created on, even if the bmodel rotates:
+//hole.movetype = MOVETYPE_FOLLOW; // make the hole follow
+//hole.solid = SOLID_NOT; // MOVETYPE_FOLLOW is always non-solid
+//hole.aiment = bmodel; // make the hole follow bmodel
+//hole.punchangle = bmodel.angles; // the original angles of bmodel
+//hole.view_ofs = hole.origin - bmodel.origin; // relative origin
+//hole.v_angle = hole.angles - bmodel.angles; // relative angles
+
+//DP_QC_ASINACOSATANATAN2TAN
+//idea: Urre
+//darkplaces implementation: LordHavoc
+//constant definitions:
+float DEG2RAD = 0.0174532925199432957692369076848861271344287188854172545609719144;
+float RAD2DEG = 57.2957795130823208767981548141051703324054724665643215491602438612;
+float PI      = 3.1415926535897932384626433832795028841971693993751058209749445923;
+//builtin definitions:
+float(float s) asin = #471; // returns angle in radians for a given sin() value, the result is in the range -PI*0.5 to PI*0.5
+float(float c) acos = #472; // returns angle in radians for a given cos() value, the result is in the range 0 to PI
+float(float t) atan = #473; // returns angle in radians for a given tan() value, the result is in the range -PI*0.5 to PI*0.5
+float(float c, float s) atan2 = #474; // returns angle in radians for a given cos() and sin() value pair, the result is in the range -PI to PI (this is identical to vectoyaw except it returns radians rather than degrees)
+float(float a) tan = #475; // returns tangent value (which is simply sin(a)/cos(a)) for the given angle in radians, the result is in the range -infinity to +infinity
+//description:
+//useful math functions for analyzing vectors, note that these all use angles in radians (just like the cos/sin functions) not degrees unlike makevectors/vectoyaw/vectoangles, so be sure to do the appropriate conversions (multiply by DEG2RAD or RAD2DEG as needed).
+//note: atan2 can take unnormalized vectors (just like vectoyaw), and the function was included only for completeness (more often you want vectoyaw or vectoangles), atan2(v_x,v_y) * RAD2DEG gives the same result as vectoyaw(v)
+
+//DP_QC_AUTOCVARS
+//idea: divVerent
+//darkplaces implementation: divVerent
+//description:
+//allows QC variables to be bound to cvars
+//(works for float, string, vector types)
+//example:
+// float autocvar_developer;
+// float autocvar_registered;
+// string autocvar__cl_name;
+//NOTE: copying a string-typed autocvar to another variable/field, and then
+//changing the cvar or returning from progs is UNDEFINED. Writing to autocvar
+//globals is UNDEFINED. Accessing autocvar globals after changing that cvar in
+//the same frame by any means other than cvar_set() from the same QC VM is
+//IMPLEMENTATION DEFINED (an implementation may either yield the previous, or
+//the current, value). Changing them via cvar_set() in the same QC VM
+//immediately must reflect on the autocvar globals. Whether autocvar globals,
+//after restoring a savegame, have the cvar's current value, or the original
+//value at time of saving, is UNDEFINED. Restoring a savegame however must not
+//restore the cvar values themselves.
+//In case the cvar does NOT exist, then it is automatically created with the
+//value of the autocvar initializer, if given. This is possible with e.g.
+//frikqcc and fteqcc the following way:
+// var float autocvar_whatever = 42;
+//If no initializer is given, the cvar will be initialized to a string
+//equivalent to the NULL value of the given data type, that is, the empty
+//string, 0, or '0 0 0'. However, when automatic cvar creation took place, a
+//warning is printed to the game console.
+//NOTE: to prevent an ambiguity with float names for vector types, autocvar
+//names MUST NOT end with _x, _y or _z!
+
+//DP_QC_CHANGEPITCH
+//idea: id Software
+//darkplaces implementation: id Software
+//field definitions:
+.float idealpitch;
+.float pitch_speed;
+//builtin definitions:
+void(entity ent) changepitch = #63;
+//description:
+//equivalent to changeyaw, ent is normally self. (this was a Q2 builtin)
+
+//DP_QC_COPYENTITY
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//builtin definitions:
+void(entity from, entity to) copyentity = #400;
+//description:
+//copies all data in the entity to another entity.
+
+//DP_QC_CRC16
+//idea: divVerent
+//darkplaces implementation: divVerent
+//Some hash function to build hash tables with. This has to be be the CRC-16-CCITT that is also required for the QuakeWorld download protocol.
+//When caseinsensitive is set, the CRC is calculated of the lower cased string.
+float(float caseinsensitive, string s, ...) crc16 = #494;
+
+//DP_QC_CVAR_DEFSTRING
+//idea: id Software (Doom3), LordHavoc
+//darkplaces implementation: LordHavoc
+//builtin definitions:
+string(string s) cvar_defstring = #482;
+//description:
+//returns the default value of a cvar, as a tempstring.
+
+//DP_QC_CVAR_DESCRIPTION
+//idea: divVerent
+//DarkPlaces implementation: divVerent
+//builtin definitions:
+string(string name) cvar_description = #518;
+//description:
+//returns the description of a cvar
+
+//DP_QC_CVAR_STRING
+//idea: VorteX
+//DarkPlaces implementation: VorteX, LordHavoc
+//builtin definitions:
+string(string s) cvar_string = #448;
+//description:
+//returns the value of a cvar, as a tempstring.
+
+//DP_QC_CVAR_TYPE
+//idea: divVerent
+//DarkPlaces implementation: divVerent
+//builtin definitions:
+float(string name) cvar_type = #495;
+float CVAR_TYPEFLAG_EXISTS = 1;
+float CVAR_TYPEFLAG_SAVED = 2;
+float CVAR_TYPEFLAG_PRIVATE = 4;
+float CVAR_TYPEFLAG_ENGINE = 8;
+float CVAR_TYPEFLAG_HASDESCRIPTION = 16;
+float CVAR_TYPEFLAG_READONLY = 32;
+
+//DP_QC_DIGEST
+//idea: motorsep, Spike
+//DarkPlaces implementation: divVerent
+//builtin definitions:
+string(string digest, string data, ...) digest_hex = #639;
+//description:
+//returns a given hex digest of given data
+//the returned digest is always encoded in hexadecimal
+//only the "MD4" digest is always supported!
+//if the given digest is not supported, string_null is returned
+//the digest string is matched case sensitively, use "MD4", not "md4"!
+
+//DP_QC_DIGEST_SHA256
+//idea: motorsep, Spike
+//DarkPlaces implementation: divVerent
+//description:
+//"SHA256" is also an allowed digest type
+
+//DP_QC_EDICT_NUM
+//idea: 515
+//DarkPlaces implementation: LordHavoc
+//builtin definitions:
+entity(float entnum) edict_num = #459;
+float(entity ent) wasfreed = #353; // same as in EXT_CSQC extension
+//description:
+//edict_num returns the entity corresponding to a given number, this works even for freed entities, but you should call wasfreed(ent) to see if is currently active.
+//wasfreed returns whether an entity slot is currently free (entities that have never spawned are free, entities that have had remove called on them are also free).
+
+//DP_QC_ENTITYDATA
+//idea: KrimZon
+//darkplaces implementation: KrimZon
+//builtin definitions:
+float() numentityfields = #496;
+string(float fieldnum) entityfieldname = #497;
+float(float fieldnum) entityfieldtype = #498;
+string(float fieldnum, entity ent) getentityfieldstring = #499;
+float(float fieldnum, entity ent, string s) putentityfieldstring = #500;
+//constants:
+//Returned by entityfieldtype
+float FIELD_STRING   = 1;
+float FIELD_FLOAT    = 2;
+float FIELD_VECTOR   = 3;
+float FIELD_ENTITY   = 4;
+float FIELD_FUNCTION = 6;
+//description:
+//Versatile functions intended for storing data from specific entities between level changes, but can be customized for some kind of partial savegame.
+//WARNING: .entity fields cannot be saved and restored between map loads as they will leave dangling pointers.
+//numentityfields returns the number of entity fields. NOT offsets. Vectors comprise 4 fields: v, v_x, v_y and v_z.
+//entityfieldname returns the name as a string, eg. "origin" or "classname" or whatever.
+//entityfieldtype returns a value that the constants represent, but the field may be of another type in more exotic progs.dat formats or compilers.
+//getentityfieldstring returns data as would be written to a savegame, eg... "0.05" (float), "0 0 1" (vector), or "Hello World!" (string). Function names can also be returned.
+//putentityfieldstring puts the data returned by getentityfieldstring back into the entity.
+
+//DP_QC_ENTITYSTRING
+void(string s) loadfromdata = #529;
+void(string s) loadfromfile = #530;
+void(string s) callfunction = #605;
+void(float fh, entity e) writetofile = #606;
+float(string s) isfunction = #607;
+void(entity e, string s) parseentitydata = #608;
+
+//DP_QC_ETOS
+//idea: id Software
+//darkplaces implementation: id Software
+//builtin definitions:
+string(entity ent) etos = #65;
+//description:
+//prints "entity 1" or similar into a string. (this was a Q2 builtin)
+
+//DP_QC_EXTRESPONSEPACKET
+//idea: divVerent
+//darkplaces implementation: divVerent
+//builtin definitions:
+string(void) getextresponse = #624;
+//description:
+//returns a string of the form "\"ipaddress:port\" data...", or the NULL string
+//if no packet was found. Packets can be queued into the client/server by
+//sending a packet starting with "\xFF\xFF\xFF\xFFextResponse " to the
+//listening port.
+
+//DP_QC_FINDCHAIN
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//builtin definitions:
+entity(.string fld, string match) findchain = #402;
+//description:
+//similar to find() but returns a chain of entities like findradius.
+
+//DP_QC_FINDCHAIN_TOFIELD
+//idea: divVerent
+//darkplaces implementation: divVerent
+//builtin definitions:
+entity(.string fld, float match, .entity tofield) findradius_tofield = #22;
+entity(.string fld, string match, .entity tofield) findchain_tofield = #402;
+entity(.string fld, float match, .entity tofield) findchainflags_tofield = #450;
+entity(.string fld, float match, .entity tofield) findchainfloat_tofield = #403;
+//description:
+//similar to findchain() etc, but stores the chain into .tofield instead of .chain
+//actually, the .entity tofield is an optional field of the the existing findchain* functions
+
+//DP_QC_FINDCHAINFLAGS
+//idea: Sajt
+//darkplaces implementation: LordHavoc
+//builtin definitions:
+entity(.float fld, float match) findchainflags = #450;
+//description:
+//similar to findflags() but returns a chain of entities like findradius.
+
+//DP_QC_FINDCHAINFLOAT
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//builtin definitions:
+entity(.entity fld, entity match) findchainentity = #403;
+entity(.float fld, float match) findchainfloat = #403;
+//description:
+//similar to findentity()/findfloat() but returns a chain of entities like findradius.
+
+//DP_QC_FINDFLAGS
+//idea: Sajt
+//darkplaces implementation: LordHavoc
+//builtin definitions:
+entity(entity start, .float fld, float match) findflags = #449;
+//description:
+//finds an entity with the specified flag set in the field, similar to find()
+
+//DP_QC_FINDFLOAT
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//builtin definitions:
+entity(entity start, .entity fld, entity match) findentity = #98;
+entity(entity start, .float fld, float match) findfloat = #98;
+//description:
+//finds an entity or float field value, similar to find(), but for entity and float fields.
+
+//DP_QC_FS_SEARCH
+//idea: Black
+//darkplaces implementation: Black
+//builtin definitions:
+float(string pattern, float caseinsensitive, float quiet) search_begin = #444;
+void(float handle) search_end = #445;
+float(float handle) search_getsize = #446;
+string(float handle, float num) search_getfilename = #447;
+//description:
+//search_begin performs a filename search with the specified pattern (for example "maps/*.bsp") and stores the results in a search slot (minimum of 128 supported by any engine with this extension), the other functions take this returned search slot number, be sure to search_free when done (they are also freed on progs reload).
+//search_end frees a search slot (also done at progs reload).
+//search_getsize returns how many filenames were found.
+//search_getfilename returns a filename from the search.
+
+//DP_QC_GETLIGHT
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//builtin definitions:
+vector(vector org) getlight = #92;
+//description:
+//returns the lighting at the requested location (in color), 0-255 range (can exceed 255).
+
+//DP_QC_GETSURFACE
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//builtin definitions:
+float(entity e, float s) getsurfacenumpoints = #434;
+vector(entity e, float s, float n) getsurfacepoint = #435;
+vector(entity e, float s) getsurfacenormal = #436;
+string(entity e, float s) getsurfacetexture = #437;
+float(entity e, vector p) getsurfacenearpoint = #438;
+vector(entity e, float s, vector p) getsurfaceclippedpoint = #439;
+//description:
+//functions to query surface information.
+
+//DP_QC_GETSURFACEPOINTATTRIBUTE
+//idea: BlackHC
+//darkplaces implementation: BlackHC
+// constants
+float SPA_POSITION = 0;
+float SPA_S_AXIS = 1;
+float SPA_T_AXIS = 2;
+float SPA_R_AXIS = 3; // same as SPA_NORMAL
+float SPA_TEXCOORDS0 = 4;
+float SPA_LIGHTMAP0_TEXCOORDS = 5;
+float SPA_LIGHTMAP0_COLOR = 6;
+//builtin definitions:
+vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
+
+//description:
+//function to query extended information about a point on a certain surface
+
+//DP_QC_GETSURFACETRIANGLE
+//idea: divVerent
+//darkplaces implementation: divVerent
+//builtin definitions:
+float(entity e, float s) getsurfacenumtriangles = #628;
+vector(entity e, float s, float n) getsurfacetriangle = #629;
+//description:
+//function to query triangles of a surface
+
+//DP_QC_GETTAGINFO
+//idea: VorteX, LordHavoc
+//DarkPlaces implementation: VorteX
+//builtin definitions:
+float(entity ent, string tagname) gettagindex = #451;
+vector(entity ent, float tagindex) gettaginfo = #452;
+//description:
+//gettagindex returns the number of a tag on an entity, this number is the same as set by setattachment (in the .tag_index field), allowing the qc to save a little cpu time by keeping the number around if it wishes (this could already be done by calling setattachment and saving off the tag_index).
+//gettaginfo returns the origin of the tag in worldspace and sets v_forward, v_right, and v_up to the current orientation of the tag in worldspace, this automatically resolves all dependencies (attachments, including viewmodelforclient), this means you could fire a shot from a tag on a gun entity attached to the view for example.
+
+//DP_QC_GETTAGINFO_BONEPROPERTIES
+//idea: daemon
+//DarkPlaces implementation: divVerent
+//global definitions:
+float gettaginfo_parent;
+string gettaginfo_name;
+vector gettaginfo_offset;
+vector gettaginfo_forward;
+vector gettaginfo_right;
+vector gettaginfo_up;
+//description:
+//when this extension is present, gettaginfo fills in some globals with info about the bone that had been queried
+//gettaginfo_parent is set to the number of the parent bone, or 0 if it is a root bone
+//gettaginfo_name is set to the name of the bone whose index had been specified in gettaginfo
+//gettaginfo_offset, gettaginfo_forward, gettaginfo_right, gettaginfo_up contain the transformation matrix of the bone relative to its parent. Note that the matrix may contain a scaling component.
+
+//DP_QC_GETTIME
+//idea: tZork
+//darkplaces implementation: tZork, divVerent
+//constant definitions:
+float GETTIME_FRAMESTART = 0; // time of start of frame relative to an arbitrary point in time
+float GETTIME_REALTIME = 1; // current absolute time (OS specific)
+float GETTIME_HIRES = 2; // like REALTIME, but may reset between QC invocations and thus can be higher precision
+float GETTIME_UPTIME = 3; // time of start of frame since start of the engine
+//builtin definitions:
+float(float tmr) gettime = #519;
+//description:
+//some timers to query...
+
+//DP_QC_GETTIME_CDTRACK
+//idea: divVerent
+//darkplaces implementation: divVerent
+//constant definitions:
+float GETTIME_CDTRACK = 4;
+//description:
+//returns the playing time of the current cdtrack when passed to gettime()
+//see DP_END_GETSOUNDTIME for similar functionality but for entity sound channels
+
+//DP_QC_I18N
+//idea: divVerent
+//darkplaces implementation: divVerent
+//description:
+//
+//The engine supports translating by gettext compatible .po files.
+//progs.dat uses progs.dat.<LANGUAGE>.po
+//menu.dat uses menu.dat.<LANGUAGE>.po
+//csprogs.dat uses csprogs.dat.<LANGUAGE>.po
+//
+//To create a string that can be translated, define it as
+//  string dotranslate_FILENOTFOUND = "File not found";
+//Note: if the compiler does constant folding, this will only work if there is
+//no other "File not found" string in the progs!
+//
+//Alternatively, if using the Xonotic patched fteqcc compiler, you can simplify
+//this by using _("File not found") directly in the source code.
+//
+//The language is set by the "prvm_language" cvar: if prvm_language is set to
+//"de", it will read progs.dat.de.po for translating strings in progs.dat.
+//
+//If prvm_language is set to the special name "dump", progs.dat.pot will be
+//written, which is a translation template to be edited by filling out the
+//msgstr entries.
+
+//DP_QC_LOG
+//darkplaces implementation: divVerent
+//builtin definitions:
+float log(float f) = #532;
+//description:
+//logarithm
+
+//DP_QC_MINMAXBOUND
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//builtin definitions:
+float(float a, float b, ...) min = #94;
+float(float a, float b, float c) min3 = #94;
+float(float a, float b, float c, float d) min4 = #94;
+float(float a, float b, float c, float d, float e) min5 = #94;
+float(float a, float b, float c, float d, float e, float f) min6 = #94;
+float(float a, float b, float c, float d, float e, float f, float g) min7 = #94;
+float(float a, float b, float c, float d, float e, float f, float g, float h) min8 = #94;
+float(float a, float b, ...) max = #95;
+float(float a, float b, float c) max3 = #95;
+float(float a, float b, float c, float d) max4 = #95;
+float(float a, float b, float c, float d, float e) max5 = #95;
+float(float a, float b, float c, float d, float e, float f) max6 = #95;
+float(float a, float b, float c, float d, float e, float f, float g) max7 = #95;
+float(float a, float b, float c, float d, float e, float f, float g, float h) max8 = #95;
+float(float minimum, float val, float maximum) bound = #96;
+//description:
+//min returns the lowest of all the supplied numbers.
+//max returns the highest of all the supplied numbers.
+//bound clamps the value to the range and returns it.
+
+//DP_QC_MULTIPLETEMPSTRINGS
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//description:
+//this extension makes all builtins returning tempstrings (ftos for example)
+//cycle through a pool of multiple tempstrings (at least 16), allowing
+//multiple ftos results to be gathered before putting them to use, normal
+//quake only had 1 tempstring, causing many headaches.
+//
+//Note that for longer term storage (or compatibility on engines having
+//FRIK_FILE but not this extension) the FRIK_FILE extension's
+//strzone/strunzone builtins provide similar functionality (slower though).
+//
+//NOTE: this extension is superseded by DP_QC_UNLIMITEDTEMPSTRINGS
+
+//DP_QC_NUM_FOR_EDICT
+//idea: Blub\0
+//darkplaces implementation: Blub\0
+//Function to get the number of an entity - a clean way.
+float(entity num) num_for_edict = #512;
+
+//DP_QC_RANDOMVEC
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//builtin definitions:
+vector() randomvec = #91;
+//description:
+//returns a vector of length < 1, much quicker version of this QC: do {v_x = random()*2-1;v_y = random()*2-1;v_z = random()*2-1;} while(vlen(v) > 1)
+
+//DP_QC_SINCOSSQRTPOW
+//idea: id Software, LordHavoc
+//darkplaces implementation: id Software, LordHavoc
+//builtin definitions:
+float(float val) sin = #60;
+float(float val) cos = #61;
+float(float val) sqrt = #62;
+float(float a, float b) pow = #97;
+//description:
+//useful math functions, sine of val, cosine of val, square root of val, and raise a to power b, respectively.
+
+//DP_QC_SPRINTF
+//idea: divVerent
+//darkplaces implementation: divVerent
+//builtin definitions:
+string(string format, ...) sprintf = #627;
+//description:
+//you know sprintf :P
+//supported stuff:
+//  %
+//  optional: <argpos>$ for the argument to format (the arg counter then is not increased)
+//  flags: #0- +
+//  optional: <width>, *, or *<argpos>$ for the field width (width is read before value and precision)
+//  optional: .<precision>, .*, or .*<argpos>$ for the precision (precision is read before value)
+//  length modifiers: h for forcing a float, l for forcing an entity (by default, %d etc. cast a float to int), ll for forcing an int
+//  conversions:
+//    d takes a float if no length is specified or h is, and an entity if l is specified as length, and an int if ll is specified as length, and cast it to an int
+//    i takes an entity if no length is specified or l is, and a float if h is specified as length, and an int if ll is specified as length, and cast it to an int
+//    ouxXc take a float if no length is specified or h is, and an entity if l is specified as length, and an int if ll is specified as length, and cast it to an unsigned int
+//    eEfFgG take a float if no length is specified or h is, and an entity if l is specified as length, and an int if ll is specified as length, and cast it to a double
+//    s takes a string
+//    vV takes a vector, and processes the three components as if it were a gG for all three components, separated by space
+//    For conversions s and c, the flag # makes precision and width interpreted
+//      as byte count, by default it is interpreted as character count in UTF-8
+//      enabled engines. No other conversions can create wide characters, and #
+//      has another meaning in these. When in character count mode, color codes
+//      are ignored. To get UTF-8 semantics WITHOUT color code parsing, use
+//      the + flag.
+
+//DP_QC_STRFTIME
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//builtin definitions:
+string(float uselocaltime, string format, ...) strftime = #478;
+//description:
+//provides the ability to get the local (in your timezone) or world (Universal Coordinated Time) time as a string using the formatting of your choice:
+//example: "%Y-%m-%d %H:%M:%S"   (result looks like: 2007-02-08 01:03:15)
+//note: "%F %T" gives the same result as "%Y-%m-%d %H:%M:%S" (ISO 8601 date format and 24-hour time)
+//for more format codes please do a web search for strftime 3 and you should find the man(3) pages for this standard C function.
+//
+//practical uses:
+//changing day/night cycle (shops closing, monsters going on the prowl) in an RPG, for this you probably want to use s = strftime(TRUE, "%H");hour = stof(s);
+//printing current date/time for competitive multiplayer games, such as the beginning/end of each round in real world time.
+//activating eastereggs in singleplayer games on certain dates.
+//
+//note: some codes such as %x and %X use your locale settings and thus may not make sense to international users, it is not advisable to use these as the server and clients may be in different countries.
+//note: if you display local time to a player, it would be a good idea to note whether it is local time using a string like "%F %T (local)", and otherwise use "%F %T (UTC)".
+//note: be aware that if the game is saved and reloaded a week later the date and time will be different, so if activating eastereggs in a singleplayer game or something you may want to only check when a level is loaded and then keep the same easteregg state throughout the level so that the easteregg does not deactivate when reloading from a savegame (also be aware that precaches should not depend on such date/time code because reloading a savegame often scrambles the precaches if so!).
+//note: this function can return a NULL string (you can check for it with if (!s)) if the localtime/gmtime functions returned NULL in the engine code, such as if those functions don't work on this platform (consoles perhaps?), so be aware that this may return nothing.
+
+//DP_QC_STRINGCOLORFUNCTIONS
+//idea: Dresk
+//darkplaces implementation: Dresk
+//builtin definitions:
+float(string s) strlennocol = #476; // returns how many characters are in a string, minus color codes
+string(string s) strdecolorize = #477; // returns a string minus the color codes of the string provided
+//description:
+//provides additional functionality to strings by supporting functions that isolate and identify strings with color codes
+
+//DP_QC_STRING_CASE_FUNCTIONS
+//idea: Dresk
+//darkplaces implementation: LordHavoc / Dresk
+//builtin definitions:
+string(string s) strtolower = #480; // returns the passed in string in pure lowercase form
+string(string s) strtoupper = #481; // returns the passed in string in pure uppercase form
+//description:
+//provides simple string uppercase and lowercase functions
+
+//DP_QC_TOKENIZEBYSEPARATOR
+//idea: Electro, SavageX, LordHavoc
+//darkplaces implementation: LordHavoc
+//builtin definitions:
+float(string s, string separator1, ...) tokenizebyseparator = #479;
+//description:
+//this function returns tokens separated by any of the supplied separator strings, example:
+//numnumbers = tokenizebyseparator("10.2.3.4", ".");
+//returns 4 and the tokens are "10" "2" "3" "4"
+//possibly useful for parsing IPv4 addresses (such as "1.2.3.4") and IPv6 addresses (such as "[1234:5678:9abc:def0:1234:5678:9abc:def0]:26000")
+
+//DP_QC_TOKENIZE_CONSOLE
+//idea: divVerent
+//darkplaces implementation: divVerent
+//builtin definitions:
+float(string s) tokenize_console = #514;
+float(float i) argv_start_index = #515;
+float(float i) argv_end_index = #516;
+//description:
+//this function returns tokens separated just like the console does
+//also, functions are provided to get the index of the first and last character of each token in the original string
+//Passing negative values to them, or to argv, will be treated as indexes from the LAST token (like lists work in Perl). So argv(-1) will return the LAST token.
+
+//DP_QC_TRACEBOX
+//idea: id Software
+//darkplaces implementation: id Software
+//builtin definitions:
+void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox = #90;
+//description:
+//similar to traceline but much more useful, traces a box of the size specified (technical note: in quake1 and halflife bsp maps the mins and maxs will be rounded up to one of the hull sizes, quake3 bsp does not have this problem, this is the case with normal moving entities as well).
+
+//DP_QC_TRACETOSS
+//idea: id Software
+//darkplaces implementation: id Software
+//builtin definitions:
+void(entity ent, entity ignore) tracetoss = #64;
+//description:
+//simulates movement of the entity as if it is MOVETYPE_TOSS and starting with it's current state (location, velocity, etc), returns relevant trace_ variables (trace_fraction is always 0, all other values are supported - trace_ent, trace_endpos, trace_plane_normal), does not actually alter the entity.
+
+//DP_QC_TRACE_MOVETYPE_HITMODEL
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//constant definitions:
+float MOVE_HITMODEL = 4;
+//description:
+//allows traces to hit alias models (not sprites!) instead of entity boxes, use as the nomonsters parameter to trace functions, note that you can hit invisible model entities (alpha < 0 or EF_NODRAW or model "", it only checks modelindex)
+
+//DP_QC_TRACE_MOVETYPE_WORLDONLY
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//constant definitions:
+float MOVE_WORLDONLY = 3;
+//description:
+//allows traces to hit only world (ignoring all entities, unlike MOVE_NOMONSTERS which hits all bmodels), use as the nomonsters parameter to trace functions
+
+//DP_QC_UNLIMITEDTEMPSTRINGS
+//idea: divVerent
+//darkplaces implementation: LordHavoc
+//description:
+//this extension alters Quake behavior such that instead of reusing a single
+//tempstring (or multiple) there are an unlimited number of tempstrings, which
+//are removed only when a QC function invoked by the engine returns,
+//eliminating almost all imaginable concerns with string handling in QuakeC.
+//
+//in short:
+//you can now use and abuse tempstrings as much as you like, you still have to
+//use strzone (FRIK_FILE) for permanent storage however.
+//
+//
+//
+//implementation notes for other engine coders:
+//these tempstrings are expected to be stored in a contiguous buffer in memory
+//which may be fixed size or controlled by a cvar, or automatically grown on
+//demand (in the case of DarkPlaces).
+//
+//this concept is similar to quake's Zone system, however these are all freed
+//when the QC interpreter returns.
+//
+//this is basically a poor man's garbage collection system for strings.
+
+//DP_QC_VECTOANGLES_WITH_ROLL
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//builtin definitions:
+vector(vector forward, vector up) vectoangles2 = #51; // same number as vectoangles
+//description:
+//variant of vectoangles that takes an up vector to calculate roll angle (also uses this to calculate yaw correctly if the forward is straight up or straight down)
+//note: just like normal vectoangles you need to negate the pitch of the returned angles if you want to feed them to makevectors or assign to self.v_angle
+
+//DP_QC_VECTORVECTORS
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//builtin definitions:
+void(vector dir) vectorvectors = #432;
+//description:
+//creates v_forward, v_right, and v_up vectors given a forward vector, similar to makevectors except it takes a forward direction vector instead of angles.
+
+//DP_QC_WHICHPACK
+//idea: divVerent
+//darkplaces implementation: divVerent
+//builtin definitions:
+string(string filename) whichpack = #503;
+//description:
+//for files in a pak/pk3/whatever, returns the pack's file name in FRIK_FILE name space.
+//for physical files, returns "".
+//in case of error, returns string_null.
+
+//DP_QC_URI_ESCAPE
+//idea: divVerent
+//darkplaces implementation: divVerent
+//URI::Escape's functionality
+string(string in) uri_escape = #510;
+string(string in) uri_unescape = #511;
+
+//DP_QC_URI_GET
+//idea: divVerent
+//darkplaces implementation: divVerent
+//loads text from an URL into a string
+//returns 1 on success of initiation, 0 if there are too many concurrent
+//connections already or if the URL is invalid
+//the following callback will receive the data and MUST exist!
+//  void(float id, float status, string data) URI_Get_Callback;
+//status is either
+//  negative for an internal error,
+//  0 for success, or
+//  the HTTP response code on server error (e.g. 404)
+//if 1 is returned by uri_get, the callback will be called in the future
+float(string url, float id) uri_get = #513;
+
+//DP_QC_URI_POST
+//idea: divVerent
+//darkplaces implementation: divVerent
+//loads text from an URL into a string after POSTing via HTTP
+//works like uri_get, but uri_post sends data with Content-Type: content_type to the server
+//and uri_post sends the string buffer buf, joined using the delimiter delim
+float(string url, float id, string content_type, string data) uri_post = #513;
+float(string url, float id, string content_type, string delim, float buf) uri_postbuf = #513;
+
+//DP_SKELETONOBJECTS
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//description:
+//this extension indicates that FTE_CSQC_SKELETONOBJECTS functionality is available in server QC (as well as CSQC).
+
+//DP_SV_SPAWNFUNC_PREFIX
+//idea: divVerent
+//darkplaces implementation: divVerent
+//Make functions whose name start with spawnfunc_ take precedence as spawn function for loading entities.
+//Useful if you have a field ammo_shells (required in any Quake mod) but want to support spawn functions called ammo_shells (like in Q3A).
+//Optionally, you can declare a global "float require_spawnfunc_prefix;" which will require ANY spawn function to start with that prefix.
+
+
+//DP_QUAKE2_MODEL
+//idea: quake community
+//darkplaces implementation: LordHavoc
+//description:
+//shows that the engine supports Quake2 .md2 files.
+
+//DP_QUAKE2_SPRITE
+//idea: LordHavoc
+//darkplaces implementation: Elric
+//description:
+//shows that the engine supports Quake2 .sp2 files.
+
+//DP_QUAKE3_MAP
+//idea: quake community
+//darkplaces implementation: LordHavoc
+//description:
+//shows that the engine supports Quake3 .bsp files.
+
+//DP_QUAKE3_MODEL
+//idea: quake community
+//darkplaces implementation: LordHavoc
+//description:
+//shows that the engine supports Quake3 .md3 files.
+
+//DP_REGISTERCVAR
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//builtin definitions:
+float(string name, string value) registercvar = #93;
+//description:
+//adds a new console cvar to the server console (in singleplayer this is the player's console), the cvar exists until the mod is unloaded or the game quits.
+//NOTE: DP_CON_SET is much better.
+
+//DP_SND_DIRECTIONLESSATTNNONE
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//description:
+//make sounds with ATTN_NONE have no spatialization (enabling easy use as music sources).
+
+//DP_SND_FAKETRACKS
+//idea: requested
+
+//darkplaces implementation: Elric
+//description:
+//the engine plays sound/cdtracks/track001.wav instead of cd track 1 and so on if found, this allows games and mods to have music tracks without using ambientsound.
+//Note: also plays .ogg with DP_SND_OGGVORBIS extension.
+
+//DP_SND_SOUND7_WIP1
+//DP_SND_SOUND7_WIP2
+//idea: divVerent
+//darkplaces implementation: divVerent
+//builtin definitions:
+void(entity e, float chan, string samp, float vol, float atten, float speed, float flags) sound7 = #8;
+float SOUNDFLAG_RELIABLE = 1;
+//description:
+//plays a sound, with some more flags
+//extensions to sound():
+//- channel may be in the range from -128 to 127; channels -128 to 0 are "auto",
+//  i.e. support multiple sounds at once, but cannot be stopped/restarted
+//- a value 0 in the speed parameter means no change; otherwise, it is a
+//  percentage of playback speed ("pitch shifting"). 100 is normal pitch, 50 is
+//  half speed, 200 is double speed, etc. (DP_SND_SOUND7_WIP2)
+//- the flag SOUNDFLAG_RELIABLE can be specified, which makes the sound send
+//  to MSG_ALL (reliable) instead of MSG_BROADCAST (unreliable, default);
+//  similarily, SOUNDFLAG_RELIABLE_TO_ONE sends to MSG_ONE
+//- channel 0 is controlled by snd_channel0volume; channel 1 and -1 by
+//  snd_channel1volume, etc. (so, a channel shares the cvar with its respective
+//  auto-channel); however, the mod MUST define snd_channel8volume and upwards
+//  in default.cfg if they are to be used, as the engine does not create them
+//  to not litter the cvar list
+//- this extension applies to CSQC as well; CSQC_Event_Sound will get speed and
+//  flags as extra 7th and 8th argument
+//- WIP2 ideas: SOUNDFLAG_RELIABLE_TO_ONE, SOUNDFLAG_NOPHS, SOUNDFLAG_FORCELOOP
+//- NOTE: to check for this, ALSO OR a check with DP_SND_SOUND7 to also support
+//  the finished extension once done
+
+//DP_SND_OGGVORBIS
+//idea: Transfusion
+//darkplaces implementation: Elric
+//description:
+//the engine supports loading Ogg Vorbis sound files.  Use either the .ogg filename directly, or a .wav of the same name (will try to load the .wav first and then .ogg).
+
+//DP_SND_STEREOWAV
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//description:
+//the engine supports stereo WAV files.  (useful with DP_SND_DIRECTIONLESSATTNNONE for music)
+
+//DP_SND_GETSOUNDTIME
+//idea: VorteX
+//darkplaces implementation: VorteX
+//constant definitions:
+float(entity e, float channel) getsoundtime = #533; // get currently sound playing position on entity channel, -1 if not playing or error
+float(string sample) soundlength = #534; // returns length of sound sample in seconds, -1 on error (sound not precached, sound system not initialized etc.)
+//description: provides opportunity to query length of sound samples and realtime tracking of sound playing on entities (similar to DP_GETTIME_CDTRACK)
+//note: beware dedicated server not running sound engine at all, so in dedicated mode this builtins will not work in server progs
+//note also: menu progs not supporting getsoundtime() (will give a warning) since it has no sound playing on entities
+//examples of use:
+//  - QC-driven looped sounds
+//  - QC events when sound playing is finished
+//  - toggleable ambientsounds
+//  - subtitles
+
+//DP_VIDEO_DPV
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//console commands:
+//  playvideo <videoname> - start playing video
+//  stopvideo - stops current video
+//description: indicated that engine support playing videos in DPV format
+
+//DP_VIDEO_SUBTITLES
+//idea: VorteX
+//darkplaces implementation: VorteX
+//cvars:
+//  cl_video_subtitles - toggles subtitles showing
+//  cl_video_subtitles_lines - how many lines to reserve for subtitles
+//  cl_video_subtitles_textsize - font size
+//console commands:
+//  playvideo <videoname> <custom_subtitles_file> - start playing video
+//  stopvideo - stops current video
+//description: indicates that engine support subtitles on videos
+//subtitles stored in external text files, each video file has it's default subtitles file ( <videoname>.dpsubs )
+//example: for video/act1.dpv default subtitles file will be video/act1.dpsubs
+//also video could be played with custom subtitles file by utilizing second parm of playvideo command
+//syntax of .dpsubs files: each line in .dpsubs file defines 1 subtitle, there are three tokens:
+//   <start> <end> "string"
+//   start: subtitle start time in seconds
+//     end: subtitle time-to-show in seconds, if 0 - subtitle will be showed until next subtitle is started, 
+//          if below 0 - show until next subtitles minus this number of seconds
+//    text: subtitle text, color codes (Q3-style and ^xRGB) are allowed
+//example of subtitle file:
+//   3 0       "Vengeance! Vengeance for my eternity of suffering!"
+//   9 0       "Whelp! As if you knew what eternity was!"
+//   13        0       "Grovel before your true master."
+//   17        0       "Never!" 
+//   18        7       "I'll hack you from crotch to gizzard and feed what's left of you to your brides..."
+
+//DP_SOLIDCORPSE
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//solid definitions:
+float SOLID_CORPSE = 5;
+//description:
+//the entity will not collide with SOLID_CORPSE and SOLID_SLIDEBOX entities (and likewise they will not collide with it), this is useful if you want dead bodies that are shootable but do not obstruct movement by players and monsters, note that if you traceline with a SOLID_SLIDEBOX entity as the ignoreent, it will ignore SOLID_CORPSE entities, this is desirable for visibility and movement traces, but not for bullets, for the traceline to hit SOLID_CORPSE you must temporarily force the player (or whatever) to SOLID_BBOX and then restore to SOLID_SLIDEBOX after the traceline.
+
+//DP_SPRITE32
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//description:
+//the engine supports .spr32 sprites.
+
+//DP_SV_BOTCLIENT
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//constants:
+float CLIENTTYPE_DISCONNECTED = 0;
+float CLIENTTYPE_REAL = 1;
+float CLIENTTYPE_BOT = 2;
+float CLIENTTYPE_NOTACLIENT = 3;
+//builtin definitions:
+entity() spawnclient = #454; // like spawn but for client slots (also calls relevant connect/spawn functions), returns world if no clients available
+float(entity clent) clienttype = #455; // returns one of the CLIENTTYPE_* constants
+//description:
+//spawns a client with no network connection, to allow bots to use client slots with no hacks.
+//How to use:
+/*
+       // to spawn a bot
+       local entity oldself;
+       oldself = self;
+       self = spawnclient();
+       if (!self)
+       {
+               bprint("Can not add bot, server full.\n");
+               self = oldself;
+               return;
+       }
+       self.netname = "Yoyobot";
+       self.clientcolors = 12 * 16 + 4; // yellow (12) shirt and red (4) pants
+       ClientConnect();
+       PutClientInServer();
+       self = oldself;
+
+       // to remove all bots
+       local entity head;
+       head = find(world, classname, "player");
+       while (head)
+       {
+               if (clienttype(head) == CLIENTTYPE_BOT)
+                       dropclient(head);
+               head = find(head, classname, "player");
+       }
+
+       // to identify if a client is a bot (for example in PlayerPreThink)
+       if (clienttype(self) == CLIENTTYPE_BOT)
+               botthink();
+*/
+//see also DP_SV_CLIENTCOLORS DP_SV_CLIENTNAME DP_SV_DROPCLIENT
+//How it works:
+//creates a new client, calls SetNewParms and stores the parms, and returns the client.
+//this intentionally does not call SV_SendServerinfo to allow the QuakeC a chance to set the netname and clientcolors fields before actually spawning the bot by calling ClientConnect and PutClientInServer manually
+//on level change ClientConnect and PutClientInServer are called by the engine to spawn in the bot (this is why clienttype() exists to tell you on the next level what type of client this is).
+//parms work the same on bot clients as they do on real clients, and do carry from level to level
+
+//DP_SV_BOUNCEFACTOR
+//idea: divVerent
+//darkplaces implementation: divVerent
+//field definitions:
+.float bouncefactor; // velocity multiplier after a bounce
+.float bouncestop; // bounce stops if velocity to bounce plane is < bouncestop * gravity AFTER the bounce
+//description:
+//allows qc to customize MOVETYPE_BOUNCE a bit
+
+//DP_SV_CLIENTCAMERA
+//idea: LordHavoc, others
+//darkplaces implementation: Black
+//field definitions:
+.entity clientcamera; // override camera entity
+//description:
+//allows another entity to be the camera for a client, for example a remote camera, this is similar to sending svc_setview manually except that it also changes the network culling appropriately.
+
+//DP_SV_CLIENTCOLORS
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//field definitions:
+.float clientcolors; // colors of the client (format: pants + shirt * 16)
+//description:
+//allows qc to read and modify the client colors associated with a client entity (not particularly useful on other entities), and automatically sends out any appropriate network updates if changed
+
+//DP_SV_CLIENTNAME
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//description:
+//allows qc to modify the client's .netname, and automatically sends out any appropriate network updates if changed
+
+//DP_SV_CUSTOMIZEENTITYFORCLIENT
+//idea: LordHavoc
+//darkplaces implementation: [515] and LordHavoc
+//field definitions:
+.float() customizeentityforclient; // self = this entity, other = client entity
+//description:
+//allows qc to modify an entity before it is sent to each client, the function returns TRUE if it should send, FALSE if it should not, and is fully capable of editing the entity's fields, this allows cloaked players to appear less transparent to their teammates, navigation markers to only show to their team, etc
+//tips on writing customize functions:
+//it is a good idea to return FALSE early in the function if possible to reduce cpu usage, because this function may be called many thousands of times per frame if there are many customized entities on a 64+ player server.
+//you are free to change anything in self, but please do not change any other entities (the results may be very inconsistent).
+//example ideas for use of this extension:
+//making icons over teammates' heads which are only visible to teammates.  for exasmple: float() playericon_customizeentityforclient = {return self.owner.team == other.team;};
+//making cloaked players more visible to their teammates than their enemies.  for example: float() player_customizeentityforclient = {if (self.items & IT_CLOAKING) {if (self.team == other.team) self.alpha = 0.6;else self.alpha = 0.1;} return TRUE;};
+//making explosion models that face the viewer (does not work well with chase_active).  for example: float() explosion_customizeentityforclient = {self.angles = vectoangles(other.origin + other.view_ofs - self.origin);self.angles_x = 0 - self.angles_x;};
+//implementation notes:
+//entity customization is done before per-client culling (visibility for instance) because the entity may be doing setorigin to display itself in different locations on different clients, may be altering its .modelindex, .effects and other fields important to culling, so customized entities increase cpu usage (non-customized entities can use all the early culling they want however, as they are not changing on a per client basis).
+
+//DP_SV_DISCARDABLEDEMO
+//idea: parasti
+//darkplaces implementation: parasti
+//field definitions:
+.float discardabledemo;
+//description:
+//when this field is set to a non-zero value on a player entity, a possibly recorded server-side demo for the player is discarded
+//Note that this extension only works if:
+//  auto demos are enabled (the cvar sv_autodemo_perclient is set)
+//  discarding demos is enabled (the cvar sv_autodemo_perclient_discardable is set)
+
+//DP_SV_DRAWONLYTOCLIENT
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//field definitions:
+.entity drawonlytoclient;
+//description:
+//the entity is only visible to the specified client.
+
+//DP_SV_DROPCLIENT
+//idea: FrikaC
+//darkplaces implementation: LordHavoc
+//builtin definitions:
+void(entity clent) dropclient = #453;
+//description:
+//causes the server to immediately drop the client, more reliable than stuffcmd(clent, "disconnect\n"); which could be intentionally ignored by the client engine
+
+//DP_SV_EFFECT
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//builtin definitions:
+void(vector org, string modelname, float startframe, float endframe, float framerate) effect = #404;
+//SVC definitions:
+//float svc_effect = #52; // [vector] org [byte] modelindex [byte] startframe [byte] framecount [byte] framerate
+//float svc_effect2 = #53; // [vector] org [short] modelindex [byte] startframe [byte] framecount [byte] framerate
+//description:
+//clientside playback of simple custom sprite effects (explosion sprites, etc).
+
+//DP_SV_ENTITYCONTENTSTRANSITION
+//idea: Dresk
+//darkplaces implementation: Dresk
+//field definitions:
+.void(float nOriginalContents, float nNewContents) contentstransition;
+//description:
+//This field function, when provided, is triggered on an entity when the contents (ie. liquid / water / etc) is changed.
+//The first parameter provides the entities original contents, prior to the transition.  The second parameter provides the new contents.
+//NOTE: If this field function is provided on an entity, the standard watersplash sound IS SUPPRESSED to allow for authors to create their own transition sounds.
+
+//DP_SV_MOVETYPESTEP_LANDEVENT
+//idea: Dresk
+//darkplaces implementation: Dresk
+//field definitions:
+.void(vector vImpactVelocity) movetypesteplandevent;
+//description:
+//This field function, when provided, is triggered on a MOVETYPE_STEP entity when it experiences  "land event".
+// The standard engine behavior for this event is to play the sv_sound_land CVar sound.
+//The parameter provides the velocity of the entity at the time of the impact.  The z value may therefore be used to calculate how "hard" the entity struck the surface.
+//NOTE: If this field function is provided on a MOVETYPE_STEP entity, the standard sv_sound_land sound IS SUPPRESSED to allow for authors to create their own feedback.
+
+//DP_SV_POINTSOUND
+//idea: Dresk
+//darkplaces implementation: Dresk
+//builtin definitions:
+void(vector origin, string sample, float volume, float attenuation) pointsound = #483;
+//description:
+//Similar to the standard QC sound function, this function takes an origin instead of an entity and omits the channel parameter.
+// This allows sounds to be played at arbitrary origins without spawning entities.
+
+//DP_SV_ONENTITYNOSPAWNFUNCTION
+//idea: Dresk
+//darkplaces implementation: Dresk
+//engine-called QC prototypes:
+//void() SV_OnEntityNoSpawnFunction;
+//description:
+// This function is called whenever an entity on the server has no spawn function, and therefore has no defined QC behavior.
+// You may as such dictate the behavior as to what happens to the entity.
+// To mimic the engine's default behavior, simply call remove(self).
+
+//DP_SV_ONENTITYPREPOSTSPAWNFUNCTION
+//idea: divVerent
+//darkplaces implementation: divVerent
+//engine-called QC prototypes:
+//void() SV_OnEntityPreSpawnFunction;
+//void() SV_OnEntityPostSpawnFunction;
+//description:
+// These functions are called BEFORE or AFTER an entity is spawned the regular way.
+// You may as such dictate the behavior as to what happens to the entity.
+// SV_OnEntityPreSpawnFunction is called before even looking for the spawn function, so you can even change its classname in there. If it remove()s the entity, the spawn function will not be looked for.
+// SV_OnEntityPostSpawnFunction is called ONLY after its spawn function or SV_OnEntityNoSpawnFunction was called, and skipped if the entity got removed by either.
+
+//DP_SV_MODELFLAGS_AS_EFFECTS
+//idea: LordHavoc, Dresk
+//darkplaces implementation: LordHavoc
+//field definitions:
+.float modelflags;
+//constant definitions:
+float EF_NOMODELFLAGS = 8388608; // ignore any effects in a model file and substitute your own
+float MF_ROCKET  =   1; // leave a trail
+float MF_GRENADE =   2; // leave a trail
+float MF_GIB     =   4; // leave a trail
+float MF_ROTATE  =   8; // rotate (bonus items)
+float MF_TRACER  =  16; // green split trail
+float MF_ZOMGIB  =  32; // small blood trail
+float MF_TRACER2 =  64; // orange split trail
+float MF_TRACER3 = 128; // purple trail
+//description:
+//this extension allows model flags to be specified on entities so you can add a rocket trail and glow to any entity, etc.
+//setting any of these will override the flags the model already has, to disable the model's flags without supplying any of your own you must use EF_NOMODELFLAGS.
+//
+//silly example modification #1 to W_FireRocket in weapons.qc:
+//missile.effects = EF_NOMODELFLAGS; // rocket without a glow/fire trail
+//silly example modification #2 to W_FireRocket in weapons.qc:
+//missile.modelflags = MF_GIB; // leave a blood trail instead of glow/fire trail
+//
+//note: you can not combine multiple kinds of trail, only one of them will be active, you can combine MF_ROTATE and the other MF_ flags however, and using EF_NOMODELFLAGS along with these does no harm.
+//
+//note to engine coders: they are internally encoded in the protocol as extra EF_ flags (shift the values left 24 bits and send them in the protocol that way), so no protocol change was required (however 32bit effects is a protocol extension itself), within the engine they are referred to as EF_ for the 24bit shifted values.
+
+//DP_SV_NETADDRESS
+//idea: Dresk
+//darkplaces implementation: Dresk
+//field definitions:
+.string netaddress;
+//description:
+// provides the netaddress of the associated entity (ie. 127.0.0.1) and "null/botclient" if the netconnection of the entity is invalid
+
+//DP_SV_NODRAWTOCLIENT
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//field definitions:
+.entity nodrawtoclient;
+//description:
+//the entity is not visible to the specified client.
+
+//DP_SV_PING
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//field definitions:
+.float ping;
+//description:
+//continuously updated field indicating client's ping (based on average of last 16 packet time differences).
+
+//DP_SV_PING_PACKETLOSS
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//field definitions:
+.float ping_packetloss;
+.float ping_movementloss;
+//description:
+//continuously updated field indicating client's packet loss, and movement loss (i.e. packet loss affecting player movement).
+
+//DP_SV_POINTPARTICLES
+//idea: Spike
+//darkplaces implementation: LordHavoc
+//function definitions:
+float(string effectname) particleeffectnum = #335; // same as in CSQC
+void(entity ent, float effectnum, vector start, vector end) trailparticles = #336; // same as in CSQC
+void(float effectnum, vector org, vector vel, float howmany) pointparticles = #337; // same as in CSQC
+//SVC definitions:
+//float svc_trailparticles = 60; // [short] entnum [short] effectnum [vector] start [vector] end
+//float svc_pointparticles = 61; // [short] effectnum [vector] start [vector] velocity [short] count
+//float svc_pointparticles1 = 62; // [short] effectnum [vector] start, same as svc_pointparticles except velocity is zero and count is 1
+//description:
+//provides the ability to spawn non-standard particle effects, typically these are defined in a particle effect information file such as effectinfo.txt in darkplaces.
+//this is a port of particle effect features from clientside QC (EXT_CSQC) to server QC, as these effects are potentially useful to all games even if they do not make use of EXT_CSQC.
+//warning: server must have same order of effects in effectinfo.txt as client does or the numbers would not match up, except for standard quake effects which are always the same numbers.
+
+//DP_SV_PUNCHVECTOR
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//field definitions:
+.vector punchvector;
+//description:
+//offsets client view in worldspace, similar to view_ofs but all 3 components are used and are sent with at least 8 bits of fraction, this allows the view to be kicked around by damage or hard landings or whatever else, note that unlike punchangle this is not faded over time, it is up to the mod to fade it (see also DP_SV_PLAYERPHYSICS).
+
+//DP_SV_PLAYERPHYSICS
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//field definitions:
+.vector movement;
+//cvar definitions:
+//"sv_playerphysicsqc" (0/1, default 1, allows user to disable qc player physics)
+//engine-called QC prototypes:
+//void() SV_PlayerPhysics;
+//description:
+//.movement vector contains the movement input from the player, allowing QC to do as it wishs with the input, and SV_PlayerPhysics will completely replace the player physics if present (works for all MOVETYPE's), see darkplaces mod source for example of this function (in playermovement.qc, adds HalfLife ladders support, as well as acceleration/deceleration while airborn (rather than the quake sudden-stop while airborn), and simplifies the physics a bit)
+
+//DP_PHYSICS_ODE
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//globals:
+//new movetypes:
+const float MOVETYPE_PHYSICS = 32; // need to be set before any physics_* builtins applied
+//new solid types (deprecated):
+const float SOLID_PHYSICS_BOX = 32;
+const float SOLID_PHYSICS_SPHERE = 33;
+const float SOLID_PHYSICS_CAPSULE = 34;
+const float SOLID_PHYSICS_TRIMESH = 35;
+const float SOLID_PHYSICS_CYLINDER = 36;
+//geometry types:
+const float GEOMTYPE_NONE = -1;       // entity will be entirely skipped by ODE
+const float GEOMTYPE_SOLID = 0;       // geometry type will be set based on .solid field
+const float GEOMTYPE_BOX = 1;         // entity bound box
+const float GEOMTYPE_SPHERE = 2;      // sphere with radius picked from x axis of entity bound box
+const float GEOMTYPE_CAPSULE = 3;     // with leading axis automatically determined from longest one, radius is picked as minimal of the rest 2 axes
+const float GEOMTYPE_TRIMESH = 4;     // triangle mesh
+const float GEOMTYPE_CYLINDER = 5;    // like capsule but not capped
+                                      // note that ODE's builtin cylinder support is experimental, somewhat bugged and unfinished (no cylinder-cylinder collision)
+                                                                         // to use properly working cylinder should build ODE with LIBCCD extension
+const float GEOMTYPE_CAPSULE_X = 6;   // capsule with fixed leading axis
+const float GEOMTYPE_CAPSULE_Y = 7;
+const float GEOMTYPE_CAPSULE_Z = 8;
+const float GEOMTYPE_CYLINDER_X        = 9;  // cylinder with fixed leading axis
+const float GEOMTYPE_CYLINDER_Y        = 10;
+const float GEOMTYPE_CYLINDER_Z        = 11;
+//joint types:
+const float JOINTTYPE_NONE = 0;
+const float JOINTTYPE_POINT = 1;
+const float JOINTTYPE_HINGE = 2;
+const float JOINTTYPE_SLIDER = 3;
+const float JOINTTYPE_UNIVERSAL = 4;
+const float JOINTTYPE_HINGE2 = 5;
+const float JOINTTYPE_FIXED = -1;
+//force types:
+const float FORCETYPE_NONE = 0;
+const float FORCETYPE_FORCE = 1; // applied at center of mass
+const float FORCETYPE_FORCEATPOS = 2;
+const float FORCETYPE_TORQUE = 3;
+// common joint properties:
+// .entity aiment; // connected objects
+// .entity enemy; // connected objects, forces
+// .vector movedir;
+//   for a spring:
+//     movedir_x = spring constant (force multiplier, must be > 0)
+//     movedir_y = spring dampening constant to prevent oscillation (must be > 0)
+//     movedir_z = spring stop position (+/-)
+//   for a motor:
+//     movedir_x = desired motor velocity
+//     movedir_y = -1 * max motor force to use
+//     movedir_z = stop position (+/-), set to 0 for no stop
+//   note that ODE does not support both in one anyway
+//   for a force:
+//     force vector to apply
+//field definitions:
+.float  geomtype;     // see GEOMTYPE_*, a more correct way to set collision shape, allows to set SOLID_CORPSE and trimesh collisions
+.float  maxcontacts;  // maximum number of contacts to make for this object, lesser = faster (but setting it too low will could make object pass though walls), default is 16, maximum is 32
+.float  mass;         // ODE mass, standart value is 1
+.vector massofs;      // offsets a mass center out of object center, if not set a center of model bounds is used
+.float  friction;     // a friction of object, get multiplied by second objects's friction on contact
+.float  bouncefactor;
+.float  bouncestop; 
+.float  jointtype;    // type of joint
+.float  forcetype;    // type of force
+.float  erp;          // error restitution parameter, makes ODE solver attempt to fix errors in contacts, 
+                      // bringing together 2 joints or fixing object being stuch in other object, 
+                                 // a value of 0.1 will fix slightly, a value of 1.0 attempts to fix whole error in one frame
+                                 // use with care as high values makes system unstable and likely to explode
+//builtin definitions:
+void(entity e, float physics_enabled) physics_enable = #540; // enable or disable physics on object
+void(entity e, vector force, vector force_pos) physics_addforce = #541; // deprecated, apply a force from certain origin, length of force vector is power of force
+void(entity e, vector torque) physics_addtorque = #542; // deprecated, add relative torque
+//description: provides Open Dynamics Engine support, requires extenal dll to be present or engine compiled with statical link option
+//be sure to checkextension for it to know if library is loaded and ready, also to enable physics set "physics_ode" cvar to 1
+//note: this extension is highly experimental and may be unstable
+
+//DP_SV_PRINT
+//idea: id Software (QuakeWorld Server)
+//darkplaces implementation: Black, LordHavoc
+void(string s, ...) print = #339; // same number as in EXT_CSQC
+//description:
+//this is identical to dprint except that it always prints regardless of the developer cvar.
+
+//DP_SV_PRECACHEANYTIME
+//idea: id Software (Quake2)
+//darkplaces implementation: LordHavoc
+//description:
+//this extension allows precache_model and precache_sound (and any variants) to be used during the game (with automatic messages to clients to precache the new model/sound indices), also setmodel/sound/ambientsound can be called without precaching first (they will cause an automatic precache).
+
+//DP_SV_QCSTATUS
+//idea: divVerent
+//darkplaces implementation: divVerent
+//1. A global variable
+string worldstatus;
+//Its content is set as "qcstatus" field in the rules.
+//It may be at most 255 characters, and must not contain newlines or backslashes.
+//2. A per-client field
+.string clientstatus;
+//It is sent instead of the "frags" in status responses.
+//It should always be set in a way so that stof(player.clientstatus) is a meaningful score value. Other info may be appended. If used this way, the cvar sv_status_use_qcstatus may be set to 1, and then this value will replace the frags in "status".
+//Currently, qstat does not support this and will not show player info if used and set to anything other than ftos(some integer).
+
+//DP_SV_ROTATINGBMODEL
+//idea: id Software
+//darkplaces implementation: LordHavoc
+//description:
+//this extension merely indicates that MOVETYPE_PUSH supports avelocity, allowing rotating brush models to be created, they rotate around their origin (needs rotation supporting qbsp/light utilities because id ones expected bmodel entity origins to be '0 0 0', recommend setting "origin" key in the entity fields in the map before compiling, there may be other methods depending on your qbsp, most are more complicated however).
+//tip: level designers can create a func_wall with an origin, and avelocity (for example "avelocity" "0 90 0"), and "nextthink" "99999999" to make a rotating bmodel without any qc modifications, such entities will be solid in stock quake but will not rotate)
+
+//DP_SV_SETCOLOR
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//builtin definitions:
+void(entity ent, float colors) setcolor = #401;
+//engine called QC functions (optional):
+//void(float color) SV_ChangeTeam;
+//description:
+//setcolor sets the color on a client and updates internal color information accordingly (equivalent to stuffing a "color" command but immediate)
+//SV_ChangeTeam is called by the engine whenever a "color" command is recieved, it may decide to do anything it pleases with the color passed by the client, including rejecting it (by doing nothing), or calling setcolor to apply it, preventing team changes is one use for this.
+//the color format is pants + shirt * 16 (0-255 potentially)
+
+//DP_SV_SLOWMO
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//cvars:
+//"slowmo" (0+, default 1)
+//description:
+//sets the time scale of the server, mainly intended for use in singleplayer by the player, however potentially useful for mods, so here's an extension for it.
+//range is 0 to infinite, recommended values to try are 0.1 (very slow, 10% speed), 1 (normal speed), 5 (500% speed).
+
+//DP_SV_WRITEPICTURE
+//idea: divVerent
+//darkplaces implementation: divVerent
+//builtin definitions:
+void(float to, string s, float sz) WritePicture = #501;
+//description:
+//writes a picture to the data stream so CSQC can read it using ReadPicture, which has the definition
+//  string(void) ReadPicture = #501;
+//The picture data is sent as at most sz bytes, by compressing to low quality
+//JPEG. The data being sent will be equivalent to:
+//  WriteString(to, s);
+//  WriteShort(to, imagesize);
+//  for(i = 0; i < imagesize; ++i)
+//    WriteByte(to, [the i-th byte of the compressed JPEG image]);
+
+//DP_SV_WRITEUNTERMINATEDSTRING
+//idea: FrikaC
+//darkplaces implementation: Sajt
+//builtin definitions:
+void(float to, string s) WriteUnterminatedString = #456;
+//description:
+//like WriteString, but does not write a terminating 0 after the string. This means you can include things like a player's netname in the middle of a string sent over the network. Just be sure to end it up with either a call to WriteString (which includes the trailing 0) or WriteByte(0) to terminate it yourself.
+//A historical note: this extension was suggested by FrikaC years ago, more recently Shadowalker has been badmouthing LordHavoc and Spike for stealing 'his' extension writestring2 which does exactly the same thing but uses a different builtin number and name and extension string, this argument hinges on the idea that it was his idea in the first place, which is incorrect as FrikaC first suggested it and used a rough equivalent of it in his FrikBot mod years ago involving WriteByte calls on each character.
+
+//DP_TE_BLOOD
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//builtin definitions:
+void(vector org, vector velocity, float howmany) te_blood = #405;
+//temp entity definitions:
+float TE_BLOOD = 50;
+//protocol:
+//vector origin
+//byte xvelocity (-128 to +127)
+//byte yvelocity (-128 to +127)
+//byte zvelocity (-128 to +127)
+//byte count (0 to 255, how much blood)
+//description:
+//creates a blood effect.
+
+//DP_TE_BLOODSHOWER
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//builtin definitions:
+void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower = #406;
+//temp entity definitions:
+//float TE_BLOODSHOWER = 52;
+//protocol:
+//vector mins (minimum corner of the cube)
+//vector maxs (maximum corner of the cube)
+//coord explosionspeed (velocity of blood particles flying out of the center)
+//short count (number of blood particles)
+//description:
+//creates an exploding shower of blood, for making gibbings more convincing.
+
+//DP_TE_CUSTOMFLASH
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//builtin definitions:
+void(vector org, float radius, float lifetime, vector color) te_customflash = #417;
+//temp entity definitions:
+//float TE_CUSTOMFLASH = 73;
+//protocol:
+//vector origin
+//byte radius ((MSG_ReadByte() + 1) * 8, meaning 8-2048 unit radius)
+//byte lifetime ((MSG_ReadByte() + 1) / 256.0, meaning approximately 0-1 second lifetime)
+//byte red (0.0 to 1.0 converted to 0-255)
+//byte green (0.0 to 1.0 converted to 0-255)
+//byte blue (0.0 to 1.0 converted to 0-255)
+//description:
+//creates a customized light flash.
+
+//DP_TE_EXPLOSIONRGB
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//builtin definitions:
+void(vector org, vector color) te_explosionrgb = #407;
+//temp entity definitions:
+//float TE_EXPLOSIONRGB = 53;
+//protocol:
+//vector origin
+//byte red (0.0 to 1.0 converted to 0 to 255)
+//byte green (0.0 to 1.0 converted to 0 to 255)
+//byte blue (0.0 to 1.0 converted to 0 to 255)
+//description:
+//creates a colored explosion effect.
+
+//DP_TE_FLAMEJET
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//builtin definitions:
+void(vector org, vector vel, float howmany) te_flamejet = #457;
+//temp entity definitions:
+//float TE_FLAMEJET = 74;
+//protocol:
+//vector origin
+//vector velocity
+//byte count (0 to 255, how many flame particles)
+//description:
+//creates a single puff of flame particles.  (not very useful really)
+
+//DP_TE_PARTICLECUBE
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//builtin definitions:
+void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube = #408;
+//temp entity definitions:
+//float TE_PARTICLECUBE = 54;
+//protocol:
+//vector mins (minimum corner of the cube)
+//vector maxs (maximum corner of the cube)
+//vector velocity
+//short count
+//byte color (palette color)
+//byte gravity (TRUE or FALSE, FIXME should this be a scaler instead?)
+//coord randomvel (how much to jitter the velocity)
+//description:
+//creates a cloud of particles, useful for forcefields but quite customizable.
+
+//DP_TE_PARTICLERAIN
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//builtin definitions:
+void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain = #409;
+//temp entity definitions:
+//float TE_PARTICLERAIN = 55;
+//protocol:
+//vector mins (minimum corner of the cube)
+//vector maxs (maximum corner of the cube)
+//vector velocity (velocity of particles)
+//short count (number of particles)
+//byte color (8bit palette color)
+//description:
+//creates a shower of rain, the rain will appear either at the top (if falling down) or bottom (if falling up) of the cube.
+
+//DP_TE_PARTICLESNOW
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//builtin definitions:
+void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow = #410;
+//temp entity definitions:
+//float TE_PARTICLERAIN = 56;
+//protocol:
+//vector mins (minimum corner of the cube)
+//vector maxs (maximum corner of the cube)
+//vector velocity (velocity of particles)
+//short count (number of particles)
+//byte color (8bit palette color)
+//description:
+//creates a shower of snow, the snow will appear either at the top (if falling down) or bottom (if falling up) of the cube, low velocities are advisable for convincing snow.
+
+//DP_TE_PLASMABURN
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//builtin definitions:
+void(vector org) te_plasmaburn = #433;
+//temp entity definitions:
+//float TE_PLASMABURN = 75;
+//protocol:
+//vector origin
+//description:
+//creates a small light flash (radius 200, time 0.2) and marks the walls.
+
+//DP_TE_QUADEFFECTS1
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//builtin definitions:
+void(vector org) te_gunshotquad = #412;
+void(vector org) te_spikequad = #413;
+void(vector org) te_superspikequad = #414;
+void(vector org) te_explosionquad = #415;
+//temp entity definitions:
+//float   TE_GUNSHOTQUAD  = 57; // [vector] origin
+//float   TE_SPIKEQUAD    = 58; // [vector] origin
+//float   TE_SUPERSPIKEQUAD = 59; // [vector] origin
+//float   TE_EXPLOSIONQUAD = 70; // [vector] origin
+//protocol:
+//vector origin
+//description:
+//all of these just take a location, and are equivalent in function (but not appearance :) to the original TE_GUNSHOT, etc.
+
+//DP_TE_SMALLFLASH
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//builtin definitions:
+void(vector org) te_smallflash = #416;
+//temp entity definitions:
+//float TE_SMALLFLASH = 72;
+//protocol:
+//vector origin
+//description:
+//creates a small light flash (radius 200, time 0.2).
+
+//DP_TE_SPARK
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//builtin definitions:
+void(vector org, vector vel, float howmany) te_spark = #411;
+//temp entity definitions:
+//float TE_SPARK = 51;
+//protocol:
+//vector origin
+//byte xvelocity (-128 to 127)
+//byte yvelocity (-128 to 127)
+//byte zvelocity (-128 to 127)
+//byte count (number of sparks)
+//description:
+//creates a shower of sparks and a smoke puff.
+
+//DP_TE_STANDARDEFFECTBUILTINS
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//builtin definitions:
+void(vector org) te_gunshot = #418;
+void(vector org) te_spike = #419;
+void(vector org) te_superspike = #420;
+void(vector org) te_explosion = #421;
+void(vector org) te_tarexplosion = #422;
+void(vector org) te_wizspike = #423;
+void(vector org) te_knightspike = #424;
+void(vector org) te_lavasplash = #425;
+void(vector org) te_teleport = #426;
+void(vector org, float color, float colorlength) te_explosion2 = #427;
+void(entity own, vector start, vector end) te_lightning1 = #428;
+void(entity own, vector start, vector end) te_lightning2 = #429;
+void(entity own, vector start, vector end) te_lightning3 = #430;
+void(entity own, vector start, vector end) te_beam = #431;
+//description:
+//to make life easier on mod coders.
+
+//DP_TRACE_HITCONTENTSMASK_SURFACEINFO
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//globals:
+.float dphitcontentsmask; // if non-zero on the entity passed to traceline/tracebox/tracetoss this will override the normal collidable contents rules and instead hit these contents values (for example AI can use tracelines that hit DONOTENTER if it wants to, by simply changing this field on the entity passed to traceline), this affects normal movement as well as trace calls
+float trace_dpstartcontents; // DPCONTENTS_ value at start position of trace
+float trace_dphitcontents; // DPCONTENTS_ value of impacted surface (not contents at impact point, just contents of the surface that was hit)
+float trace_dphitq3surfaceflags; // Q3SURFACEFLAG_ value of impacted surface
+string trace_dphittexturename; // texture name of impacted surface
+//constants:
+float DPCONTENTS_SOLID = 1; // hit a bmodel, not a bounding box
+float DPCONTENTS_WATER = 2;
+float DPCONTENTS_SLIME = 4;
+float DPCONTENTS_LAVA = 8;
+float DPCONTENTS_SKY = 16;
+float DPCONTENTS_BODY = 32; // hit a bounding box, not a bmodel
+float DPCONTENTS_CORPSE = 64; // hit a SOLID_CORPSE entity
+float DPCONTENTS_NODROP = 128; // an area where backpacks should not spawn
+float DPCONTENTS_PLAYERCLIP = 256; // blocks player movement
+float DPCONTENTS_MONSTERCLIP = 512; // blocks monster movement
+float DPCONTENTS_DONOTENTER = 1024; // AI hint brush
+float DPCONTENTS_LIQUIDSMASK = 14; // WATER | SLIME | LAVA
+float DPCONTENTS_BOTCLIP = 2048; // AI hint brush
+float DPCONTENTS_OPAQUE = 4096; // only fully opaque brushes get this (may be useful for line of sight checks)
+float Q3SURFACEFLAG_NODAMAGE = 1;
+float Q3SURFACEFLAG_SLICK = 2; // low friction surface
+float Q3SURFACEFLAG_SKY = 4; // sky surface (also has NOIMPACT and NOMARKS set)
+float Q3SURFACEFLAG_LADDER = 8; // climbable surface
+float Q3SURFACEFLAG_NOIMPACT = 16; // projectiles should remove themselves on impact (this is set on sky)
+float Q3SURFACEFLAG_NOMARKS = 32; // projectiles should not leave marks, such as decals (this is set on sky)
+float Q3SURFACEFLAG_FLESH = 64; // projectiles should do a fleshy effect (blood?) on impact
+float Q3SURFACEFLAG_NODRAW = 128; // compiler hint (not important to qc)
+//float Q3SURFACEFLAG_HINT = 256; // compiler hint (not important to qc)
+//float Q3SURFACEFLAG_SKIP = 512; // compiler hint (not important to qc)
+//float Q3SURFACEFLAG_NOLIGHTMAP = 1024; // compiler hint (not important to qc)
+//float Q3SURFACEFLAG_POINTLIGHT = 2048; // compiler hint (not important to qc)
+float Q3SURFACEFLAG_METALSTEPS = 4096; // walking on this surface should make metal step sounds
+float Q3SURFACEFLAG_NOSTEPS = 8192; // walking on this surface should not make footstep sounds
+float Q3SURFACEFLAG_NONSOLID = 16384; // compiler hint (not important to qc)
+//float Q3SURFACEFLAG_LIGHTFILTER = 32768; // compiler hint (not important to qc)
+//float Q3SURFACEFLAG_ALPHASHADOW = 65536; // compiler hint (not important to qc)
+//float Q3SURFACEFLAG_NODLIGHT = 131072; // compiler hint (not important to qc)
+//float Q3SURFACEFLAG_DUST = 262144; // translucent 'light beam' effect (not important to qc)
+//description:
+//adds additional information after a traceline/tracebox/tracetoss call.
+//also (very important) sets trace_* globals before calling .touch functions,
+//this allows them to inspect the nature of the collision (for example
+//determining if a projectile hit sky), clears trace_* variables for the other
+//object in a touch event (that is to say, a projectile moving will see the
+//trace results in its .touch function, but the player it hit will see very
+//little information in the trace_ variables as it was not moving at the time)
+
+//DP_VIEWZOOM
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc
+//field definitions:
+.float viewzoom;
+//description:
+//scales fov and sensitivity of player, valid range is 0 to 1 (intended for sniper rifle zooming, and such)
+
+//EXT_BITSHIFT
+//idea: Spike
+//darkplaces implementation: [515]
+//builtin definitions:
+float(float number, float quantity) bitshift = #218;
+//description:
+//multiplies number by a power of 2 corresponding to quantity (0 = *1, 1 = *2, 2 = *4, 3 = *8, -1 = /2, -2 = /4x, etc), and rounds down (due to integer math) like other bit operations do (& and | and the like).
+//note: it is faster to use multiply if you are shifting by a constant, avoiding the quakec function call cost, however that does not do a floor for you.
+
+//FRIK_FILE
+//idea: FrikaC
+//darkplaces implementation: LordHavoc
+//builtin definitions:
+float(string s) stof = #81; // get numerical value from a string
+float(string filename, float mode) fopen = #110; // opens a file inside quake/gamedir/data/ (mode is FILE_READ, FILE_APPEND, or FILE_WRITE), returns fhandle >= 0 if successful, or fhandle < 0 if unable to open file for any reason
+void(float fhandle) fclose = #111; // closes a file
+string(float fhandle) fgets = #112; // reads a line of text from the file and returns as a tempstring
+void(float fhandle, string s, ...) fputs = #113; // writes a line of text to the end of the file
+float(string s) strlen = #114; // returns how many characters are in a string
+string(string s1, string s2, ...) strcat = #115; // concatenates two or more strings (for example "abc", "def" would return "abcdef") and returns as a tempstring
+string(string s, float start, float length) substring = #116; // returns a section of a string as a tempstring - see FTE_STRINGS for enhanced version
+vector(string s) stov = #117; // returns vector value from a string
+string(string s, ...) strzone = #118; // makes a copy of a string into the string zone and returns it, this is often used to keep around a tempstring for longer periods of time (tempstrings are replaced often)
+void(string s) strunzone = #119; // removes a copy of a string from the string zone (you can not use that string again or it may crash!!!)
+//constants:
+float FILE_READ = 0;
+float FILE_APPEND = 1;
+float FILE_WRITE = 2;
+//cvars:
+//pr_zone_min_strings : default 64 (64k), min 64 (64k), max 8192 (8mb)
+//description:
+//provides text file access functions and string manipulation functions, note that you may want to set pr_zone_min_strings in the worldspawn function if 64k is not enough string zone space.
+//
+//NOTE: strzone functionality is partially superseded by
+//DP_QC_UNLIMITEDTEMPSTRINGS when longterm storage is not needed
+//NOTE: substring is upgraded by FTE_STRINGS extension with negative start/length handling identical to php 5.2.0
+
+//FTE_CSQC_SKELETONOBJECTS
+//idea: Spike, LordHavoc
+//darkplaces implementation: LordHavoc
+//builtin definitions:
+// all skeleton numbers are 1-based (0 being no skeleton)
+// all bone numbers are 1-based (0 being invalid)
+float(float modlindex) skel_create = #263; // create a skeleton (be sure to assign this value into .skeletonindex for use), returns skeleton index (1 or higher) on success, returns 0 on failure (for example if the modelindex is not skeletal), it is recommended that you create a new skeleton if you change modelindex, as the skeleton uses the hierarchy from the model.
+float(float skel, entity ent, float modlindex, float retainfrac, float firstbone, float lastbone) skel_build = #264; // blend in a percentage of standard animation, 0 replaces entirely, 1 does nothing, 0.5 blends half, etc, and this only alters the bones in the specified range for which out of bounds values like 0,100000 are safe (uses .frame, .frame2, .frame3, .frame4, .lerpfrac, .lerpfrac3, .lerpfrac4, .frame1time, .frame2time, .frame3time, .frame4time), returns skel on success, 0 on failure
+float(float skel) skel_get_numbones = #265; // returns how many bones exist in the created skeleton, 0 if skeleton does not exist
+string(float skel, float bonenum) skel_get_bonename = #266; // returns name of bone (as a tempstring), "" if invalid bonenum (< 1 for example) or skeleton does not exist
+float(float skel, float bonenum) skel_get_boneparent = #267; // returns parent num for supplied bonenum, 0 if bonenum has no parent or bone does not exist (returned value is always less than bonenum, you can loop on this)
+float(float skel, string tagname) skel_find_bone = #268; // get number of bone with specified name, 0 on failure, bonenum (1-based) on success, same as using gettagindex but takes modelindex instead of entity
+vector(float skel, float bonenum) skel_get_bonerel = #269; // get matrix of bone in skeleton relative to its parent - sets v_forward, v_right, v_up, returns origin (relative to parent bone)
+vector(float skel, float bonenum) skel_get_boneabs = #270; // get matrix of bone in skeleton in model space - sets v_forward, v_right, v_up, returns origin (relative to entity)
+void(float skel, float bonenum, vector org) skel_set_bone = #271; // set matrix of bone relative to its parent, reads v_forward, v_right, v_up, takes origin as parameter (relative to parent bone)
+void(float skel, float bonenum, vector org) skel_mul_bone = #272; // transform bone matrix (relative to its parent) by the supplied matrix in v_forward, v_right, v_up, takes origin as parameter (relative to parent bone)
+void(float skel, float startbone, float endbone, vector org) skel_mul_bones = #273; // transform bone matrices (relative to their parents) by the supplied matrix in v_forward, v_right, v_up, takes origin as parameter (relative to parent bones)
+void(float skeldst, float skelsrc, float startbone, float endbone) skel_copybones = #274; // copy bone matrices (relative to their parents) from one skeleton to another, useful for copying a skeleton to a corpse
+void(float skel) skel_delete = #275; // deletes skeleton at the beginning of the next frame (you can add the entity, delete the skeleton, renderscene, and it will still work)
+float(float modlindex, string framename) frameforname = #276; // finds number of a specified frame in the animation, returns -1 if no match found
+float(float modlindex, float framenum) frameduration = #277; // returns the intended play time (in seconds) of the specified framegroup, if it does not exist the result is 0, if it is a single frame it may be a small value around 0.1 or 0.
+//fields:
+.float skeletonindex; // active skeleton overriding standard animation on model
+.float frame; // primary framegroup animation (strength = 1 - lerpfrac - lerpfrac3 - lerpfrac4)
+.float frame2; // secondary framegroup animation (strength = lerpfrac)
+.float frame3; // tertiary framegroup animation (strength = lerpfrac3)
+.float frame4; // quaternary framegroup animation (strength = lerpfrac4)
+.float lerpfrac; // strength of framegroup blend
+.float lerpfrac3; // strength of framegroup blend
+.float lerpfrac4; // strength of framegroup blend
+.float frame1time; // start time of framegroup animation
+.float frame2time; // start time of framegroup animation
+.float frame3time; // start time of framegroup animation
+.float frame4time; // start time of framegroup animation
+//description:
+//this extension provides a way to do complex skeletal animation on an entity.
+//
+//see also DP_SKELETONOBJECTS (this extension implemented on server as well as client)
+//
+//notes:
+//each model contains its own skeleton, reusing a skeleton with incompatible models will yield garbage (or not render).
+//each model contains its own animation data, you can use animations from other model files (for example saving out all character animations as separate model files).
+//if an engine supports loading an animation-only file format such as .md5anim in FTEQW, it can be used to animate any model with a compatible skeleton.
+//proper use of this extension may require understanding matrix transforms (v_forward, v_right, v_up, origin), and you must keep in mind that v_right is negative for this purpose.
+//
+//features include:
+//multiple animations blended together.
+//animating a model with animations from another model with a compatible skeleton.
+//restricting animation blends to certain bones of a model - for example independent animation of legs, torso, head.
+//custom bone controllers - for example making eyes track a target location.
+//
+//
+//
+//example code follows...
+//
+//this helper function lets you identify (by parentage) what group a bone
+//belongs to - for example "torso", "leftarm", would return 1 ("torso") for
+//all children of the bone named "torso", unless they are children of
+//"leftarm" (which is a child of "torso") which would return 2 instead...
+float(float skel, float bonenum, string g1, string g2, string g3, string g4, string g5, string g6) example_skel_findbonegroup =
+{
+       local string bonename;
+       while (bonenum >= 0)
+       {
+               bonename = skel_get_bonename(skel, bonenum);
+               if (bonename == g1) return 1;
+               if (bonename == g2) return 2;
+               if (bonename == g3) return 3;
+               if (bonename == g4) return 4;
+               if (bonename == g5) return 5;
+               if (bonename == g6) return 6;
+               bonenum = skel_get_boneparent(skel, bonenum);
+       }
+       return 0;
+};
+// create a skeletonindex for our player using current modelindex
+void() example_skel_player_setup =
+{
+       self.skeletonindex = skel_create(self.modelindex);
+};
+// setup bones of skeleton based on an animation
+// note: animmodelindex can be a different model than self.modelindex
+void(float animmodelindex, float framegroup, float framegroupstarttime) example_skel_player_update_begin =
+{
+       // start with our standard animation
+       self.frame = framegroup;
+       self.frame2 = 0;
+       self.frame3 = 0;
+       self.frame4 = 0;
+       self.frame1time = framegroupstarttime;
+       self.frame2time = 0;
+       self.frame3time = 0;
+       self.frame4time = 0;
+       self.lerpfrac = 0;
+       self.lerpfrac3 = 0;
+       self.lerpfrac4 = 0;
+       skel_build(self.skeletonindex, self, animmodelindex, 0, 0, 100000);
+};
+// apply a different framegroup animation to bones with a specified parent
+void(float animmodelindex, float framegroup, float framegroupstarttime, float blendalpha, string groupbonename, string excludegroupname1, string excludegroupname2) example_skel_player_update_applyoverride =
+{
+       local float bonenum;
+       local float numbones;
+       self.frame = framegroup;
+       self.frame2 = 0;
+       self.frame3 = 0;
+       self.frame4 = 0;
+       self.frame1time = framegroupstarttime;
+       self.frame2time = 0;
+       self.frame3time = 0;
+       self.frame4time = 0;
+       self.lerpfrac = 0;
+       self.lerpfrac3 = 0;
+       self.lerpfrac4 = 0;
+       bonenum = 0;
+       numbones = skel_get_numbones(self.skeletonindex);
+       while (bonenum < numbones)
+       {
+               if (example_skel_findbonegroup(self.skeletonindex, bonenum, groupbonename, excludegroupname1, excludegroupname2, "", "", "") == 1)
+                       skel_build(self.skeletonindex, self, animmodelindex, 1 - blendalpha, bonenum, bonenum + 1);
+               bonenum = bonenum + 1;
+       }
+};
+// make eyes point at a target location, be sure v_forward, v_right, v_up are set correctly before calling
+void(vector eyetarget, string bonename) example_skel_player_update_eyetarget =
+{
+       local float bonenum;
+       local vector ang;
+       local vector oldforward, oldright, oldup;
+       local vector relforward, relright, relup, relorg;
+       local vector boneforward, boneright, boneup, boneorg;
+       local vector parentforward, parentright, parentup, parentorg;
+       local vector u, v;
+       local vector modeleyetarget;
+       bonenum = skel_find_bone(self.skeletonindex, bonename) - 1;
+       if (bonenum < 0)
+               return;
+       oldforward = v_forward;
+       oldright = v_right;
+       oldup = v_up;
+       v = eyetarget - self.origin;
+       modeleyetarget_x =   v * v_forward;
+       modeleyetarget_y = 0-v * v_right;
+       modeleyetarget_z =   v * v_up;
+       // this is an eyeball, make it point at the target location
+       // first get all the data we can...
+       relorg = skel_get_bonerel(self.skeletonindex, bonenum);
+       relforward = v_forward;
+       relright = v_right;
+       relup = v_up;
+       boneorg = skel_get_boneabs(self.skeletonindex, bonenum);
+       boneforward = v_forward;
+       boneright = v_right;
+       boneup = v_up;
+       parentorg = skel_get_boneabs(self.skeletonindex, skel_get_boneparent(self.skeletonindex, bonenum));
+       parentforward = v_forward;
+       parentright = v_right;
+       parentup = v_up;
+       // get the vector from the eyeball to the target
+       u = modeleyetarget - boneorg;
+       // now transform it inversely by the parent matrix to produce new rel vectors
+       v_x = u * parentforward;
+       v_y = u * parentright;
+       v_z = u * parentup;
+       ang = vectoangles2(v, relup);
+       ang_x = 0 - ang_x;
+       makevectors(ang);
+       // set the relative bone matrix
+       skel_set_bone(self.skeletonindex, bonenum, relorg);
+       // restore caller's v_ vectors
+       v_forward = oldforward;
+       v_right = oldright;
+       v_up = oldup;
+};
+// delete skeleton when we're done with it
+// note: skeleton remains valid until next frame when it is really deleted
+void() example_skel_player_delete =
+{
+       skel_delete(self.skeletonindex);
+       self.skeletonindex = 0;
+};
+//
+// END OF EXAMPLES FOR FTE_CSQC_SKELETONOBJECTS
+//
+
+//KRIMZON_SV_PARSECLIENTCOMMAND
+//idea: KrimZon
+//darkplaces implementation: KrimZon, LordHavoc
+//engine-called QC prototypes:
+//void(string s) SV_ParseClientCommand;
+//builtin definitions:
+void(entity e, string s) clientcommand = #440;
+float(string s) tokenize = #441;
+string(float n) argv = #442;
+//description:
+//provides QC the ability to completely control server interpretation of client commands ("say" and "color" for example, clientcommand is necessary for this and substring (FRIK_FILE) is useful) as well as adding new commands (tokenize, argv, and stof (FRIK_FILE) are useful for this)), whenever a clc_stringcmd is received the QC function is called, and it is up to the QC to decide what (if anything) to do with it
+
+//NEH_CMD_PLAY2
+//idea: Nehahra
+//darkplaces implementation: LordHavoc
+//description:
+//shows that the engine supports the "play2" console command (plays a sound without spatialization).
+
+//NEH_RESTOREGAME
+//idea: Nehahra
+//darkplaces implementation: LordHavoc
+//engine-called QC prototypes:
+//void() RestoreGame;
+//description:
+//when a savegame is loaded, this function is called
+
+//NEXUIZ_PLAYERMODEL
+//idea: Nexuiz
+//darkplaces implementation: Black
+//console commands:
+//playermodel <name> - FIXME: EXAMPLE NEEDED
+//playerskin <name> - FIXME: EXAMPLE NEEDED
+//field definitions:
+.string playermodel; // name of player model sent by client
+.string playerskin; // name of player skin sent by client
+//description:
+//these client properties are used by Nexuiz.
+
+//NXQ_GFX_LETTERBOX
+//idea: nxQuake
+//darkplaces implementation: LordHavoc
+//description:
+//shows that the engine supports the "r_letterbox" console variable, set to values in the range 0-100 this restricts the view vertically (and turns off sbar and crosshair), value is a 0-100 percentage of how much to constrict the view, <=0 = normal view height, 25 = 75% of normal view height, 50 = 50%, 75 = 25%, >=100 = no view
+
+//PRYDON_CLIENTCURSOR
+//idea: FrikaC
+//darkplaces implementation: LordHavoc
+//effects bit:
+float EF_SELECTABLE = 16384; // allows cursor to highlight entity (brighten)
+//field definitions:
+.float cursor_active; // true if cl_prydoncursor mode is on
+.vector cursor_screen; // screen position of cursor as -1 to +1 in _x and _y (_z unused)
+.vector cursor_trace_start; // position of camera
+.vector cursor_trace_endpos; // position of cursor in world (as traced from camera)
+.entity cursor_trace_ent; // entity the cursor is pointing at (server forces this to world if the entity is currently free at time of receipt)
+//cvar definitions:
+//cl_prydoncursor (0/1+, default 0, 1 and above use cursors named gfx/prydoncursor%03i.lmp - or .tga and such if DP_GFX_EXTERNALTEXTURES is implemented)
+//description:
+//shows that the engine supports the cl_prydoncursor cvar, this puts a clientside mouse pointer on the screen and feeds input to the server for the QuakeC to use as it sees fit.
+//the mouse pointer triggers button4 if cursor is at left edge of screen, button5 if at right edge of screen, button6 if at top edge of screen, button7 if at bottom edge of screen.
+//the clientside trace skips transparent entities (except those marked EF_SELECTABLE).
+//the selected entity highlights only if EF_SELECTABLE is set, a typical selection method would be doubling the brightness of the entity by some means (such as colormod[] *= 2).
+//intended to be used by Prydon Gate.
+
+//TENEBRAE_GFX_DLIGHTS
+//idea: Tenebrae
+//darkplaces implementation: LordHavoc
+//fields:
+.float light_lev; // radius (does not affect brightness), typical value 350
+.vector color; // color (does not affect radius), typical value '1 1 1' (bright white), can be up to '255 255 255' (nuclear blast)
+.float style; // light style (like normal light entities, flickering torches or switchable, etc)
+.float pflags; // flags (see PFLAGS_ constants)
+.vector angles; // orientation of the light
+.float skin; // cubemap filter number, can be 1-255 (0 is assumed to be none, and tenebrae only allows 16-255), this selects a projective light filter, a value of 1 loads cubemaps/1posx.tga and cubemaps/1negx.tga and posy, negy, posz, and negz, similar to skybox but some sides need to be rotated or flipped
+//constants:
+float PFLAGS_NOSHADOW = 1; // light does not cast shadows
+float PFLAGS_CORONA = 2; // light has a corona flare
+float PFLAGS_FULLDYNAMIC = 128; // light enable (without this set no light is produced!)
+//description:
+//more powerful dynamic light settings
+//warning: it is best not to use cubemaps on a light entity that has a model, as using a skin number that a model does not have will cause issues in glquake, and produce warnings in darkplaces (use developer 1 to see them)
+//changes compared to tenebrae (because they're too 'leet' for standards):
+//note: networking should send entities with PFLAGS_FULLDYNAMIC set even if they have no model (lights in general do not have a model, nor should they)
+//EF_FULLDYNAMIC effects flag replaced by PFLAGS_FULLDYNAMIC flag (EF_FULLDYNAMIC conflicts with EF_NODRAW)
+
+//TW_SV_STEPCONTROL
+//idea: Transfusion
+//darkplaces implementation: LordHavoc
+//cvars:
+//sv_jumpstep (0/1, default 1)
+//sv_stepheight (default 18)
+//description:
+//sv_jumpstep allows stepping up onto stairs while airborn, sv_stepheight controls how high a single step can be.
+
+//FTE_QC_CHECKPVS
+//idea: Urre
+//darkplaces implementation: divVerent
+//builtin definitions:
+float checkpvs(vector viewpos, entity viewee) = #240;
+//description:
+//returns true if viewee can be seen from viewpos according to PVS data
+
+//FTE_STRINGS
+//idea: many
+//darkplaces implementation: KrimZon
+//builtin definitions:
+float(string str, string sub, float startpos) strstrofs = #221; // returns the offset into a string of the matching text, or -1 if not found, case sensitive
+float(string str, float ofs) str2chr = #222; // returns the character at the specified offset as an integer, or 0 if an invalid index, or byte value - 256 if the engine supports UTF8 and the byte is part of an extended character
+string(float c, ...) chr2str = #223; // returns a string representing the character given, if the engine supports UTF8 this may be a multi-byte sequence (length may be more than 1) for characters over 127.
+string(float ccase, float calpha, float cnum, string s, ...) strconv = #224; // reformat a string with special color characters in the font, DO NOT USE THIS ON UTF8 ENGINES (if you are lucky they will emit ^4 and such color codes instead), the parameter values are 0=same/1=lower/2=upper for ccase, 0=same/1=white/2=red/5=alternate/6=alternate-alternate for redalpha, 0=same/1=white/2=red/3=redspecial/4=whitespecial/5=alternate/6=alternate-alternate for rednum.
+string(float chars, string s, ...) strpad = #225; // pad string with spaces to a specified length, < 0 = left padding, > 0 = right padding
+string(string info, string key, string value, ...) infoadd = #226; // sets or adds a key/value pair to an infostring - note: forbidden characters are \ and "
+string(string info, string key) infoget = #227; // gets a key/value pair in an infostring, returns value or null if not found
+float(string s1, string s2) strcmp = #228; // compare two strings
+float(string s1, string s2, float len) strncmp = #228; // compare two strings up to the specified number of characters, if their length differs and is within the specified limit the result will be negative, otherwise it is the difference in value of their first non-matching character.
+float(string s1, string s2) strcasecmp = #229; // compare two strings with case-insensitive matching, characters a-z are considered equivalent to the matching A-Z character, no other differences, and this does not consider special characters equal even if they look similar
+float(string s1, string s2, float len) strncasecmp = #230; // same as strcasecmp but with a length limit, see strncmp
+//string(string s, float start, float length) substring = #116; // see note below
+//description:
+//various string manipulation functions
+//note: substring also exists in FRIK_FILE but this extension adds negative start and length as valid cases (see note above), substring is consistent with the php 5.2.0 substr function (not 5.2.3 behavior)
+//substring returns a section of a string as a tempstring, if given negative
+// start the start is measured back from the end of the string, if given a
+// negative length the length is the offset back from the end of the string to
+// stop at, rather than being relative to start, if start is negative and
+// larger than length it is treated as 0.
+// examples of substring:
+// substring("blah", -3, 3) returns "lah"
+// substring("blah", 3, 3) returns "h"
+// substring("blah", -10, 3) returns "bla"
+// substring("blah", -10, -3) returns "b"
+
+//DP_CON_BESTWEAPON
+//idea: many
+//darkplaces implementation: divVerent
+//description:
+//allows QC to register weapon properties for use by the bestweapon command, for mods that change required ammo count or type for the weapons
+//it is done using console commands sent via stuffcmd:
+//  register_bestweapon quake
+//  register_bestweapon clear
+//  register_bestweapon <shortname> <impulse> <itemcode> <activeweaponcode> <ammostat> <ammomin>
+//for example, this is what Quake uses:
+//  register_bestweapon 1 1 4096 4096 6 0 // STAT_SHELLS is 6
+//  register_bestweapon 2 2    1    1 6 1
+//  register_bestweapon 3 3    2    2 6 1
+//  register_bestweapon 4 4    4    4 7 1 // STAT_NAILS is 7
+//  register_bestweapon 5 5    8    8 7 1
+//  register_bestweapon 6 6   16   16 8 1 // STAT_ROCKETS is 8
+//  register_bestweapon 7 7   32   32 8 1
+//  register_bestweapon 8 8   64   64 9 1 // STAT_CELLS is 9
+//after each map client initialization, this is reset back to Quake settings. So you should send these data in ClientConnect.
+//also, this extension introduces a new "cycleweapon" command to the user.
+
+//DP_QC_STRINGBUFFERS
+//idea: ??
+//darkplaces implementation: LordHavoc
+//functions to manage string buffer objects - that is, arbitrary length string arrays that are handled by the engine
+float() buf_create = #460;
+void(float bufhandle) buf_del = #461;
+float(float bufhandle) buf_getsize = #462;
+void(float bufhandle_from, float bufhandle_to) buf_copy = #463;
+void(float bufhandle, float sortpower, float backward) buf_sort = #464;
+string(float bufhandle, string glue) buf_implode = #465;
+string(float bufhandle, float string_index) bufstr_get = #466;
+void(float bufhandle, float string_index, string str) bufstr_set = #467;
+float(float bufhandle, string str, float order) bufstr_add = #468;
+void(float bufhandle, float string_index) bufstr_free = #469;
+
+//DP_QC_STRINGBUFFERS_CVARLIST
+//idea: divVerent
+//darkplaces implementation: divVerent
+//functions to list cvars and store their names into a stringbuffer
+//cvars that start with pattern but not with antipattern will be stored into the buffer
+void(float bufhandle, string pattern, string antipattern) buf_cvarlist = #517;
+
+//DP_QC_STRINGBUFFERS_EXT_WIP
+//idea: VorteX
+//darkplaces implementation: VorteX
+//constant definitions:
+const float MATCH_AUTO = 0;
+const float MATCH_WHOLE = 1;
+const float MATCH_LEFT = 2;
+const float MATCH_RIGHT = 3;
+const float MATCH_MIDDLE = 4;
+const float MATCH_PATTERN = 5;
+//builtin definitions:
+float(string filename, float bufhandle) buf_loadfile = #535; // append each line of file as new buffer string, return 1 if succesful
+float(float filehandle, float bufhandle, float startpos, float numstrings) buf_writefile = #536; // writes buffer strings as lines, returns 1 if succesful
+float(float bufhandle, string match, float matchrule, float startpos, float step) bufstr_find = #537; // returns string index
+float(string s, string pattern, float matchrule) matchpattern = #538; // returns 0/1
+float(string s, string pattern, float matchrule, float pos) matchpatternofs = #538;
+//description:
+//provides a set of functions to manipulate with string buffers
+//pattern wildcards: * - any character (or no characters), ? - any 1 character
+//Warning: This extension is work-in-progress, it may be changed/revamped/removed at any time, dont use it if you dont want any trouble
+//wip note: UTF8 is not supported yet
+
+//DP_QC_STRREPLACE
+//idea: Sajt
+//darkplaces implementation: Sajt
+//builtin definitions:
+string(string search, string replace, string subject) strreplace = #484;
+string(string search, string replace, string subject) strireplace = #485;
+//description:
+//strreplace replaces all occurrences of 'search' with 'replace' in the string 'subject', and returns the result as a tempstring.
+//strireplace does the same but uses case-insensitive matching of the 'search' term
+
+//DP_SV_SHUTDOWN
+//idea: divVerent
+//darkplaces implementation: divVerent
+//A function that gets called just before progs exit. To save persistent data from.
+//It is not called on a crash or error.
+//void SV_Shutdown();
+
+//EXT_CSQC
+// #232 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
+void(float index, float type, ...) addstat = #232;
+
+//ZQ_PAUSE
+//idea: ZQuake
+//darkplaces implementation: GreEn`mArine
+//builtin definitions:
+void(float pause) setpause = #531;
+//function definitions:
+//void(float elapsedtime) SV_PausedTic;
+//description:
+//during pause the world is not updated (time does not advance), SV_PausedTic is the only function you can be sure will be called at regular intervals during the pause, elapsedtime is the current system time in seconds since the pause started (not affected by slowmo or anything else).
+//
+//calling setpause(0) will end a pause immediately.
+//
+//Note: it is worth considering that network-related functions may be called during the pause (including customizeentityforclient for example), and it is also important to consider the continued use of the KRIMZON_SV_PARSECLIENTCOMMAND extension while paused (chatting players, etc), players may also join/leave during the pause.  In other words, the only things that are not called are think and other time-related functions.
+
+//DP_COVERAGE
+//idea: divVerent
+//darkplaces implementation: divVerent
+//function definitions:
+void coverage() = #642;  // Reports a coverage event. The engine counts for each of the calls to this builtin whether it has been called.
+
+
+// EXPERIMENTAL (not finalized) EXTENSIONS:
+
+//DP_CRYPTO
+//idea: divVerent
+//darkplaces implementation: divVerent
+//field definitions: (SVQC)
+.string crypto_keyfp; // fingerprint of CA key the player used to authenticate
+.string crypto_mykeyfp; // fingerprint of CA key the server used to authenticate to the player
+.string crypto_idfp; // fingerprint of ID used by the player entity, or string_null if not identified
+.float crypto_idfp_signed; // set if the player's ID has been signed
+.string crypto_encryptmethod; // the string "AES128" if encrypting, and string_null if plaintext
+.string crypto_signmethod; // the string "HMAC-SHA256" if signing, and string_null if plaintext
+// there is no field crypto_myidfp, as that info contains no additional information the QC may have a use for
+//builtin definitions: (SVQC)
+float(string url, float id, string content_type, string delim, float buf, float keyid) crypto_uri_postbuf = #513;
+//description:
+//use -1 as buffer handle to justs end delim as postdata
diff --git a/qcsrc/dpdefs/upstream/keycodes.qc b/qcsrc/dpdefs/upstream/keycodes.qc
new file mode 100644 (file)
index 0000000..e3d98ab
--- /dev/null
@@ -0,0 +1,146 @@
+///////////////////////////
+// key constants
+
+//
+// these are the key numbers that should be passed to Key_Event
+//
+float K_TAB                    =       9;
+float K_ENTER          =       13;
+float K_ESCAPE         =       27;
+float K_SPACE          =       32;
+
+// normal keys should be passed as lowercased ascii
+
+float K_BACKSPACE      =       127;
+float K_UPARROW                =       128;
+float K_DOWNARROW      =       129;
+float K_LEFTARROW      =       130;
+float K_RIGHTARROW     =       131;
+
+float K_ALT            =       132;
+float K_CTRL   =       133;
+float K_SHIFT  =       134;
+
+float K_F1             =       135;
+float K_F2             =       136;
+float K_F3             =       137;
+float K_F4             =       138;
+float K_F5             =       139;
+float K_F6             =       140;
+float K_F7             =       141;
+float K_F8             =       142;
+float K_F9             =       143;
+float K_F10            =       144;
+float K_F11            =       145;
+float K_F12            =       146;
+
+float K_INS            =       147;
+float K_DEL            =       148;
+float K_PGDN   =       149;
+float K_PGUP   =       150;
+float K_HOME   =       151;
+float K_END            =       152;
+
+float K_NUMLOCK                = 154;
+float K_CAPSLOCK       = 155;
+float K_SCROLLOCK      = 156;
+
+float K_KP_0   =       157;
+float K_KP_INS =       157; // same as K_KP_0
+float K_KP_1   =       158;
+float K_KP_END =       158; // same as K_KP_1
+float K_KP_2   =       159;
+float K_KP_DOWNARROW = 159; // same as K_KP_2
+float K_KP_3   =       160;
+float K_KP_PGDN = 160; // same as K_KP_3
+float K_KP_4   =       161;
+float K_KP_LEFTARROW = 161; // same as K_KP_4
+float K_KP_5   =       162;
+float K_KP_6   =       163;
+float K_KP_RIGHTARROW = 163; // same as K_KP_6
+float K_KP_7   =       164;
+float K_KP_HOME = 164; // same as K_KP_7
+float K_KP_8   =       165;
+float K_KP_UPARROW = 165; // same as K_KP_8
+float K_KP_9   = 166;
+float K_KP_PGUP = 166; // same as K_KP_9
+float K_KP_PERIOD = 167;
+float K_KP_DEL = 167; // same as K_KP_PERIOD
+float K_KP_DIVIDE = 168;
+float K_KP_SLASH = 168; // same as K_KP_DIVIDE
+float K_KP_MULTIPLY = 169;
+float K_KP_MINUS       = 170;
+float K_KP_PLUS                = 171;
+float K_KP_ENTER       = 172;
+float K_KP_EQUALS      = 173;
+
+// mouse buttons generate virtual keys
+float K_PAUSE  =       153;
+
+//
+// joystick buttons
+//
+float K_JOY1 = 768;
+float K_JOY2 = 769;
+float K_JOY3 = 770;
+float K_JOY4 = 771;
+
+//
+//
+// aux keys are for multi-buttoned joysticks to generate so they can use
+// the normal binding process
+//
+float K_AUX1   =       772;
+float K_AUX2   =       773;
+float K_AUX3   =       774;
+float K_AUX4   =       775;
+float K_AUX5   =       776;
+float K_AUX6   =       777;
+float K_AUX7   =       778;
+float K_AUX8   =       779;
+float K_AUX9   =       780;
+float K_AUX10  =       781;
+float K_AUX11  =       782;
+float K_AUX12  =       783;
+float K_AUX13  =       784;
+float K_AUX14  =       785;
+float K_AUX15  =       786;
+float K_AUX16  =       787;
+float K_AUX17  =       788;
+float K_AUX18  =       789;
+float K_AUX19  =       790;
+float K_AUX20  =       791;
+float K_AUX21  =       792;
+float K_AUX22  =       793;
+float K_AUX23  =       794;
+float K_AUX24  =       795;
+float K_AUX25  =       796;
+float K_AUX26  =       797;
+float K_AUX27  =       798;
+float K_AUX28  =       799;
+float K_AUX29  =       800;
+float K_AUX30  =       801;
+float K_AUX31  =       802;
+float K_AUX32  =       803;
+
+//
+// mouse buttons generate virtual keys
+//
+float K_MOUSE1         =       512;
+float K_MOUSE2         =       513;
+float K_MOUSE3         =       514;
+float K_MWHEELUP       =       515;
+float K_MWHEELDOWN     =       516;
+float K_MOUSE4         =       517;
+float K_MOUSE5         =       518;
+float K_MOUSE6         =       519;
+float K_MOUSE7         =       520;
+float K_MOUSE8         =       521;
+float K_MOUSE9         =       522;
+float K_MOUSE10                =       523;
+float K_MOUSE11                =       524;
+float K_MOUSE12                =       525;
+float K_MOUSE13                =       526;
+float K_MOUSE14                =       527;
+float K_MOUSE15                =       528;
+float K_MOUSE16                =       529;
diff --git a/qcsrc/dpdefs/upstream/menudefs.qc b/qcsrc/dpdefs/upstream/menudefs.qc
new file mode 100644 (file)
index 0000000..8caab4a
--- /dev/null
@@ -0,0 +1,584 @@
+//////////////////////////////////////////////////////////
+// sys globals
+
+entity self;
+
+/////////////////////////////////////////////////////////
+void           end_sys_globals;
+/////////////////////////////////////////////////////////
+// sys fields
+
+/////////////////////////////////////////////////////////
+void           end_sys_fields;
+/////////////////////////////////////////////////////////
+// sys functions
+
+void() m_init;
+void(float keynr, float ascii) m_keydown;
+void(float width, float height) m_draw;
+void(float mode) m_toggle;
+void() m_shutdown;
+// optional: float(float) m_gethostcachecategory;
+
+/////////////////////////////////////////////////////////
+// sys constants
+///////////////////////////
+// key dest constants
+
+float KEY_UNKNOWN      =       -1;
+float KEY_GAME                 =       0;
+float KEY_MENU         =       2;
+float KEY_MENU_GRABBED =       3;
+
+///////////////////////////
+// file constants
+
+float FILE_READ = 0;
+float FILE_APPEND = 1;
+float FILE_WRITE = 2;
+
+///////////////////////////
+// logical constants (just for completeness)
+
+float TRUE     = 1;
+float FALSE = 0;
+
+///////////////////////////
+// boolean constants
+
+float true = 1;
+float false = 0;
+
+///////////////////////////
+// msg constants
+
+float MSG_BROADCAST            = 0;            // unreliable to all
+float MSG_ONE                  = 1;            // reliable to one (msg_entity)
+float MSG_ALL                  = 2;            // reliable to all
+float MSG_INIT                 = 3;            // write to the init string
+
+/////////////////////////////
+// mouse target constants
+
+float MT_MENU = 1;
+float MT_CLIENT = 2;
+
+/////////////////////////
+// client state constants
+
+float CS_DEDICATED             = 0;
+float CS_DISCONNECTED  = 1;
+float CS_CONNECTED             = 2;
+
+///////////////////////////
+// blend flags
+
+float DRAWFLAG_NORMAL          = 0;
+float DRAWFLAG_ADDITIVE        = 1;
+float DRAWFLAG_MODULATE        = 2;
+float DRAWFLAG_2XMODULATE   = 3;
+
+///////////////////////////
+// null entity (actually it is the same like the world entity)
+
+entity null_entity;
+
+///////////////////////////
+// error constants
+
+// file handling
+float ERR_CANNOTOPEN                   = -1; // fopen
+float ERR_NOTENOUGHFILEHANDLES         = -2; // fopen
+float ERR_INVALIDMODE                  = -3; // fopen
+float ERR_BADFILENAME                  = -4; // fopen
+
+// drawing functions
+
+float ERR_NULLSTRING                   = -1;
+float ERR_BADDRAWFLAG                  = -2;
+float ERR_BADSCALE                             = -3;
+float ERR_BADSIZE                              = -3; // same as ERR_BADSCALE
+float ERR_NOTCACHED                            = -4;
+
+// server list stuff
+float SLIST_HOSTCACHEVIEWCOUNT  = 0;
+float SLIST_HOSTCACHETOTALCOUNT = 1;
+float SLIST_MASTERQUERYCOUNT   = 2;
+float SLIST_MASTERREPLYCOUNT   = 3;
+float SLIST_SERVERQUERYCOUNT   = 4;
+float SLIST_SERVERREPLYCOUNT   = 5;
+float SLIST_SORTFIELD          = 6;
+float SLIST_SORTDESCENDING     = 7;
+float SLIST_LEGACY_LINE1       = 1024;
+float SLIST_LEGACY_LINE2       = 1025;
+float SLIST_TEST_CONTAINS      = 0;
+float SLIST_TEST_NOTCONTAIN    = 1;
+float SLIST_TEST_LESSEQUAL     = 2;
+float SLIST_TEST_LESS          = 3;
+float SLIST_TEST_EQUAL         = 4;
+float SLIST_TEST_GREATER       = 5;
+float SLIST_TEST_GREATEREQUAL  = 6;
+float SLIST_TEST_NOTEQUAL      = 7;
+float SLIST_TEST_STARTSWITH    = 8;
+float SLIST_TEST_NOTSTARTSWITH = 9;
+float SLIST_MASK_AND = 0;
+float SLIST_MASK_OR  = 512;
+
+// font stuff
+float FONT_DEFAULT     = 0;
+float FONT_CONSOLE     = 1;
+float FONT_SBAR        = 2;
+float FONT_NOTIFY      = 3;
+float FONT_CHAT        = 4;
+float FONT_CENTERPRINT = 5;
+float FONT_INFOBAR     = 6;
+float FONT_MENU        = 7;
+float FONT_USER        = 8; // add to this the index, like FONT_USER+3 = user3. At least 8 of them are supported.
+float drawfont;
+
+/* not supported at the moment
+///////////////////////////
+// os constants
+
+float OS_WINDOWS       = 0;
+float OS_LINUX         = 1;
+float OS_MAC           = 2;
+*/
+
+
+
+
+
+
+
+
+
+
+//////////////////////////////////////////////////
+// common cmd
+//////////////////////////////////////////////////
+// AK FIXME: Create perhaps a special builtin file for the common cmds
+
+void   checkextension(string ext)      = #1;
+
+// error cmds
+void   error(string err,...)           = #2;
+void   objerror(string err,...)        = #3;
+
+// print
+
+void   print(string text,...)                   = #4;
+void   bprint(string text,...)                  = #5;
+void   sprint(float clientnum, string text,...) = #6;
+void   centerprint(string text,...)             = #7;
+
+// vector stuff
+
+vector normalize(vector v)             = #8;
+float  vlen(vector v)                  = #9;
+float          vectoyaw(vector v)              = #10;
+vector         vectoangles(vector v)           = #11;
+
+float  random(void)  = #12;
+
+void   cmd(string command, ...) = #13;
+
+// cvar cmds
+
+float  cvar(string name)                       = #14;
+const string str_cvar(string name)             = #71;
+void   cvar_set(string name, string value)     = #15;
+
+void   dprint(string text,...) = #16;
+
+// conversion functions
+
+string ftos(float f)   = #17;
+float  fabs(float f)   = #18;
+string vtos(vector v)  = #19;
+string etos(entity e)  = #20;
+
+float  stof(string val,...)  = #21;
+
+entity spawn(void)             = #22;
+void   remove(entity e)        = #23;
+
+entity find(entity start, .string field, string match)         = #24;
+entity findfloat(entity start, .float field, float match)      = #25;
+entity findentity(entity start, .entity field, entity match)   = #25;
+
+entity findchainstring(.string field, string match)    = #26;
+entity findchainfloat(.float field, float match)       = #27;
+entity findchainentity(.entity field, entity match)    = #27;
+
+string precache_file(string file)      = #28;
+string precache_sound(string sample)   = #29;
+
+void   crash(void)     = #72;
+void   coredump(void)  = #30;
+void   stackdump(void) = #73;
+void   traceon(void)   = #31;
+void   traceoff(void)  = #32;
+
+void   eprint(entity e)        = #33;
+float  rint(float f)           = #34;
+float  floor(float f)          = #35;
+float  ceil(float f)           = #36;
+entity nextent(entity e)       = #37;
+float  sin(float f)            = #38;
+float  cos(float f)            = #39;
+float  sqrt(float f)           = #40;
+vector randomvec(void)         = #41;
+
+float  registercvar(string name, string value, float flags)  = #42; // returns 1 if success
+
+float  min(float f,...)  = #43;
+float  max(float f,...)  = #44;
+
+float  bound(float min,float value, float max)  = #45;
+float  pow(float a, float b)  = #46;
+
+void   copyentity(entity src, entity dst)  = #47;
+
+float  fopen(string filename, float mode)  = #48;
+void   fclose(float fhandle)  = #49;
+string fgets(float fhandle)  = #50;
+void   fputs(float fhandle, string s)  = #51;
+
+float  strlen(string s)  = #52;
+string strcat(string s1,string s2,...)  = #53;
+string substring(string s, float start, float length)  = #54;
+
+vector stov(string s)  = #55;
+
+string strzone(string s)  = #56;
+void   strunzone(string s) = #57;
+
+float  tokenize(string s)  = #58;
+string argv(float n)  = #59;
+
+float  isserver(void)  = #60;
+float  clientcount(void)  = #61;
+float  clientstate(void)  = #62;
+void   clientcommand(float client, string s)  = #63;
+void   changelevel(string map)  = #64;
+void   localsound(string sample)  = #65;
+vector getmousepos(void)       = #66;
+float  gettime(void)           = #67;
+void   loadfromdata(string data) = #68;
+void   loadfromfile(string file) = #69;
+
+float  mod(float val, float m) = #70;
+
+float  search_begin(string pattern, float caseinsensitive, float quiet) = #74;
+void   search_end(float handle) = #75;
+float  search_getsize(float handle) = #76;
+string search_getfilename(float handle, float num) = #77;
+
+string chr(float ascii) = #78;
+
+/////////////////////////////////////////////////
+// Write* Functions
+/////////////////////////////////////////////////
+void   WriteByte(float data, float dest, float desto)  = #401;
+void   WriteChar(float data, float dest, float desto)  = #402;
+void   WriteShort(float data, float dest, float desto) = #403;
+void   WriteLong(float data, float dest, float desto)  = #404;
+void   WriteAngle(float data, float dest, float desto) = #405;
+void   WriteCoord(float data, float dest, float desto) = #406;
+void   WriteString(string data, float dest, float desto)= #407;
+void   WriteEntity(entity data, float dest, float desto) = #408;
+
+//////////////////////////////////////////////////
+// Draw funtions
+//////////////////////////////////////////////////
+
+float  iscachedpic(string name)        = #451;
+string precache_pic(string name, ...)  = #452;
+void   freepic(string name)            = #453;
+
+float  drawcharacter(vector position, float character, vector scale, vector rgb, float alpha, float flag) = #454;
+
+float  drawstring(vector position, string text, vector scale, vector rgb, float alpha, float flag) = #455;
+
+float  drawcolorcodedstring(vector position, string text, vector scale, float alpha, float flag) = #467;
+
+vector drawcolorcodedstring2(vector position, string text, vector scale, vector rgb, float alpha, float flag) = #467;
+float  drawpic(vector position, string pic, vector size, vector rgb, float alpha, float flag) = #456;
+
+float  drawfill(vector position, vector size, vector rgb, float alpha, float flag) = #457;
+
+void   drawsetcliparea(float x, float y, float width, float height) = #458;
+
+void   drawresetcliparea(void) = #459;
+
+vector  drawgetimagesize(string pic) = #460;
+
+////////////////////////////////////////////////
+// Menu functions
+////////////////////////////////////////////////
+
+void   setkeydest(float dest)  = #601;
+float  getkeydest(void)        = #602;
+
+void   setmousetarget(float trg) = #603;
+float  getmousetarget(void)      = #604;
+
+float  isfunction(string function_name) = #607;
+void   callfunction(...) = #605;
+void   writetofile(float fhandle, entity ent) = #606;
+vector getresolution(float number) = #608;
+string keynumtostring(float keynum) = #609;
+
+float  gethostcachevalue(float type) = #611;
+string gethostcachestring(float type, float hostnr) = #612;
+
+//DP_CSQC_BINDMAPS
+//idea: daemon, motorsep
+//darkplaces implementation: divVerent
+//builtin definitions:
+string(float key, float bindmap) getkeybind_bindmap = #342;
+float(float key, string bind, float bindmap) setkeybind_bindmap = #630;
+vector(void) getbindmaps = #631;
+float(vector bm) setbindmaps = #632;
+string(string command, float bindmap) findkeysforcommand = #610;
+float(string key) stringtokeynum = #341;
+//<also allowed builtin number to match EXT_CSQC> string(float keynum) keynumtostring = #340;
+//description: key bind setting/getting including support for switchable
+//bindmaps.
+
+//DP_CRYPTO
+//idea: divVerent
+//darkplaces implementation: divVerent
+//field definitions: (MENUQC)
+string(string serveraddress) crypto_getkeyfp = #633; // retrieves the cached host key's CA fingerprint of a server given by IP address
+string(string serveraddress) crypto_getidfp = #634; // retrieves the cached host key fingerprint of a server given by IP address
+float(string serveraddress) crypto_getidstatus = #643; // retrieves the cached host key's key status. See below for CRYPTO_IDSTATUS_ defines.
+string(string serveraddress) crypto_getencryptlevel = #635; // 0 if never encrypting, 1 supported, 2 requested, 3 required, appended by list of allowed methods in order of preference ("AES128"), preceded by a space each
+string(float i) crypto_getmykeyfp = #636; // retrieves the CA key fingerprint of a given CA slot, or "" if slot is unused but more to come, or string_null if end of list
+string(float i) crypto_getmyidfp = #637; // retrieves the ID fingerprint of a given CA slot, or "" if slot is unused but more to come, or string_null if end of list
+float CRYPTO_IDSTATUS_OUTOFRANGE = -1;
+float CRYPTO_IDSTATUS_EMPTY = 0;
+float CRYPTO_IDSTATUS_UNSIGNED = 1;
+float CRYPTO_IDSTATUS_SIGNED = 2;
+float(float i) crypto_getmyidstatus = #641; // retrieves the ID's status of a given CA slot, or 0 if slot is unused but more to come, or -1 if end of list
+float(string url, float id, string content_type, string delim, float buf, float keyid) crypto_uri_postbuf = #513;
+//description:
+//use -1 as buffer handle to justs end delim as postdata
+
+//DP_GECKO_SUPPORT
+//idea: Res2k, BlackHC
+//darkplaces implementation: Res2k, BlackHC
+//constant definitions:
+float GECKO_BUTTON_DOWN         = 0;
+float GECKO_BUTTON_UP           = 1;
+// either use down and up or just press but not all of them!
+float GECKO_BUTTON_PRESS        = 2;
+// use this for mouse events if needed?
+float GECKO_BUTTON_DOUBLECLICK  = 3;
+//builtin definitions:
+float gecko_create( string name ) = #487;
+void gecko_destroy( string name ) = #488;
+void gecko_navigate( string name, string URI ) = #489;
+float gecko_keyevent( string name, float key, float eventtype ) = #490;
+void gecko_mousemove( string name, float x, float y ) = #491;
+void gecko_resize( string name, float w, float h ) = #492;
+vector gecko_get_texture_extent( string name ) = #493;
+//engine-called QC prototypes:
+//string(string name, string query) Qecko_Query;
+//description:
+//provides an interface to the offscreengecko library and allows for internet browsing in games
+
+//FTE_STRINGS
+//idea: many
+//darkplaces implementation: KrimZon
+//description:
+//various string manipulation functions
+float(string str, string sub, float startpos) strstrofs = #221;
+float(string str, float ofs) str2chr = #222;
+string(float c, ...) chr2str = #223;
+string(float ccase, float calpha, float cnum, string s, ...) strconv = #224;
+string(float chars, string s, ...) strpad = #225;
+string(string info, string key, string value, ...) infoadd = #226;
+string(string info, string key) infoget = #227;
+float(string s1, string s2) strcmp = #228;
+float(string s1, string s2, float len) strncmp = #228;
+float(string s1, string s2) strcasecmp = #229;
+float(string s1, string s2, float len) strncasecmp = #230;
+
+//DP_PRECACHE_PIC_FLAGS
+//idea: divVerent
+//darkplaces implementation: divVerent
+//constant definitions:
+float PRECACHE_PIC_FROMWAD = 1; // this one actually is part of EXT_CSQC
+float PRECACHE_PIC_NOTPERSISTENT = 2; // picture may get deallocated when unused
+float PRECACHE_PIC_MIPMAP = 8; // mipmap the texture for possibly better downscaling at memory expense
+//notes: these constants are given as optional second argument to precache_pic()
+
+//DP_QC_CRC16
+//idea: div0
+//darkplaces implementation: div0
+//Some hash function to build hash tables with. This has to be be the CRC-16-CCITT that is also required for the QuakeWorld download protocol.
+//When caseinsensitive is set, the CRC is calculated of the lower cased string.
+float(float caseinsensitive, string s, ...) crc16 = #494;
+
+//DP_QC_CVAR_TYPE
+float(string name) cvar_type = #495;
+float CVAR_TYPEFLAG_EXISTS = 1;
+float CVAR_TYPEFLAG_SAVED = 2;
+float CVAR_TYPEFLAG_PRIVATE = 4;
+float CVAR_TYPEFLAG_ENGINE = 8;
+float CVAR_TYPEFLAG_HASDESCRIPTION = 16;
+float CVAR_TYPEFLAG_READONLY = 32;
+
+//DP_QC_STRINGBUFFERS
+//idea: ??
+//darkplaces implementation: LordHavoc
+//functions to manage string buffer objects - that is, arbitrary length string arrays that are handled by the engine
+float() buf_create = #440;
+void(float bufhandle) buf_del = #441;
+float(float bufhandle) buf_getsize = #442;
+void(float bufhandle_from, float bufhandle_to) buf_copy = #443;
+void(float bufhandle, float sortpower, float backward) buf_sort = #444;
+string(float bufhandle, string glue) buf_implode = #445;
+string(float bufhandle, float string_index) bufstr_get = #446;
+void(float bufhandle, float string_index, string str) bufstr_set = #447;
+float(float bufhandle, string str, float order) bufstr_add = #448;
+void(float bufhandle, float string_index) bufstr_free = #449;
+void(float bufhandle, string pattern, string antipattern) buf_cvarlist = #517;
+
+//DP_QC_STRING_CASE_FUNCTIONS
+//idea: Dresk
+//darkplaces implementation: LordHavoc / Dresk
+//builtin definitions:
+string(string s) strtolower = #480; // returns the passed in string in pure lowercase form
+string(string s) strtoupper = #481; // returns the passed in string in pure uppercase form
+//description:
+//provides simple string uppercase and lowercase functions
+
+//DP_QC_CVAR_DESCRIPTION
+//idea: divVerent
+//DarkPlaces implementation: divVerent
+//builtin definitions:
+string(string name) cvar_description = #518;
+//description:
+//returns the description of a cvar
+
+//DP_QC_DIGEST
+//idea: motorsep, Spike
+//DarkPlaces implementation: divVerent
+//builtin definitions:
+string(string digest, string data, ...) digest_hex = #639;
+//description:
+//returns a given hex digest of given data
+//the returned digest is always encoded in hexadecimal
+//only the "MD4" digest is always supported!
+//if the given digest is not supported, string_null is returned
+//the digest string is matched case sensitively, use "MD4", not "md4"!
+
+//DP_QC_URI_ESCAPE
+//idea: div0
+//darkplaces implementation: div0
+//URI::Escape's functionality
+string(string in) uri_escape = #510;
+string(string in) uri_unescape = #511;
+
+//DP_QC_URI_GET
+//idea: divVerent
+//darkplaces implementation: divVerent
+//loads text from an URL into a string
+//returns 1 on success of initiation, 0 if there are too many concurrent
+//connections already or if the URL is invalid
+//the following callback will receive the data and MUST exist!
+//  void(float id, float status, string data) URI_Get_Callback;
+//status is either
+//  negative for an internal error,
+//  0 for success, or
+//  the HTTP response code on server error (e.g. 404)
+//if 1 is returned by uri_get, the callback will be called in the future
+float(string url, float id) uri_get = #513;
+//DP_QC_URI_POST
+//idea: divVerent
+//darkplaces implementation: divVerent
+//loads text from an URL into a string after POSTing via HTTP
+//works like uri_get, but uri_post sends data with Content-Type: content_type to the server
+//and uri_post sends the string buffer buf, joined using the delimiter delim
+float(string url, float id, string content_type, string data) uri_post = #513;
+float(string url, float id, string content_type, string delim, float buf) uri_postbuf = #513;
+
+//DP_QC_ENTITYDATA
+//idea: KrimZon
+//darkplaces implementation: KrimZon
+//builtin definitions:
+float() numentityfields = #496;
+string(float fieldnum) entityfieldname = #497;
+float(float fieldnum) entityfieldtype = #498;
+string(float fieldnum, entity ent) getentityfieldstring = #499;
+float(float fieldnum, entity ent, string s) putentityfieldstring = #500;
+//constants:
+//Returned by entityfieldtype
+float FIELD_STRING   = 1;
+float FIELD_FLOAT    = 2;
+float FIELD_VECTOR   = 3;
+float FIELD_ENTITY   = 4;
+float FIELD_FUNCTION = 6;
+//description:
+//Versatile functions intended for storing data from specific entities between level changes, but can be customized for some kind of partial savegame.
+//WARNING: .entity fields cannot be saved and restored between map loads as they will leave dangling pointers.
+//numentityfields returns the number of entity fields. NOT offsets. Vectors comprise 4 fields: v, v_x, v_y and v_z.
+//entityfieldname returns the name as a string, eg. "origin" or "classname" or whatever.
+//entityfieldtype returns a value that the constants represent, but the field may be of another type in more exotic progs.dat formats or compilers.
+//getentityfieldstring returns data as would be written to a savegame, eg... "0.05" (float), "0 0 1" (vector), or "Hello World!" (string). Function names can also be returned.
+//putentityfieldstring puts the data returned by getentityfieldstring back into the entity.
+
+//DP_COVERAGE
+//idea: divVerent
+//darkplaces implementation: divVerent
+//function definitions:
+void coverage() = #642;  // Reports a coverage event. The engine counts for each of the calls to this builtin whether it has been called.
+
+// assorted undocumented extensions
+string(string, float) netaddress_resolve = #625;
+string(string search, string replace, string subject) strreplace = #484;
+string(float uselocaltime, string format, ...) strftime = #478;
+float(string s) tokenize_console = #514;
+float(float i) argv_start_index = #515;
+float(float i) argv_end_index = #516;
+string(float, float) getgamedirinfo = #626;
+#define GETGAMEDIRINFO_NAME 0
+#define GETGAMEDIRINFO_DESCRIPTION 1
+float log(float f) = #532;
+string(string format, ...) sprintf = #627;
+string(string s) strdecolorize = #477;
+entity findflags(entity start, .float field, float match) = #87;
+entity findchainflags(.float field, float match) = #88;
+float(string s, string separator1, ...) tokenizebyseparator = #479;
+float  etof(entity ent) = #79;
+entity         ftoe(float num)  = #80;
+float   validstring(string str) = #81;
+float  altstr_count(string str) = #82;
+string  altstr_prepare(string str) = #83;
+string  altstr_get(string str, float num) = #84;
+string  altstr_set(string str, float num, string set) = #85;
+string         altstr_ins(string str, float num, string set) = #86;
+float  isdemo() = #349;
+float  drawsubpic(vector position, vector size, string pic, vector srcPosition, vector srcSize, vector rgb, float alpha, float flag) = #469;
+//vector       getresolution(float number, ...) = #608; // optional argument "isfullscreen"
+void   parseentitydata(entity ent, string data) = #613;
+void   resethostcachemasks(void) = #615;
+void   sethostcachemaskstring(float mask, float fld, string str, float op) = #616;
+void   sethostcachemasknumber(float mask, float fld, float num, float op) = #617;
+void   resorthostcache(void) = #618;
+float SLSF_DESCENDING = 1;
+float SLSF_FAVORITES = 2;
+float SLSF_CATEGORIES = 4;
+void   sethostcachesort(float fld, float slsf) = #619;
+void   refreshhostcache(...) = #620;  // optional boolean argument "clear_list"
+float  gethostcachenumber(float fld, float hostnr) = #621;
+float  gethostcacheindexforkey(string key) = #622;
+void   addwantedhostcachekey(string key) = #623;
+string getextresponse(void) = #624;
+const string cvar_string(string name) = #71;
+const string cvar_defstring(string name) = #89;
+float  stringwidth(string text, float handleColors, vector size) = #468;
diff --git a/qcsrc/dpdefs/upstream/progsdefs.qc b/qcsrc/dpdefs/upstream/progsdefs.qc
new file mode 100644 (file)
index 0000000..2ccd843
--- /dev/null
@@ -0,0 +1,507 @@
+/*
+==============================================================================
+
+                       SOURCE FOR GLOBALVARS_T C STRUCTURE
+                       MUST NOT BE MODIFIED, OR CRC ERRORS WILL APPEAR
+
+==============================================================================
+*/
+
+//
+// system globals
+//
+entity         self;
+entity         other;
+entity         world;
+float          time;
+float          frametime;
+
+float          force_retouch;          // force all entities to touch triggers
+                                                               // next frame.  this is needed because
+                                                               // non-moving things don't normally scan
+                                                               // for triggers, and when a trigger is
+                                                               // created (like a teleport trigger), it
+                                                               // needs to catch everything.
+                                                               // decremented each frame, so set to 2
+                                                               // to guarantee everything is touched
+string         mapname;
+
+float          deathmatch;
+float          coop;
+float          teamplay;
+
+float          serverflags;            // propagated from level to level, used to
+                                                               // keep track of completed episodes
+
+float          total_secrets;
+float          total_monsters;
+
+float          found_secrets;          // number of secrets found
+float          killed_monsters;        // number of monsters killed
+
+
+// spawnparms are used to encode information about clients across server
+// level changes
+float          parm1, parm2, parm3, parm4, parm5, parm6, parm7, parm8, parm9, parm10, parm11, parm12, parm13, parm14, parm15, parm16;
+
+//
+// global variables set by built in functions
+//
+vector         v_forward, v_up, v_right;       // set by makevectors()
+
+// set by traceline / tracebox
+float          trace_allsolid;
+float          trace_startsolid;
+float          trace_fraction;
+vector         trace_endpos;
+vector         trace_plane_normal;
+float          trace_plane_dist;
+entity         trace_ent;
+float          trace_inopen;
+float          trace_inwater;
+
+entity         msg_entity;                             // destination of single entity writes
+
+//
+// required prog functions
+//
+void()                 main;                                           // only for testing
+
+void()         StartFrame;
+
+void()                 PlayerPreThink;
+void()                 PlayerPostThink;
+
+void()         ClientKill;
+void()         ClientConnect;
+void()                 PutClientInServer;              // call after setting the parm1... parms
+void()         ClientDisconnect;
+
+void()         SetNewParms;                    // called when a client first connects to
+                                                                       // a server. sets parms so they can be
+                                                                       // saved off for restarts
+
+void()         SetChangeParms;                 // call to set parms for self so they can
+                                                                       // be saved for a level transition
+
+
+//================================================
+void           end_sys_globals;                // flag for structure dumping
+//================================================
+
+/*
+==============================================================================
+
+                       SOURCE FOR ENTVARS_T C STRUCTURE
+                       MUST NOT BE MODIFIED, OR CRC ERRORS WILL APPEAR
+
+==============================================================================
+*/
+
+//
+// system fields (*** = do not set in prog code, maintained by C code)
+//
+.float         modelindex;             // *** model index in the precached list
+.vector                absmin, absmax; // *** origin + mins / maxs
+
+.float         ltime;                  // local time for entity
+.float         movetype;
+.float         solid;
+
+.vector                origin;                 // ***
+.vector                oldorigin;              // ***
+.vector                velocity;
+.vector                angles;
+.vector                avelocity;
+
+.vector                punchangle;             // temp angle adjust from damage or recoil
+
+.string                classname;              // spawn function
+.string                model;
+.float         frame;
+.float         skin;
+.float         effects;
+
+.vector                mins, maxs;             // bounding box extents reletive to origin
+.vector                size;                   // maxs - mins
+
+.void()                touch;
+.void()                use;
+.void()                think;
+.void()                blocked;                // for doors or plats, called when can't push other
+
+.float         nextthink;
+.entity                groundentity;
+
+// stats
+.float         health;
+.float         frags;
+.float         weapon;                 // one of the IT_SHOTGUN, etc flags
+.string                weaponmodel;
+.float         weaponframe;
+.float         currentammo;
+.float         ammo_shells, ammo_nails, ammo_rockets, ammo_cells;
+
+.float         items;                  // bit flags
+
+.float         takedamage;
+.entity                chain;
+.float         deadflag;
+
+.vector                view_ofs;                       // add to origin to get eye point
+
+
+.float         button0;                // fire
+.float         button1;                // use
+.float         button2;                // jump
+
+.float         impulse;                // weapon changes
+
+.float         fixangle;
+.vector                v_angle;                // view / targeting angle for players
+.float         idealpitch;             // calculated pitch angle for lookup up slopes
+
+
+.string                netname;
+
+.entity        enemy;
+
+.float         flags;
+
+.float         colormap;
+.float         team;
+
+.float         max_health;             // players maximum health is stored here
+
+.float         teleport_time;  // don't back up
+
+.float         armortype;              // save this fraction of incoming damage
+.float         armorvalue;
+
+.float         waterlevel;             // 0 = not in, 1 = feet, 2 = wast, 3 = eyes
+.float         watertype;              // a contents value
+
+.float         ideal_yaw;
+.float         yaw_speed;
+
+.entity                aiment;
+
+.entity        goalentity;             // a movetarget or an enemy
+
+.float         spawnflags;
+
+.string                target;
+.string                targetname;
+
+// damage is accumulated through a frame. and sent as one single
+// message, so the super shotgun doesn't generate huge messages
+.float         dmg_take;
+.float         dmg_save;
+.entity                dmg_inflictor;
+
+.entity                owner;          // who launched a missile
+.vector                movedir;        // mostly for doors, but also used for waterjump
+
+.string                message;                // trigger messages
+
+.float         sounds;         // either a cd track number or sound number
+
+.string                noise, noise1, noise2, noise3;  // contains names of wavs to play
+
+//================================================
+void           end_sys_fields;                 // flag for structure dumping
+//================================================
+
+/*
+==============================================================================
+
+                               CONSTANT DEFINITIONS
+
+==============================================================================
+*/
+
+
+//
+// constants
+//
+
+float  FALSE                                   = 0;
+float  TRUE                                    = 1;
+
+// edict.flags
+float  FL_FLY                                  = 1;
+float  FL_SWIM                                 = 2;
+float  FL_CLIENT                               = 8;    // set for all client edicts
+float  FL_INWATER                              = 16;   // for enter / leave water splash
+float  FL_MONSTER                              = 32;
+float  FL_GODMODE                              = 64;   // player cheat
+float  FL_NOTARGET                             = 128;  // player cheat
+float  FL_ITEM                                 = 256;  // extra wide size for bonus items
+float  FL_ONGROUND                             = 512;  // standing on something
+float  FL_PARTIALGROUND                = 1024; // not all corners are valid
+float  FL_WATERJUMP                    = 2048; // player jumping out of water
+float  FL_JUMPRELEASED                 = 4096; // for jump debouncing
+
+// edict.movetype values
+float  MOVETYPE_NONE                   = 0;    // never moves
+//float        MOVETYPE_ANGLENOCLIP    = 1;
+//float        MOVETYPE_ANGLECLIP              = 2;
+float  MOVETYPE_WALK                   = 3;    // players only
+float  MOVETYPE_STEP                   = 4;    // discrete, not real time unless fall
+float  MOVETYPE_FLY                    = 5;
+float  MOVETYPE_TOSS                   = 6;    // gravity
+float  MOVETYPE_PUSH                   = 7;    // no clip to world, push and crush
+float  MOVETYPE_NOCLIP                 = 8;
+float  MOVETYPE_FLYMISSILE             = 9;    // fly with extra size against monsters
+float  MOVETYPE_BOUNCE                 = 10;
+float  MOVETYPE_BOUNCEMISSILE  = 11;   // bounce with extra size
+
+// edict.solid values
+float  SOLID_NOT                               = 0;    // no interaction with other objects
+float  SOLID_TRIGGER                   = 1;    // touch on edge, but not blocking
+float  SOLID_BBOX                              = 2;    // touch on edge, block
+float  SOLID_SLIDEBOX                  = 3;    // touch on edge, but not an onground
+float  SOLID_BSP                               = 4;    // bsp clip, touch on edge, block
+
+// range values
+float  RANGE_MELEE                             = 0;
+float  RANGE_NEAR                              = 1;
+float  RANGE_MID                               = 2;
+float  RANGE_FAR                               = 3;
+
+// deadflag values
+
+float  DEAD_NO                                 = 0;
+float  DEAD_DYING                              = 1;
+float  DEAD_DEAD                               = 2;
+float  DEAD_RESPAWNABLE                = 3;
+float  DEAD_RESPAWNING                 = 4; // dead, waiting for buttons to be released
+
+// takedamage values
+
+float  DAMAGE_NO                               = 0;
+float  DAMAGE_YES                              = 1;
+float  DAMAGE_AIM                              = 2;
+
+// items
+float  IT_AXE                                  = 4096;
+float  IT_SHOTGUN                              = 1;
+float  IT_SUPER_SHOTGUN                = 2;
+float  IT_NAILGUN                              = 4;
+float  IT_SUPER_NAILGUN                = 8;
+float  IT_GRENADE_LAUNCHER             = 16;
+float  IT_ROCKET_LAUNCHER              = 32;
+float  IT_LIGHTNING                    = 64;
+float  IT_EXTRA_WEAPON                 = 128;
+
+float  IT_SHELLS                               = 256;
+float  IT_NAILS                                = 512;
+float  IT_ROCKETS                              = 1024;
+float  IT_CELLS                                = 2048;
+
+float  IT_ARMOR1                               = 8192;
+float  IT_ARMOR2                               = 16384;
+float  IT_ARMOR3                               = 32768;
+float  IT_SUPERHEALTH                  = 65536;
+
+float  IT_KEY1                                 = 131072;
+float  IT_KEY2                                 = 262144;
+
+float  IT_INVISIBILITY                 = 524288;
+float  IT_INVULNERABILITY              = 1048576;
+float  IT_SUIT                                 = 2097152;
+float  IT_QUAD                                 = 4194304;
+
+// point content values
+
+float  CONTENT_EMPTY                   = -1;
+float  CONTENT_SOLID                   = -2;
+float  CONTENT_WATER                   = -3;
+float  CONTENT_SLIME                   = -4;
+float  CONTENT_LAVA                    = -5;
+float  CONTENT_SKY                             = -6;
+
+float  STATE_TOP               = 0;
+float  STATE_BOTTOM    = 1;
+float  STATE_UP                = 2;
+float  STATE_DOWN              = 3;
+
+vector VEC_ORIGIN = '0 0 0';
+vector VEC_HULL_MIN = '-16 -16 -24';
+vector VEC_HULL_MAX = '16 16 32';
+
+vector VEC_HULL2_MIN = '-32 -32 -24';
+vector VEC_HULL2_MAX = '32 32 64';
+
+// protocol bytes
+float  SVC_TEMPENTITY          = 23;
+float  SVC_KILLEDMONSTER       = 27;
+float  SVC_FOUNDSECRET         = 28;
+float  SVC_INTERMISSION        = 30;
+float  SVC_FINALE                      = 31;
+float  SVC_CDTRACK                     = 32;
+float  SVC_SELLSCREEN          = 33;
+
+
+float  TE_SPIKE                = 0;
+float  TE_SUPERSPIKE   = 1;
+float  TE_GUNSHOT              = 2;
+float  TE_EXPLOSION    = 3;
+float  TE_TAREXPLOSION = 4;
+float  TE_LIGHTNING1   = 5;
+float  TE_LIGHTNING2   = 6;
+float  TE_WIZSPIKE             = 7;
+float  TE_KNIGHTSPIKE  = 8;
+float  TE_LIGHTNING3   = 9;
+float  TE_LAVASPLASH   = 10;
+float  TE_TELEPORT             = 11;
+
+// sound channels
+// channel 0 never willingly overrides
+// other channels (1-7) allways override a playing sound on that channel
+float  CHAN_AUTO               = 0;
+float  CHAN_WEAPON             = 1;
+float  CHAN_VOICE              = 2;
+float  CHAN_ITEM               = 3;
+float  CHAN_BODY               = 4;
+
+float  ATTN_NONE               = 0;
+float  ATTN_NORM               = 1;
+float  ATTN_IDLE               = 2;
+float  ATTN_STATIC             = 3;
+
+// update types
+
+float  UPDATE_GENERAL  = 0;
+float  UPDATE_STATIC   = 1;
+float  UPDATE_BINARY   = 2;
+float  UPDATE_TEMP             = 3;
+
+// entity effects
+
+float  EF_BRIGHTFIELD  = 1;
+float  EF_MUZZLEFLASH  = 2;
+float  EF_BRIGHTLIGHT  = 4;
+float  EF_DIMLIGHT     = 8;
+
+
+// messages
+float  MSG_BROADCAST   = 0;            // unreliable to all
+float  MSG_ONE                 = 1;            // reliable to one (msg_entity)
+float  MSG_ALL                 = 2;            // reliable to all
+float  MSG_INIT                = 3;            // write to the init string
+
+//===========================================================================
+
+//
+// builtin functions
+//
+
+void(vector ang)       makevectors             = #1;           // sets v_forward, etc globals
+void(entity e, vector o) setorigin     = #2;
+void(entity e, string m) setmodel      = #3;           // set movetype and solid first
+void(entity e, vector min, vector max) setsize = #4;
+// #5 was removed
+void() break_to_debugger                                               = #6;
+float() random                                         = #7;           // returns 0 - 1
+void(entity e, float chan, string samp, float vol, float atten) sound = #8;
+vector(vector v) normalize                     = #9;
+void(string e, ...) error                              = #10;
+void(string e, ...) objerror                           = #11;
+float(vector v) vlen                           = #12;
+float(vector v) vectoyaw                       = #13;
+entity() spawn                                         = #14;
+void(entity e) remove                          = #15;
+
+// sets trace_* globals
+// nomonsters can be:
+// An entity will also be ignored for testing if forent == test,
+// forent->owner == test, or test->owner == forent
+// a forent of world is ignored
+void(vector v1, vector v2, float nomonsters, entity forent) traceline = #16;
+
+entity() checkclient                           = #17;  // returns a client to look for
+entity(entity start, .string fld, string match) find = #18;
+string(string s) precache_sound                = #19;
+string(string s) precache_model                = #20;
+void(entity client, string s, ...)stuffcmd = #21;
+entity(vector org, float rad) findradius = #22;
+void(string s, ...) bprint                             = #23;
+void(entity client, string s, ...) sprint = #24;
+void(string s, ...) dprint                             = #25;
+string(float f) ftos                           = #26;
+string(vector v) vtos                          = #27;
+void() coredump                                                = #28;          // prints all edicts
+void() traceon                                         = #29;          // turns statment trace on
+void() traceoff                                                = #30;
+void(entity e) eprint                          = #31;          // prints an entire edict
+float(float yaw, float dist) walkmove  = #32;  // returns TRUE or FALSE
+// #33 was removed
+float() droptofloor= #34;      // TRUE if landed on floor
+void(float style, string value) lightstyle = #35;
+float(float v) rint                                    = #36;          // round to nearest int
+float(float v) floor                           = #37;          // largest integer <= v
+float(float v) ceil                                    = #38;          // smallest integer >= v
+// #39 was removed
+float(entity e) checkbottom                    = #40;          // true if self is on ground
+float(vector v) pointcontents          = #41;          // returns a CONTENT_*
+// #42 was removed
+float(float f) fabs = #43;
+vector(entity e, float speed) aim = #44;               // returns the shooting vector
+float(string s) cvar = #45;                                            // return cvar.value
+void(string s, ...) localcmd = #46;                                    // put string into local que
+entity(entity e) nextent = #47;                                        // for looping through all ents
+void(vector o, vector d, float color, float count) particle = #48;// start a particle effect
+void() ChangeYaw = #49;                                                // turn towards self.ideal_yaw
+                                                                                       // at self.yaw_speed
+// #50 was removed
+vector(vector v) vectoangles                   = #51;
+
+//
+// direct client message generation
+//
+void(float to, float f) WriteByte              = #52;
+void(float to, float f) WriteChar              = #53;
+void(float to, float f) WriteShort             = #54;
+void(float to, float f) WriteLong              = #55;
+void(float to, float f) WriteCoord             = #56;
+void(float to, float f) WriteAngle             = #57;
+void(float to, string s, ...) WriteString      = #58;
+void(float to, entity s) WriteEntity   = #59;
+
+//
+// broadcast client message generation
+//
+
+// void(float f) bWriteByte            = #59;
+// void(float f) bWriteChar            = #60;
+// void(float f) bWriteShort           = #61;
+// void(float f) bWriteLong            = #62;
+// void(float f) bWriteCoord           = #63;
+// void(float f) bWriteAngle           = #64;
+// void(string s) bWriteString = #65;
+// void(entity e) bWriteEntity = #66;
+
+void(float step) movetogoal                            = #67;
+
+string(string s) precache_file         = #68;  // no effect except for -copy
+void(entity e) makestatic              = #69;
+void(string s) changelevel = #70;
+
+//#71 was removed
+
+void(string var, string val) cvar_set = #72;   // sets cvar.value
+
+void(entity client, string s, ...) centerprint = #73;  // sprint, but in middle
+
+void(vector pos, string samp, float vol, float atten) ambientsound = #74;
+
+string(string s) precache_model2       = #75;          // registered version only
+string(string s) precache_sound2       = #76;          // registered version only
+string(string s) precache_file2                = #77;          // registered version only
+
+void(entity e) setspawnparms           = #78;          // set parm1... to the
+                                                                                               // values at level start
+                                                                                               // for coop respawn
+
+//============================================================================
diff --git a/qcsrc/menu/_all.qh b/qcsrc/menu/_all.qh
new file mode 100644 (file)
index 0000000..a6903ae
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef CLIENT_ALL_H
+#define CLIENT_ALL_H
+
+#include "../dpdefs/menudefs.qh"
+#include "../dpdefs/keycodes.qh"
+
+#endif
index 26b01d71801f3555fa7cc5f0b329c833a5752848..3039d85b8daff86bcc48ccac4d5a38b64f7eb864 100644 (file)
@@ -1,5 +1,8 @@
-#ifdef INTERFACE
-CLASS(Animation) EXTENDS(Object)
+#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))
        METHOD(Animation, setTimeStartEnd, void(entity, float, float))
        METHOD(Animation, setTimeStartDuration, void(entity, float, float))
@@ -23,7 +26,6 @@ CLASS(Animation) EXTENDS(Object)
        ATTRIB(Animation, stopped, float, false)
        ATTRIB(Animation, finished, float, false)
 ENDCLASS(Animation)
-void setterDummy(entity, float);
 #endif
 
 #ifdef IMPLEMENTATION
index c46334d530aed763cd3e0c8706e387131e0d1730..61a040cff96801d4345b5cd27bd12002d6d0382a 100644 (file)
@@ -1,7 +1,9 @@
 #include "../menu.qh"
 
-#ifdef INTERFACE
-CLASS(AnimHost) EXTENDS(Object)
+#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))
        METHOD(AnimHost, removeAllAnim, void(entity))
index 94ea9cf0872da839e836be94e28cda460f029bab..fe4c0fb65a9e0cbb1134bcef1300c5069075c698 100644 (file)
@@ -1,15 +1,17 @@
-#ifdef INTERFACE
-CLASS(Easing) EXTENDS(Animation)
-       METHOD(Easing, calcValue, float(entity, float, float, float, float))
-       METHOD(Easing, setMath, void(entity, float(float, float, float, float)))
-       ATTRIB(Easing, math, float(float, float, float, float), easingLinear)
-ENDCLASS(Easing)
+#ifndef ANIM_EASING_H
+#define ANIM_EASING_H
+#include "animation.qc"
 entity makeHostedEasing(entity, void(entity, float), float(float, float, float, float), float, float, float);
 entity makeEasing(entity, void(entity, float), float(float, float, float, float), float, float, float, float);
 float easingLinear(float, float, float, float);
 float easingQuadIn(float, float, float, float);
 float easingQuadOut(float, float, float, float);
 float easingQuadInOut(float, float, float, float);
+CLASS(Easing, Animation)
+       METHOD(Easing, calcValue, float(entity, float, float, float, float))
+       METHOD(Easing, setMath, void(entity, float(float, float, float, float)))
+       ATTRIB(Easing, math, float(float, float, float, float), easingLinear)
+ENDCLASS(Easing)
 #endif
 
 #ifdef IMPLEMENTATION
@@ -24,7 +26,7 @@ entity makeHostedEasing(entity obj, void(entity, float) objSetter, float(float,
 entity makeEasing(entity obj, void(entity, float) objSetter, float(float, float, float, float) func, float animStartTime, float animDuration, float animStartValue, float animEnd)
 {
        entity me;
-       me = spawnEasing();
+       me = NEW(Easing);
        me.configureAnimation(me, obj, objSetter, animStartTime, animDuration, animStartValue, animEnd);
        me.setMath(me, func);
        return me;
index 3bcda94e692939b733c668cf09e46b27e59364c6..d310ef72c7093c7eabd56045b7ab7506a5731738 100644 (file)
@@ -1,5 +1,7 @@
-#ifdef INTERFACE
-CLASS(Keyframe) EXTENDS(Animation)
+#ifndef ANIM_KEYFRAME_H
+#define ANIM_KEYFRAME_H
+#include "animation.qc"
+CLASS(Keyframe, Animation)
        METHOD(Keyframe, addEasing, entity(entity, float, float, float(float, float, float, float)))
        METHOD(Keyframe, addAnim, void(entity, entity))
        METHOD(Keyframe, calcValue, float(entity, float, float, float, float))
@@ -26,7 +28,7 @@ entity makeHostedKeyframe(entity obj, void(entity, float) objSetter, float animD
 entity makeKeyframe(entity obj, void(entity, float) objSetter, float animDuration, float animStart, float animEnd)
 {
        entity me;
-       me = spawnKeyframe();
+       me = NEW(Keyframe);
        me.configureAnimation(me, obj, objSetter, time, animDuration, animStart, animEnd);
        return me;
 }
diff --git a/qcsrc/menu/classes.inc b/qcsrc/menu/classes.inc
new file mode 100644 (file)
index 0000000..5b0e417
--- /dev/null
@@ -0,0 +1,134 @@
+#include "anim/animation.qc"
+#include "anim/animhost.qc"
+#include "anim/easing.qc"
+#include "anim/keyframe.qc"
+
+#include "item.qc"
+#include "item/borderimage.qc"
+#include "item/button.qc"
+#include "item/checkbox.qc"
+#include "item/container.qc"
+#include "item/dialog.qc"
+#include "item/image.qc"
+#include "item/inputbox.qc"
+#include "item/inputcontainer.qc"
+#include "item/label.qc"
+#include "item/listbox.qc"
+#include "item/modalcontroller.qc"
+#include "item/nexposee.qc"
+#include "item/radiobutton.qc"
+#include "item/slider.qc"
+#include "item/tab.qc"
+#include "item/textslider.qc"
+
+#include "xonotic/bigbutton.qc"
+#include "xonotic/bigcommandbutton.qc"
+#include "xonotic/button.qc"
+#include "xonotic/campaign.qc"
+#include "xonotic/charmap.qc"
+#include "xonotic/checkbox.qc"
+#include "xonotic/checkbox_slider_invalid.qc"
+#include "xonotic/checkbox_string.qc"
+#include "xonotic/colorbutton.qc"
+#include "xonotic/colorpicker.qc"
+#include "xonotic/colorpicker_string.qc"
+#include "xonotic/commandbutton.qc"
+#include "xonotic/credits.qc"
+#include "xonotic/crosshairpicker.qc"
+#include "xonotic/crosshairpreview.qc"
+#include "xonotic/cvarlist.qc"
+#include "xonotic/demolist.qc"
+#include "xonotic/dialog.qc"
+#include "xonotic/dialog_credits.qc"
+#include "xonotic/dialog_firstrun.qc"
+#include "xonotic/dialog_hudpanel_ammo.qc"
+#include "xonotic/dialog_hudpanel_buffs.qc"
+#include "xonotic/dialog_hudpanel_centerprint.qc"
+#include "xonotic/dialog_hudpanel_chat.qc"
+#include "xonotic/dialog_hudpanel_engineinfo.qc"
+#include "xonotic/dialog_hudpanel_healtharmor.qc"
+#include "xonotic/dialog_hudpanel_infomessages.qc"
+#include "xonotic/dialog_hudpanel_modicons.qc"
+#include "xonotic/dialog_hudpanel_notification.qc"
+#include "xonotic/dialog_hudpanel_physics.qc"
+#include "xonotic/dialog_hudpanel_powerups.qc"
+#include "xonotic/dialog_hudpanel_pressedkeys.qc"
+#include "xonotic/dialog_hudpanel_racetimer.qc"
+#include "xonotic/dialog_hudpanel_radar.qc"
+#include "xonotic/dialog_hudpanel_score.qc"
+#include "xonotic/dialog_hudpanel_timer.qc"
+#include "xonotic/dialog_hudpanel_vote.qc"
+#include "xonotic/dialog_hudpanel_weapons.qc"
+#include "xonotic/dialog_hudsetup_exit.qc"
+#include "xonotic/dialog_monstertools.qc"
+#include "xonotic/dialog_multiplayer.qc"
+#include "xonotic/dialog_multiplayer_create.qc"
+#include "xonotic/dialog_multiplayer_create_mapinfo.qc"
+#include "xonotic/dialog_multiplayer_create_mutators.qc"
+#include "xonotic/dialog_multiplayer_join.qc"
+#include "xonotic/dialog_multiplayer_join_serverinfo.qc"
+#include "xonotic/dialog_multiplayer_media.qc"
+#include "xonotic/dialog_multiplayer_media_demo.qc"
+#include "xonotic/dialog_multiplayer_media_demo_startconfirm.qc"
+#include "xonotic/dialog_multiplayer_media_demo_timeconfirm.qc"
+#include "xonotic/dialog_multiplayer_media_musicplayer.qc"
+#include "xonotic/dialog_multiplayer_media_screenshot.qc"
+#include "xonotic/dialog_multiplayer_media_screenshot_viewer.qc"
+#include "xonotic/dialog_multiplayer_profile.qc"
+#include "xonotic/dialog_quit.qc"
+#include "xonotic/dialog_sandboxtools.qc"
+#include "xonotic/dialog_settings.qc"
+#include "xonotic/dialog_settings_audio.qc"
+#include "xonotic/dialog_settings_effects.qc"
+#include "xonotic/dialog_settings_game.qc"
+#include "xonotic/dialog_settings_game_crosshair.qc"
+#include "xonotic/dialog_settings_game_hudconfirm.qc"
+#include "xonotic/dialog_settings_game_hud.qc"
+#include "xonotic/dialog_settings_game_messages.qc"
+#include "xonotic/dialog_settings_game_model.qc"
+#include "xonotic/dialog_settings_game_view.qc"
+#include "xonotic/dialog_settings_game_weapons.qc"
+#include "xonotic/dialog_settings_input.qc"
+#include "xonotic/dialog_settings_input_userbind.qc"
+#include "xonotic/dialog_settings_misc.qc"
+#include "xonotic/dialog_settings_misc_cvars.qc"
+#include "xonotic/dialog_settings_misc_reset.qc"
+#include "xonotic/dialog_settings_user.qc"
+#include "xonotic/dialog_settings_user_languagewarning.qc"
+#include "xonotic/dialog_settings_video.qc"
+#include "xonotic/dialog_singleplayer.qc"
+#include "xonotic/dialog_singleplayer_winner.qc"
+#include "xonotic/dialog_teamselect.qc"
+#include "xonotic/gametypelist.qc"
+#include "xonotic/image.qc"
+#include "xonotic/inputbox.qc"
+#include "xonotic/keybinder.qc"
+#include "xonotic/languagelist.qc"
+#include "xonotic/listbox.qc"
+#include "xonotic/mainwindow.qc"
+#include "xonotic/maplist.qc"
+#include "xonotic/nexposee.qc"
+#include "xonotic/picker.qc"
+#include "xonotic/playerlist.qc"
+#include "xonotic/playermodel.qc"
+#include "xonotic/playlist.qc"
+#include "xonotic/radiobutton.qc"
+#include "xonotic/rootdialog.qc"
+#include "xonotic/screenshotimage.qc"
+#include "xonotic/screenshotlist.qc"
+#include "xonotic/serverlist.qc"
+#include "xonotic/skinlist.qc"
+#include "xonotic/slider.qc"
+#include "xonotic/slider_decibels.qc"
+#include "xonotic/slider_particles.qc"
+#include "xonotic/slider_picmip.qc"
+#include "xonotic/slider_resolution.qc"
+#include "xonotic/slider_sbfadetime.qc"
+#include "xonotic/soundlist.qc"
+#include "xonotic/statslist.qc"
+#include "xonotic/tabcontroller.qc"
+#include "xonotic/tab.qc"
+#include "xonotic/textlabel.qc"
+#include "xonotic/textslider.qc"
+#include "xonotic/weaponarenacheckbox.qc"
+#include "xonotic/weaponslist.qc"
diff --git a/qcsrc/menu/classes.qc b/qcsrc/menu/classes.qc
deleted file mode 100644 (file)
index 9b4bb4d..0000000
+++ /dev/null
@@ -1,130 +0,0 @@
-#include "anim/animhost.qc"
-#include "anim/animation.qc"
-#include "anim/easing.qc"
-#include "anim/keyframe.qc"
-#include "item.qc"
-#include "item/container.qc"
-#include "item/inputcontainer.qc"
-#include "item/nexposee.qc"
-#include "item/modalcontroller.qc"
-#include "item/image.qc"
-#include "item/label.qc"
-#include "item/button.qc"
-#include "item/checkbox.qc"
-#include "item/radiobutton.qc"
-#include "item/borderimage.qc"
-#include "item/slider.qc"
-#include "item/dialog.qc"
-#include "item/tab.qc"
-#include "item/textslider.qc"
-#include "item/listbox.qc"
-#include "item/inputbox.qc"
-#include "xonotic/dialog.qc"
-#include "xonotic/tab.qc"
-#include "xonotic/mainwindow.qc"
-#include "xonotic/button.qc"
-#include "xonotic/bigbutton.qc"
-#include "xonotic/commandbutton.qc"
-#include "xonotic/bigcommandbutton.qc"
-#include "xonotic/textlabel.qc"
-#include "xonotic/dialog_firstrun.qc"
-#include "xonotic/dialog_teamselect.qc"
-#include "xonotic/dialog_sandboxtools.qc"
-#include "xonotic/dialog_monstertools.qc"
-#include "xonotic/dialog_settings.qc"
-#include "xonotic/dialog_settings_video.qc"
-#include "xonotic/dialog_settings_effects.qc"
-#include "xonotic/dialog_settings_audio.qc"
-#include "xonotic/dialog_settings_game.qc"
-#include "xonotic/dialog_settings_user.qc"
-#include "xonotic/dialog_settings_user_languagewarning.qc"
-#include "xonotic/dialog_settings_misc.qc"
-#include "xonotic/dialog_multiplayer.qc"
-#include "xonotic/dialog_multiplayer_profile.qc"
-#include "xonotic/tabcontroller.qc"
-#include "xonotic/slider.qc"
-#include "xonotic/slider_resolution.qc"
-#include "xonotic/checkbox.qc"
-#include "xonotic/checkbox_string.qc"
-#include "xonotic/weaponarenacheckbox.qc"
-#include "xonotic/radiobutton.qc"
-#include "xonotic/nexposee.qc"
-#include "xonotic/rootdialog.qc"
-#include "xonotic/textslider.qc"
-#include "xonotic/colorbutton.qc"
-#include "xonotic/dialog_multiplayer_join.qc"
-#include "xonotic/dialog_multiplayer_join_serverinfo.qc"
-#include "xonotic/playerlist.qc"
-#include "xonotic/listbox.qc"
-#include "xonotic/serverlist.qc"
-#include "xonotic/inputbox.qc"
-#include "xonotic/dialog_quit.qc"
-#include "xonotic/dialog_multiplayer_create.qc"
-#include "xonotic/dialog_multiplayer_create_mutators.qc"
-#include "xonotic/dialog_multiplayer_create_mapinfo.qc"
-#include "xonotic/gametypelist.qc"
-#include "xonotic/maplist.qc"
-#include "xonotic/skinlist.qc"
-#include "xonotic/languagelist.qc"
-#include "xonotic/image.qc"
-#include "xonotic/crosshairbutton.qc"
-#include "xonotic/playermodel.qc"
-#include "xonotic/checkbox_slider_invalid.qc"
-#include "xonotic/charmap.qc"
-#include "xonotic/keybinder.qc"
-#include "xonotic/dialog_settings_input.qc"
-#include "xonotic/dialog_settings_input_userbind.qc"
-#include "xonotic/slider_decibels.qc"
-#include "xonotic/dialog_singleplayer.qc"
-#include "xonotic/campaign.qc"
-#include "xonotic/dialog_singleplayer_winner.qc"
-#include "xonotic/dialog_credits.qc"
-#include "xonotic/credits.qc"
-#include "xonotic/dialog_settings_game_crosshair.qc"
-#include "xonotic/dialog_settings_game_hud.qc"
-#include "xonotic/dialog_settings_game_hudconfirm.qc"
-#include "xonotic/dialog_settings_game_model.qc"
-#include "xonotic/dialog_settings_game_messages.qc"
-#include "xonotic/dialog_settings_game_view.qc"
-#include "xonotic/dialog_settings_game_weapons.qc"
-#include "xonotic/weaponslist.qc"
-#include "xonotic/dialog_multiplayer_media.qc"
-#include "xonotic/dialog_multiplayer_media_demo.qc"
-#include "xonotic/dialog_multiplayer_media_demo_startconfirm.qc"
-#include "xonotic/dialog_multiplayer_media_demo_timeconfirm.qc"
-#include "xonotic/demolist.qc"
-#include "xonotic/screenshotimage.qc"
-#include "xonotic/dialog_multiplayer_media_screenshot.qc"
-#include "xonotic/dialog_multiplayer_media_screenshot_viewer.qc"
-#include "xonotic/screenshotlist.qc"
-#include "xonotic/statslist.qc"
-#include "xonotic/dialog_multiplayer_media_musicplayer.qc"
-#include "xonotic/soundlist.qc"
-#include "xonotic/playlist.qc"
-#include "xonotic/colorpicker.qc"
-#include "xonotic/colorpicker_string.qc"
-#include "xonotic/cvarlist.qc"
-#include "xonotic/dialog_settings_misc_cvars.qc"
-#include "xonotic/dialog_hudsetup_exit.qc"
-#include "xonotic/dialog_hudpanel_notification.qc"
-#include "xonotic/dialog_hudpanel_ammo.qc"
-#include "xonotic/dialog_hudpanel_healtharmor.qc"
-#include "xonotic/dialog_hudpanel_powerups.qc"
-#include "xonotic/dialog_hudpanel_racetimer.qc"
-#include "xonotic/dialog_hudpanel_pressedkeys.qc"
-#include "xonotic/dialog_hudpanel_radar.qc"
-#include "xonotic/dialog_hudpanel_score.qc"
-#include "xonotic/dialog_hudpanel_timer.qc"
-#include "xonotic/dialog_hudpanel_vote.qc"
-#include "xonotic/dialog_hudpanel_modicons.qc"
-#include "xonotic/dialog_hudpanel_chat.qc"
-#include "xonotic/dialog_hudpanel_engineinfo.qc"
-#include "xonotic/dialog_hudpanel_infomessages.qc"
-#include "xonotic/dialog_hudpanel_weapons.qc"
-#include "xonotic/dialog_hudpanel_physics.qc"
-#include "xonotic/dialog_hudpanel_centerprint.qc"
-#include "xonotic/dialog_hudpanel_buffs.qc"
-#include "xonotic/slider_picmip.qc"
-#include "xonotic/slider_particles.qc"
-#include "xonotic/slider_sbfadetime.qc"
-#include "xonotic/dialog_settings_misc_reset.qc"
diff --git a/qcsrc/menu/command/all.qc b/qcsrc/menu/command/all.qc
new file mode 100644 (file)
index 0000000..711a747
--- /dev/null
@@ -0,0 +1,5 @@
+#include "../menu.qh"
+
+#include "../../common/command/all.qc"
+
+#include "menu_cmd.qc"
diff --git a/qcsrc/menu/command/all.qh b/qcsrc/menu/command/all.qh
new file mode 100644 (file)
index 0000000..7f116ae
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef MENU_COMMANDS_ALL_H
+#define MENU_COMMANDS_ALL_H
+
+#include "../../common/command/commands.qh"
+
+#include "menu_cmd.qh"
+
+#endif
index 93825cd56098d73e2ebe53aa0aee97041fcaf03c..3f3f72f5753f61a291966d325f64ea0481d53bd3 100644 (file)
@@ -1,7 +1,12 @@
 #include "menu_cmd.qh"
 
+#include "../menu.qh"
+#include "../oo/classes.qc"
+
 #include "../../common/command/generic.qh"
 
+.entity firstChild, nextSibling;
+
 string _dumptree_space;
 void _dumptree_open(entity pass, entity me)
 {
@@ -29,6 +34,8 @@ void _dumptree_close(entity pass, entity me)
        }
 }
 
+float updateConwidths(float width, float height, float pixelheight);
+
 void GameCommand(string theCommand)
 {
        float argc;
index 05e7af227adccb9040870bc7e690e405a7b1d400..2796c05706d0647662ebff6c4dafd88ac5c24b7b 100644 (file)
@@ -1,7 +1,6 @@
-#if defined(CSQC)
-#elif defined(MENUQC)
-#elif defined(SVQC)
-#endif
+#include "draw.qh"
+#include "../common/util.qh"
+#include "../common/constants.qh"
 
 string draw_mousepointer;
 vector draw_mousepointer_offset;
index d0bd40b03884c30d4e83c6727e82d89ac23019a3..cb24866d1ffbe198431b7fc414cb0adf650e2452 100644 (file)
@@ -1,5 +1,8 @@
-#ifdef INTERFACE
-CLASS(Item) EXTENDS(Object)
+#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))
        METHOD(Item, keyUp, float(entity, float, float, float))
index e6affc1c03a848c93edbf95e9a9d1b6fe8fccaa8..6b6f4693dc4a48d83823a7144c29f033daacc632 100644 (file)
@@ -1,5 +1,7 @@
-#ifdef INTERFACE
-CLASS(BorderImage) EXTENDS(Label)
+#ifndef ITEM_BORDERIMAGE_H
+#define ITEM_BORDERIMAGE_H
+#include "label.qc"
+CLASS(BorderImage, Label)
        METHOD(BorderImage, configureBorderImage, void(entity, string, float, vector, string, float))
        METHOD(BorderImage, resizeNotify, void(entity, vector, vector, vector, vector))
        METHOD(BorderImage, recalcPositionWithText, void(entity, string))
index 52e58238c86916248549bfb6c87a917913705098..796ce40a3365374b2e870e2fc630a84f250a6fd6 100644 (file)
@@ -1,5 +1,7 @@
-#ifdef INTERFACE
-CLASS(Button) EXTENDS(Label)
+#ifndef ITEM_BUTTON_H
+#define ITEM_BUTTON_H
+#include "label.qc"
+CLASS(Button, Label)
        METHOD(Button, configureButton, void(entity, string, float, string))
        METHOD(Button, draw, void(entity))
        METHOD(Button, showNotify, void(entity))
index 2540cc846fdbddf80ef44a5d8f4bd022e7f1dee8..e8b4e15e339349ad655af6f866aefccd5eb35796 100644 (file)
@@ -1,6 +1,8 @@
-#ifdef INTERFACE
+#ifndef ITEM_CHECKBOX_H
+#define ITEM_CHECKBOX_H
+#include "button.qc"
 void CheckBox_Click(entity me, entity other);
-CLASS(CheckBox) EXTENDS(Button)
+CLASS(CheckBoxButton)
        METHOD(CheckBox, configureCheckBox, void(entity, string, float, string))
        METHOD(CheckBox, draw, void(entity))
        METHOD(CheckBox, playClickSound, void(entity))
index dc369862f3c8bf61fe9d2584af9263059f11b3f6..ac0655cfa6d1ecad35403763767ceba31d431d9c 100644 (file)
@@ -1,5 +1,7 @@
-#ifdef INTERFACE
-CLASS(Container) EXTENDS(Item)
+#ifndef ITEM_CONTAINER_H
+#define ITEM_CONTAINER_H
+#include "../item.qc"
+CLASS(Container, Item)
        METHOD(Container, draw, void(entity))
        METHOD(Container, keyUp, float(entity, float, float, float))
        METHOD(Container, keyDown, float(entity, float, float, float))
@@ -12,6 +14,7 @@ CLASS(Container) EXTENDS(Item)
        METHOD(Container, resizeNotifyLie, void(entity, vector, vector, vector, vector, .vector, .vector, .vector))
        METHOD(Container, addItem, void(entity, entity, vector, vector, float))
        METHOD(Container, addItemCentered, void(entity, entity, vector, float))
+       METHOD(Container, addItemRightCentered, void(entity, entity, vector, float))
        METHOD(Container, moveItemAfter, void(entity, entity, entity))
        METHOD(Container, removeItem, void(entity, entity))
        METHOD(Container, setFocus, void(entity, entity))
@@ -117,9 +120,9 @@ void Container_resizeNotifyLie(entity me, vector relOrigin, vector relSize, vect
        float d;
        for(e = me.firstChild; e; e = e.nextSibling)
        {
-               o = e.originField;
-               s = e.sizeField;
-               me.enterLieSubitem(me, o, s, e.fontScaleField, e.Container_alpha);
+               o = e.(originField);
+               s = e.(sizeField);
+               me.enterLieSubitem(me, o, s, e.(fontScaleField), e.Container_alpha);
                e.resizeNotify(e, o, s, boxToGlobal(o, absOrigin, absSize), boxToGlobalSize(s, absSize));
                me.leaveSubitem(me);
        }
@@ -131,9 +134,9 @@ void Container_resizeNotifyLie(entity me, vector relOrigin, vector relSize, vect
                        {
                                e.resized = 0;
                                d = 1;
-                               o = e.originField;
-                               s = e.sizeField;
-                               me.enterLieSubitem(me, o, s, e.fontScaleField, e.Container_alpha);
+                               o = e.(originField);
+                               s = e.(sizeField);
+                               me.enterLieSubitem(me, o, s, e.(fontScaleField), e.Container_alpha);
                                e.resizeNotify(e, o, s, boxToGlobal(o, absOrigin, absSize), boxToGlobalSize(s, absSize));
                                me.leaveSubitem(me);
                        }
@@ -280,6 +283,11 @@ void Container_addItemCentered(entity me, entity other, vector theSize, float th
        me.addItem(me, other, '0.5 0.5 0' - 0.5 * theSize, theSize, theAlpha);
 }
 
+void Container_addItemRightCentered(entity me, entity other, vector theSize, float theAlpha)
+{
+       me.addItem(me, other, '1 0.5 0' - 0.5 * theSize, theSize, theAlpha);
+}
+
 void Container_addItem(entity me, entity other, vector theOrigin, vector theSize, float theAlpha)
 {
        if(other.parent)
index 1723f27cb8e5335691741ca3df38a883f3798e74..77037ace61132e48fc3bf57e87f24fc7e249756a 100644 (file)
 //
 // a subclass may help with using this as a tab
 
-#ifdef INTERFACE
-CLASS(Dialog) EXTENDS(InputContainer)
+#ifndef ITEM_DIALOG_H
+#define ITEM_DIALOG_H
+#include "inputcontainer.qc"
+CLASS(Dialog, InputContainer)
        METHOD(Dialog, configureDialog, void(entity)) // no runtime configuration, all parameters are given in the code!
        METHOD(Dialog, fill, void(entity)) // to be overridden by user to fill the dialog with controls
        METHOD(Dialog, keyDown, float(entity, float, float, float))
@@ -128,12 +130,15 @@ void Dialog_configureDialog(entity me)
 {
        float absWidth, absHeight;
 
-       me.frame = spawnBorderImage();
-       me.frame.configureBorderImage(me.frame, me.title, me.titleFontSize, me.color, me.backgroundImage, me.borderLines * me.titleHeight);
-       me.frame.zoomedOutTitleBarPosition = me.zoomedOutTitleBarPosition;
-       me.frame.zoomedOutTitleBar = me.zoomedOutTitleBar;
-       me.frame.alpha = me.alpha;
-       me.addItem(me, me.frame, '0 0 0', '1 1 0', 1);
+       if(me.isTabRoot)
+       {
+               me.frame = NEW(BorderImage);
+               me.frame.configureBorderImage(me.frame, me.title, me.titleFontSize, me.color, me.backgroundImage, me.borderLines * me.titleHeight);
+               me.frame.zoomedOutTitleBarPosition = me.zoomedOutTitleBarPosition;
+               me.frame.zoomedOutTitleBar = me.zoomedOutTitleBar;
+               me.frame.alpha = me.alpha;
+               me.addItem(me, me.frame, '0 0 0', '1 1 0', 1);
+       }
 
        if (!me.titleFontSize)
                me.titleHeight = 0; // no title bar
@@ -153,10 +158,10 @@ void Dialog_configureDialog(entity me)
 
        me.fill(me);
 
-       if(me.closable && me.borderLines > 0)
+       if(me.isTabRoot && me.closable && me.borderLines > 0)
        {
                entity closebutton;
-               closebutton = me.closeButton = me.frame.closeButton = spawnButton();
+               closebutton = me.closeButton = me.frame.closeButton = NEW(Button);
                closebutton.configureButton(closebutton, "", 0, me.closeButtonImage);
                closebutton.onClick = Dialog_Close; closebutton.onClickEntity = me;
                closebutton.srcMulti = 0;
index b67df840cc7f8e58134592ee4332fdd04370c9d3..7756b4991338ff440342a137dc362553230a9723 100644 (file)
@@ -1,5 +1,7 @@
-#ifdef INTERFACE
-CLASS(Image) EXTENDS(Item)
+#ifndef ITEM_IMAGE_H
+#define ITEM_IMAGE_H
+#include "../item.qc"
+CLASS(Image, Item)
        METHOD(Image, configureImage, void(entity, string))
        METHOD(Image, draw, void(entity))
        METHOD(Image, toString, string(entity))
index 275b20046def9e411a8211d231fc55a3117e162e..5bcfd5f9c0491f4e2a8a36310f74e805ac5f4b72 100644 (file)
@@ -1,5 +1,7 @@
-#ifdef INTERFACE
-CLASS(InputBox) EXTENDS(Label)
+#ifndef ITEM_INPUTBOX_H
+#define ITEM_INPUTBOX_H
+#include "label.qc"
+CLASS(InputBox, Label)
        METHOD(InputBox, configureInputBox, void(entity, string, float, float, string))
        METHOD(InputBox, draw, void(entity))
        METHOD(InputBox, setText, void(entity, string))
index 8c09d1991be2a474eaa0e331918fce0ff3698307..90ca719dce9e25326e54a700df5799f7a5a83189 100644 (file)
@@ -1,5 +1,7 @@
-#ifdef INTERFACE
-CLASS(InputContainer) EXTENDS(Container)
+#ifndef ITEM_INPUTCONTAINER_H
+#define ITEM_INPUTCONTAINER_H
+#include "container.qc"
+CLASS(InputContainer, Container)
        METHOD(InputContainer, keyDown, float(entity, float, float, float))
        METHOD(InputContainer, mouseMove, float(entity, vector))
        METHOD(InputContainer, mousePress, float(entity, vector))
index a1769fc03d7ba5ed5235f99bbef65e5437cdc566..75e79f0b228394e3d5da4c0c377992e9a1e12b4b 100644 (file)
@@ -1,5 +1,7 @@
-#ifdef INTERFACE
-CLASS(Label) EXTENDS(Item)
+#ifndef ITEM_LABEL_H
+#define ITEM_LABEL_H
+#include "../item.qc"
+CLASS(Label, Item)
        METHOD(Label, configureLabel, void(entity, string, float, float))
        METHOD(Label, draw, void(entity))
        METHOD(Label, resizeNotify, void(entity, vector, vector, vector, vector))
index 178b12b9a047ea3645cb89ca8fa09326ddb692f2..f7c17fa6bd888a73e580f825c81c077467d230a5 100644 (file)
@@ -1,16 +1,21 @@
-#ifdef INTERFACE
-CLASS(ListBox) EXTENDS(Item)
+#ifndef ITEM_LISTBOX_H
+#define ITEM_LISTBOX_H
+#include "../item.qc"
+CLASS(ListBox, Item)
        METHOD(ListBox, resizeNotify, void(entity, vector, vector, vector, vector))
        METHOD(ListBox, configureListBox, void(entity, float, float))
        METHOD(ListBox, draw, void(entity))
        METHOD(ListBox, keyDown, float(entity, float, float, float))
+       METHOD(ListBox, mouseMove, float(entity, vector))
        METHOD(ListBox, mousePress, float(entity, vector))
        METHOD(ListBox, mouseDrag, float(entity, vector))
        METHOD(ListBox, mouseRelease, float(entity, vector))
        METHOD(ListBox, focusLeave, void(entity))
        ATTRIB(ListBox, focusable, float, 1)
+       ATTRIB(ListBox, focusedItem, int, -1)
+       ATTRIB(ListBox, focusedItemAlpha, float, 0.3)
        ATTRIB(ListBox, allowFocusSound, float, 1)
-       ATTRIB(ListBox, selectedItem, float, 0)
+       ATTRIB(ListBox, selectedItem, int, 0)
        ATTRIB(ListBox, size, vector, '0 0 0')
        ATTRIB(ListBox, origin, vector, '0 0 0')
        ATTRIB(ListBox, scrollPos, float, 0) // measured in window heights, fixed when needed
@@ -40,7 +45,7 @@ CLASS(ListBox) EXTENDS(Item)
        ATTRIB(ListBox, lastClickedItem, float, -1)
        ATTRIB(ListBox, lastClickedTime, float, 0)
 
-       METHOD(ListBox, drawListBoxItem, void(entity, float, vector, float)) // item number, width/height, selected
+       METHOD(ListBox, drawListBoxItem, void(entity, int, vector, bool, bool)) // item number, width/height, isSelected, isFocused
        METHOD(ListBox, clickListBoxItem, void(entity, float, vector)) // item number, relative clickpos
        METHOD(ListBox, doubleClickListBoxItem, void(entity, float, vector)) // item number, relative clickpos
        METHOD(ListBox, setSelected, void(entity, float))
@@ -176,6 +181,22 @@ float ListBox_keyDown(entity me, float key, float ascii, float shift)
                return 0;
        return 1;
 }
+float ListBox_mouseMove(entity me, vector pos)
+{
+       if(pos_x < 0) return 0;
+       if(pos_y < 0) return 0;
+       if(pos_x >= 1) return 0;
+       if(pos_y >= 1) return 0;
+       if(pos_x < 1 - me.controlWidth)
+       {
+               float x;
+               x = me.focusedItem;
+               me.focusedItem = me.getItemAtPos(me, me.scrollPos + pos.y);
+               if(x != me.focusedItem)
+                       me.focusedItemAlpha = SKINALPHA_LISTBOX_FOCUSED;
+       }
+       return 1;
+}
 float ListBox_mouseDrag(entity me, vector pos)
 {
        float hit;
@@ -286,6 +307,7 @@ void ListBox_focusLeave(entity me)
        // by a mouse click on an item of the list
        // for example showing a dialog on right click
        me.pressed = 0;
+       me.focusedItem = -1;
 }
 void ListBox_updateControlTopBottom(entity me)
 {
@@ -367,6 +389,7 @@ void ListBox_draw(entity me)
        draw_SetClip();
        oldshift = draw_shift;
        oldscale = draw_scale;
+
        float y;
        i = me.getItemAtPos(me, me.scrollPos);
        y = me.getItemStart(me, i) - me.scrollPos;
@@ -376,7 +399,7 @@ void ListBox_draw(entity me)
                vector relSize = eX * (1 - me.controlWidth) + eY * me.getItemHeight(me, i);
                absSize = boxToGlobalSize(relSize, me.size);
                draw_scale = boxToGlobalSize(relSize, oldscale);
-               me.drawListBoxItem(me, i, absSize, (me.selectedItem == i));
+               me.drawListBoxItem(me, i, absSize, (me.selectedItem == i), (me.focusedItem == i));
                y += relSize.y;
        }
        draw_ClearClip();
@@ -396,8 +419,8 @@ void ListBox_doubleClickListBoxItem(entity me, float i, vector where)
        // template method
 }
 
-void ListBox_drawListBoxItem(entity me, float i, vector absSize, float selected)
+void ListBox_drawListBoxItem(entity me, int i, vector absSize, bool isSelected, bool isFocused)
 {
-       draw_Text('0 0 0', sprintf(_("Item %d"), i), eX * (8 / absSize.x) + eY * (8 / absSize.y), (selected ? '0 1 0' : '1 1 1'), 1, 0);
+       draw_Text('0 0 0', sprintf(_("Item %d"), i), eX * (8 / absSize.x) + eY * (8 / absSize.y), (isSelected ? '0 1 0' : '1 1 1'), 1, 0);
 }
 #endif
index 3ef656744568ad3b0ebfd25768e5acf3267fbfe5..a13fcdd69f5706d663ea529072735ae0a85c4dcc 100644 (file)
@@ -1,5 +1,7 @@
-#ifdef INTERFACE
-CLASS(ModalController) EXTENDS(Container)
+#ifndef ITEM_MODALCONTROLLER_H
+#define ITEM_MODALCONTROLLER_H
+#include "container.qc"
+CLASS(ModalController, Container)
        METHOD(ModalController, resizeNotify, void(entity, vector, vector, vector, vector))
        METHOD(ModalController, draw, void(entity))
        METHOD(ModalController, showChild, void(entity, entity, vector, vector, float))
index 1413039851ee7fcde86e3869d8778c9d2fc72614..69d54b7a0733e6d6b766f88b385906237e6a4fb7 100644 (file)
@@ -1,5 +1,7 @@
-#ifdef INTERFACE
-CLASS(Nexposee) EXTENDS(Container)
+#ifndef ITEM_NEXPOSEE_H
+#define ITEM_NEXPOSEE_H
+#include "container.qc"
+CLASS(Nexposee, Container)
        METHOD(Nexposee, draw, void(entity))
        METHOD(Nexposee, keyDown, float(entity, float, float, float))
        METHOD(Nexposee, keyUp, float(entity, float, float, float))
@@ -23,7 +25,6 @@ CLASS(Nexposee) EXTENDS(Container)
 ENDCLASS(Nexposee)
 
 void ExposeeCloseButton_Click(entity button, entity other); // un-exposees the current state
-#endif
 
 // animation states:
 //   0 = thumbnails seen
@@ -31,9 +32,6 @@ void ExposeeCloseButton_Click(entity button, entity other); // un-exposees the c
 //   2 = zoomed in
 //   3 = zooming out
 // animation factor: 0 = minimum theSize, 1 = maximum theSize
-
-#ifdef IMPLEMENTATION
-
 .vector Nexposee_initialSize;
 .vector Nexposee_initialFontScale;
 .vector Nexposee_initialOrigin;
@@ -47,6 +45,9 @@ void ExposeeCloseButton_Click(entity button, entity other); // un-exposees the c
 .vector Nexposee_align;
 .float Nexposee_animationFactor;
 
+#endif
+
+#ifdef IMPLEMENTATION
 void Nexposee_close(entity me)
 {
        // user must override this
index 80fd5329b41f70f2dedab6ced75caea971e58284..c1e034855aeaa2cc7992ddea2373ff9ae79fa06e 100644 (file)
@@ -1,6 +1,8 @@
-#ifdef INTERFACE
+#ifndef ITEM_RADIOBUTTON_H
+#define ITEM_RADIOBUTTON_H
+#include "checkbox.qc"
 void RadioButton_Click(entity me, entity other);
-CLASS(RadioButton) EXTENDS(CheckBox)
+CLASS(RadioButtonCheckBox)
        METHOD(RadioButton, configureRadioButton, void(entity, string, float, string, float, float))
        ATTRIB(RadioButton, checked, float, 0)
        ATTRIB(RadioButton, group, float, 0)
index 2c74f6131c8f06e40e4a530bcb3720e2e2612613..e944a96aea18f010c7a6e3dd5b25ddc8ec15cfbf 100644 (file)
@@ -1,7 +1,9 @@
 // Note:
 //   to use this, you FIRST call configureSliderVisuals, then configureSliderValues
-#ifdef INTERFACE
-CLASS(Slider) EXTENDS(Label)
+#ifndef ITEM_SLIDER_H
+#define ITEM_SLIDER_H
+#include "label.qc"
+CLASS(Slider, Label)
        METHOD(Slider, resizeNotify, void(entity, vector, vector, vector, vector))
        METHOD(Slider, configureSliderVisuals, void(entity, float, float, float, string))
        METHOD(Slider, configureSliderValues, void(entity, float, float, float, float, float, float))
index 8cd72ba9c76a253b73001f2b1a32e3b95d23bf89..fbbf77668750c26a27b5e1b1e018e0805d0cb822 100644 (file)
@@ -1,5 +1,7 @@
-#ifdef INTERFACE
-CLASS(Tab) EXTENDS(Dialog)
+#ifndef ITEM_TAB_H
+#define ITEM_TAB_H
+#include "dialog.qc"
+CLASS(Tab, Dialog)
        ATTRIB(Tab, isTabRoot, float, 0)
        ATTRIB(Tab, closable, float, 0)
        ATTRIB(Tab, rootDialog, float, 0)
index 59d8c10db59f6053009f51b90bd39a7c2561c645..f22e632d6f03f9973b47540bbbcfe69975e8f22c 100644 (file)
@@ -1,7 +1,9 @@
 // Note:
 //   to use this, you FIRST call configureSliderVisuals, then multiple times addValue, then configureTextSlider
-#ifdef INTERFACE
-CLASS(TextSlider) EXTENDS(Slider)
+#ifndef ITEM_TEXTSLIDER_H
+#define ITEM_TEXTSLIDER_H
+#include "slider.qc"
+CLASS(TextSlider, Slider)
        METHOD(TextSlider, valueToText, string(entity, float))
        METHOD(TextSlider, valueToIdentifier, string(entity, float))
        METHOD(TextSlider, setValueFromIdentifier, void(entity, string))
@@ -12,12 +14,12 @@ CLASS(TextSlider) EXTENDS(Slider)
        METHOD(TextSlider, configureTextSliderValues, void(entity, string))
        ATTRIBARRAY(TextSlider, valueStrings, string, 256)
        ATTRIBARRAY(TextSlider, valueIdentifiers, string, 256)
-       ATTRIB(TextSlider, nValues, float, 0)
+       ATTRIB(TextSlider, nValues, int, 0)
 ENDCLASS(TextSlider)
 #endif
 
 #ifdef IMPLEMENTATION
-string TextSlider_valueToIdentifier(entity me, float val)
+string TextSlider_valueToIdentifier(entity me, int val)
 {
        if(val >= me.nValues)
                return "custom";
@@ -25,7 +27,7 @@ string TextSlider_valueToIdentifier(entity me, float val)
                return "custom";
        return me.(valueIdentifiers[val]);
 }
-string TextSlider_valueToText(entity me, float val)
+string TextSlider_valueToText(entity me, int val)
 {
        if(val >= me.nValues)
                return _("Custom");
@@ -35,7 +37,7 @@ string TextSlider_valueToText(entity me, float val)
 }
 void TextSlider_setValueFromIdentifier(entity me, string id)
 {
-       float i;
+       int i;
        for(i = 0; i < me.nValues; ++i)
                if(me.valueToIdentifier(me, i) == id)
                {
@@ -58,9 +60,9 @@ void TextSlider_addValue(entity me, string theString, string theIdentifier)
        me.(valueIdentifiers[me.nValues]) = theIdentifier;
        me.nValues += 1;
 }
-void TextSlider_insertValue(entity me, float pos, string theString, string theIdentifier)
+void TextSlider_insertValue(entity me, int pos, string theString, string theIdentifier)
 {
-       float i;
+       int i;
        for (i = me.nValues; i > pos; --i)
        {
                me.(valueStrings[i]) = me.(valueStrings[i-1]);
index e348796a0f89747b89e16fa315684d4ae0edddc7..d8a3ede2e7d8988afd29865a409af7de2defe772 100644 (file)
@@ -1,7 +1,10 @@
-#if defined(CSQC)
-#elif defined(MENUQC)
-#elif defined(SVQC)
-#endif
+#include "menu.qh"
+#include "oo/classes.qc"
+#include "xonotic/util.qh"
+
+#include "../common/items/all.qh"
+#include "../common/weapons/all.qh"
+#include "../common/mapinfo.qh"
 
 ///////////////////////////////////////////////
 // Menu Source File
@@ -78,6 +81,7 @@ void m_init()
 
        // needs to be done so early because of the constants they create
        CALL_ACCUMULATED_FUNCTION(RegisterWeapons);
+       CALL_ACCUMULATED_FUNCTION(RegisterItems);
        CALL_ACCUMULATED_FUNCTION(RegisterGametypes);
 
        RegisterSLCategories();
@@ -211,8 +215,8 @@ void m_init_delayed()
        draw_setMousePointer(SKINGFX_CURSOR, SKINSIZE_CURSOR, SKINOFFSET_CURSOR);
 
        loadTooltips();
-       anim = spawnAnimHost();
-       main = spawnMainWindow(); main.configureMainWindow(main);
+       anim = NEW(AnimHost);
+       main = NEW(MainWindow); main.configureMainWindow(main);
        unloadTooltips();
 
        main.resizeNotify(main, '0 0 0', eX * conwidth + eY * conheight, '0 0 0', eX * conwidth + eY * conheight);
@@ -960,7 +964,10 @@ void m_setpointerfocus(entity wnd)
                        menuMousePos = focus.origin + 0.5 * focus.size;
                        menuMousePos.x *= 1 / conwidth;
                        menuMousePos.y *= 1 / conheight;
-                       if(wnd.focused) // why does this never happen?
+                       entity par = wnd.parent;
+                       if(par.focused)
+                               par.setFocus(par, wnd);
+                       if(wnd.focused)
                                m_focus_item_chain(wnd, focus);
                }
        }
index 00f6017aa06b3bdf4b2143fbd132cd4dac4885e3..020a65a20c318ac1cf8f1bbf5e1625759aa30cc2 100644 (file)
@@ -14,9 +14,6 @@
 
 #define localcmd cmd
 
-#define NULL (null_entity)
-#define world NULL
-
 // constants
 
 const int GAME_ISSERVER        = 1;
@@ -53,6 +50,8 @@ void postMenuDraw(); // this is run just after the menu is drawn (or not). Usefu
 
 void m_sync();
 
+void draw_reset_cropped();
+
 // sounds
 
 const string MENU_SOUND_CLEAR   = "sound/menu/clear.wav";
index 55af8adb84cfa4ddbba23e7eb60f4089be48a557..28b87ab7fca7e13d74ed3c6e12b3d04049c9cb41 100644 (file)
@@ -1,31 +1,11 @@
 #ifndef BASE_H
 #define BASE_H
 
-.string classname;
-entity Object_vtbl;
-.string vtblname;
-.entity vtblbase;
-// THIS LINE INTENTIONALLY LEFT BLANK
-entity spawnVtbl(entity e, entity b)
-{
-       entity v;
-       v = spawn();
-       copyentity(e, v);
-       v.vtblname = v.classname;
-       v.classname = "vtbl";
-       if(b)
-               v.vtblbase = b;
-       else
-               v.vtblbase = v;
-       return v;
-}
-entity spawnObject()
-{
-       entity e;
-       e = spawn();
-       e.classname = "Object";
-       if(!Object_vtbl)
-               Object_vtbl = spawnVtbl(e, null_entity);
-       return e;
-}
+#include "../../common/oo.qh"
+
+#include "../../common/util.qh"
+#include "../../dpdefs/keycodes.qh"
+
+#define world NULL
+
 #endif
diff --git a/qcsrc/menu/oo/classes.qc b/qcsrc/menu/oo/classes.qc
new file mode 100644 (file)
index 0000000..2170a83
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef CLASSES_H
+#define CLASSES_H
+#include "base.qh"
+
+#include "../classes.inc"
+#define IMPLEMENTATION
+#include "../classes.inc"
+
+#endif
diff --git a/qcsrc/menu/oo/implementation.qh b/qcsrc/menu/oo/implementation.qh
deleted file mode 100644 (file)
index 42a74be..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-#ifndef IMPLEMENTATION_H
-#define IMPLEMENTATION_H
-
-#ifndef INTERFACE
-#define INTERFACE
-#endif
-
-#ifndef IMPLEMENTATION
-#define IMPLEMENTATION
-#endif
-
-#ifdef CLASS
-#undef CLASS
-#undef EXTENDS
-#undef METHOD
-#undef ATTRIB
-#undef ATTRIBARRAY
-#undef ENDCLASS
-#undef SUPER
-#endif
-
-// for the constructor
-#define CLASS(cname)                       entity spawn##cname() { entity me;
-#define EXTENDS(base)                      me = spawn##base (); entity basevtbl; basevtbl = base##_vtbl;
-#define METHOD(cname,name,prototype)       me.name = cname##_##name;
-#define ATTRIB(cname,name,type,val)        me.name = val;
-#define ATTRIBARRAY(cname,name,type,cnt)
-#define ENDCLASS(cname)                    me.instanceOf##cname = 1; me.classname = #cname; if(!cname##_vtbl) cname##_vtbl = spawnVtbl(me, basevtbl); return me; }
-
-// for the implementation
-#define SUPER(cname) (cname##_vtbl.vtblbase)
-#endif
diff --git a/qcsrc/menu/oo/interface.qh b/qcsrc/menu/oo/interface.qh
deleted file mode 100644 (file)
index e24bb3f..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-#ifndef INTERFACE_H
-#define INTERFACE_H
-
-#ifndef INTERFACE
-#define INTERFACE
-#endif
-
-#ifdef IMPLEMENTATION
-#undef IMPLEMENTATION
-#endif
-
-#ifdef CLASS
-#undef CLASS
-#undef EXTENDS
-#undef METHOD
-#undef ATTRIB
-#undef ATTRIBARRAY
-#undef ENDCLASS
-#undef SUPER
-#endif
-
-#define CLASS(cname)                       entity spawn##cname(); entity cname##_vtbl;
-#define EXTENDS(base)
-#define METHOD(cname,name,prototype)       prototype cname##_##name; .prototype name;
-#define ATTRIB(cname,name,type,val)        .type name;
-#define ATTRIBARRAY(cname,name,type,cnt)   .type name[cnt];
-#define ENDCLASS(cname)                    .float instanceOf##cname;
-#define SUPER(cname)
-#endif
index a1fb38b1a12bec97dcc2026da161c364a779563b..2315616d1701bfc29dbdbe8cc7c6ce04e8433092 100644 (file)
@@ -4,15 +4,12 @@
 ../dpdefs/menudefs.qh
 ../dpdefs/keycodes.qh
 
-oo/interface.qh
-       classes.qc
-oo/implementation.qh
-       classes.qc
+oo/classes.qc
 
 draw.qc
 menu.qc
 
-command/menu_cmd.qc
+command/all.qc
 
 xonotic/util.qc
 
@@ -24,12 +21,10 @@ xonotic/util.qc
 ../common/urllib.qc
 ../common/util.qc
 
-../common/command/generic.qc
-../common/command/markup.qc
-../common/command/rpn.qc
+../common/items/all.qc
 
-../common/monsters/monsters.qc
+../common/monsters/all.qc
 
-../common/weapons/weapons.qc // TODO
+../common/weapons/all.qc // TODO
 
 ../warpzonelib/mathlib.qc
index ee0e76f399f7efbde625505d3b2fd59db7f84dae..d5e1f82eba4ab0ece3d7fb7995ec4b7838c455a3 100644 (file)
@@ -144,9 +144,6 @@ SKINBEGIN
        SKINFLOAT(ROWS_CREDITS, 20);
        SKINFLOAT(WIDTH_CREDITS, 0.5);
 
-       // item: crosshair button
-       SKINSTRING(GFX_CROSSHAIRBUTTON, "crosshairbutton");
-
        // item: cvar list
        SKINFLOAT(ALPHA_CVARLIST_SAVED, 1);
        SKINFLOAT(ALPHA_CVARLIST_TEMPORARY, 0.7);
@@ -178,6 +175,9 @@ SKINBEGIN
        SKINVECTOR(COLOR_CLEARBUTTON_F, '1 1 1');
        SKINVECTOR(COLOR_CLEARBUTTON_C, '1 1 1');
 
+       // item: gametype list
+       SKINFLOAT(BOOL_GAMETYPELIST_ICON_BLUR, 1);
+
        // item: key grabber
        SKINVECTOR(COLOR_KEYGRABBER_TITLES, '1 1 1');
        SKINFLOAT(ALPHA_KEYGRABBER_TITLES, 1);
@@ -191,6 +191,9 @@ SKINBEGIN
        SKINFLOAT(ALPHA_LISTBOX_WAITING, 0.5);
        SKINVECTOR(COLOR_LISTBOX_BACKGROUND, '0 0 0');
        SKINFLOAT(ALPHA_LISTBOX_BACKGROUND, 0.5);
+       SKINVECTOR(COLOR_LISTBOX_FOCUSED, '0 0 1');
+       SKINFLOAT(ALPHA_LISTBOX_FOCUSED, 0.7);
+       SKINFLOAT(FADEALPHA_LISTBOX_FOCUSED, 0.3);
 
        // item: map list
        SKINVECTOR(COLOR_MAPLIST_TITLE, '1 1 1');
@@ -211,11 +214,13 @@ SKINBEGIN
        SKINVECTOR(COLOR_MODELTITLE, '1 1 1');
        SKINFLOAT(ALPHA_MODELTITLE, 1);
 
-       // item: player name editor
+       // item: special character picker
        SKINVECTOR(COLOR_CHARMAP_CHAR, '1 1 1');
        SKINFLOAT(ALPHA_CHARMAP_CHAR, 1);
-       SKINVECTOR(COLOR_CHARMAP_FOCUS, '0 0 1');
-       SKINFLOAT(ALPHA_CHARMAP_FOCUS, 0.5);
+
+       // item: crosshair picker
+       SKINVECTOR(COLOR_CROSSHAIRPICKER_CROSSHAIR, '1 1 1');
+       SKINFLOAT(ALPHA_CROSSHAIRPICKER_CROSSHAIR, 1);
 
        // item: radio button
        SKINSTRING(GFX_RADIOBUTTON, "radiobutton");
@@ -245,7 +250,6 @@ SKINBEGIN
        SKINVECTOR(COLOR_SERVERLIST_FAVORITE, '1 1 1');
        SKINFLOAT(ALPHA_SERVERLIST_IMPOSSIBLE, 0.7);
        SKINVECTOR(COLOR_SERVERLIST_IMPOSSIBLE, '0.3 0.3 0.3');
-       SKINSTRING(GFX_SERVERLIST_ICON, "icon");
        SKINFLOAT(ALPHA_SERVERLIST_ICON_NONPURE, 0.5);
 
        // item: server info
index 84f9029c0f155d1317ed355209a5b88e9ae2ac6a..10c81e7ef34bbec061df61789857970764025c1f 100644 (file)
 #undef SKINFLOAT
 #undef SKINVECTOR
 
-#define SKINBEGIN void Skin_ApplySetting(string key, string value) { switch(key) {
-#define SKINVECTOR(name,def) case #name: SKIN##name = stov(value); break
-#define SKINFLOAT(name,def) case #name: SKIN##name = stof(value); break
+#define SKINBEGIN void Skin_ApplySetting(string key, string _value) { switch(key) {
+#define SKINVECTOR(name,def) case #name: SKIN##name = stov(_value); break
+#define SKINFLOAT(name,def) case #name: SKIN##name = stof(_value); break
 //#define SKINSTRING(name,def) case #name: break
-#define SKINSTRING(name,def) case #name: SKIN##name = strzone(value); break
+#define SKINSTRING(name,def) case #name: SKIN##name = strzone(_value); break
        // I know this leaks memory when skin is read multiple times. Screw it.
 #define SKINEND case "": break; case "//": break; default: dprint("Invalid key in skin file: ", key, "\n"); } }
 #include "skin-customizables.inc"
index a63189b63a850dc326e46216e7429f5d80ba98cb..07b6a074ceca2a341dba0c81976c0df3ab7c6046 100644 (file)
@@ -1,5 +1,7 @@
-#ifdef INTERFACE
-CLASS(XonoticBigButton) EXTENDS(XonoticButton)
+#ifndef BIGBUTTON_H
+#define BIGBUTTON_H
+#include "button.qc"
+CLASS(XonoticBigButton, XonoticButton)
        METHOD(XonoticBigButton, configureXonoticBigButton, void(entity, string, vector))
        ATTRIB(XonoticBigButton, image, string, SKINGFX_BUTTON_BIG)
        ATTRIB(XonoticBigButton, grayImage, string, SKINGFX_BUTTON_BIG_GRAY)
@@ -11,7 +13,7 @@ entity makeXonoticButton(string theText, vector theColor);
 entity makeXonoticBigButton(string theText, vector theColor)
 {
        entity me;
-       me = spawnXonoticBigButton();
+       me = NEW(XonoticBigButton);
        me.configureXonoticBigButton(me, theText, theColor);
        return me;
 }
index c96dd57a16afcc614fedff7ce68d5a65b6076182..6798d9b01b2602ba4cae85e78768788a6dde2467 100644 (file)
@@ -1,5 +1,7 @@
-#ifdef INTERFACE
-CLASS(XonoticBigCommandButton) EXTENDS(XonoticCommandButton)
+#ifndef BIGCOMMANDBUTTON_H
+#define BIGCOMMANDBUTTON_H
+#include "commandbutton.qc"
+CLASS(XonoticBigCommandButton, XonoticCommandButton)
        METHOD(XonoticBigCommandButton, configureXonoticBigCommandButton, void(entity, string, vector, string, float))
        ATTRIB(XonoticBigCommandButton, image, string, SKINGFX_BUTTON_BIG)
        ATTRIB(XonoticBigCommandButton, grayImage, string, SKINGFX_BUTTON_BIG_GRAY)
@@ -11,7 +13,7 @@ entity makeXonoticBigCommandButton(string theText, vector theColor, string theCo
 entity makeXonoticBigCommandButton(string theText, vector theColor, string theCommand, float theFlags)
 {
        entity me;
-       me = spawnXonoticBigCommandButton();
+       me = NEW(XonoticBigCommandButton);
        me.configureXonoticBigCommandButton(me, theText, theColor, theCommand, theFlags);
        return me;
 }
index cbc7c47c40acbb84a88f39c154b7299428559531..73518ef96ad3396471e4a3497e9203bf92d0104a 100644 (file)
@@ -1,5 +1,7 @@
-#ifdef INTERFACE
-CLASS(XonoticButton) EXTENDS(Button)
+#ifndef BUTTON_H
+#define BUTTON_H
+#include "../item/button.qc"
+CLASS(XonoticButton, Button)
        METHOD(XonoticButton, configureXonoticButton, void(entity, string, vector))
        ATTRIB(XonoticButton, fontSize, float, SKINFONTSIZE_NORMAL)
        ATTRIB(XonoticButton, image, string, SKINGFX_BUTTON)
@@ -20,7 +22,7 @@ entity makeXonoticButton(string theText, vector theColor);
 entity makeXonoticButton(string theText, vector theColor)
 {
        entity me;
-       me = spawnXonoticButton();
+       me = NEW(XonoticButton);
        me.configureXonoticButton(me, theText, theColor);
        return me;
 }
index 885c89183cf548543cf7af27a2479ff355c60e08..e30c038a01b5b14e2dea5e241698ca1e05b0c5fc 100644 (file)
@@ -1,11 +1,13 @@
 #include "../../common/campaign_common.qh"
 
-#ifdef INTERFACE
-CLASS(XonoticCampaignList) EXTENDS(XonoticListBox)
+#ifndef CAMPAIGN_H
+#define CAMPAIGN_H
+#include "listbox.qc"
+CLASS(XonoticCampaignList, XonoticListBox)
        METHOD(XonoticCampaignList, configureXonoticCampaignList, void(entity))
        ATTRIB(XonoticCampaignList, rowsPerItem, float, 10)
        METHOD(XonoticCampaignList, draw, void(entity))
-       METHOD(XonoticCampaignList, drawListBoxItem, void(entity, float, vector, float))
+       METHOD(XonoticCampaignList, drawListBoxItem, void(entity, int, vector, bool, bool))
        METHOD(XonoticCampaignList, doubleClickListBoxItem, void(entity, float, vector))
        METHOD(XonoticCampaignList, resizeNotify, void(entity, vector, vector, vector, vector))
        METHOD(XonoticCampaignList, setSelected, void(entity, float))
@@ -50,8 +52,9 @@ string campaign_longdesc_wrapped[CAMPAIGN_MAX_ENTRIES];
 
 void rewrapCampaign(float w, float l0, float emptyheight, vector theFontSize)
 {
-       float i, j;
-       float n, l;
+       int i, j;
+       int n;
+       float l;
        string r, s;
        for(i = 0; i < campaign_entries; ++i)
        {
@@ -91,7 +94,7 @@ void rewrapCampaign(float w, float l0, float emptyheight, vector theFontSize)
 entity makeXonoticCampaignList()
 {
        entity me;
-       me = spawnXonoticCampaignList();
+       me = NEW(XonoticCampaignList);
        me.configureXonoticCampaignList(me);
        return me;
 }
@@ -236,7 +239,7 @@ void XonoticCampaignList_doubleClickListBoxItem(entity me, float i, vector where
 {
        CampaignList_LoadMap(me, me);
 }
-void XonoticCampaignList_drawListBoxItem(entity me, float i, vector absSize, float isSelected)
+void XonoticCampaignList_drawListBoxItem(entity me, int i, vector absSize, bool isSelected, bool isFocused)
 {
        string s;
        vector theColor;
@@ -262,6 +265,11 @@ void XonoticCampaignList_drawListBoxItem(entity me, float i, vector absSize, flo
 
        if(isSelected)
                draw_Fill('0 0 0', '1 1 0', SKINCOLOR_LISTBOX_SELECTED, SKINALPHA_LISTBOX_SELECTED);
+       else if(isFocused)
+       {
+               me.focusedItemAlpha = getFadedAlpha(me.focusedItemAlpha, SKINALPHA_LISTBOX_FOCUSED, SKINFADEALPHA_LISTBOX_FOCUSED);
+               draw_Fill('0 0 0', '1 1 0', SKINCOLOR_LISTBOX_FOCUSED, me.focusedItemAlpha);
+       }
 
        if(draw_PictureSize(strcat("/maps/", campaign_mapname[i])) == '0 0 0')
                draw_Picture(me.columnPreviewOrigin * eX, "nopreview_map", me.columnPreviewSize * eX + eY, '1 1 1', theAlpha);
index 0ba72a5d83404ff3fee24deb3d9d93aac7fccb36..747d1f03b4568a4a820bdc35cedb170b67570a19 100644 (file)
@@ -1,32 +1,27 @@
-#ifdef INTERFACE
-CLASS(XonoticCharmap) EXTENDS(Item)
+#ifndef CHARMAP_H
+#define CHARMAP_H
+#include "picker.qc"
+CLASS(XonoticCharmap, XonoticPicker)
        METHOD(XonoticCharmap, configureXonoticCharmap, void(entity, entity))
-       METHOD(XonoticCharmap, mousePress, float(entity, vector))
-       METHOD(XonoticCharmap, mouseRelease, float(entity, vector))
-       METHOD(XonoticCharmap, mouseMove, float(entity, vector))
-       METHOD(XonoticCharmap, mouseDrag, float(entity, vector))
-       METHOD(XonoticCharmap, keyDown, float(entity, float, float, float))
        METHOD(XonoticCharmap, focusLeave, void(entity))
        METHOD(XonoticCharmap, resizeNotify, void(entity, vector, vector, vector, vector))
-       METHOD(XonoticCharmap, draw, void(entity))
-       ATTRIB(XonoticCharmap, focusable, float, 1)
-
-       METHOD(XonoticCharmap, moveFocus, void(entity, vector, vector))
-       METHOD(XonoticCharmap, enterChar, void(entity))
+       METHOD(XonoticCharmap, keyDown, float(entity, float, float, float))
        ATTRIB(XonoticCharmap, inputBox, entity, NULL)
        ATTRIB(XonoticCharmap, realFontSize, vector, '0 0 0')
-       ATTRIB(XonoticCharmap, realCellSize, vector, '0 0 0')
-       ATTRIB(XonoticCharmap, focusedCell, vector, '-1 -1 0')
-       ATTRIB(XonoticCharmap, previouslyFocusedCell, vector, '-1 -1 0')
+
+       ATTRIB(XonoticCharmap, rows, float, 10)
+       ATTRIB(XonoticCharmap, columns, float, 14)
+
+       METHOD(XonoticCharmap, cellSelect, void(entity, vector))
+       METHOD(XonoticCharmap, cellIsValid, bool(entity, vector))
+       METHOD(XonoticCharmap, cellDraw, void(entity, vector, vector))
+       METHOD(XonoticCharmap, charOffset, vector)
 ENDCLASS(XonoticCharmap)
 entity makeXonoticCharmap(entity controlledInputBox);
 #endif
 
 #ifdef IMPLEMENTATION
 
-const float CHARMAP_COLS = 14;
-const float CHARMAP_ROWS = 10;
-
 string CHARMAP =
        "★◆■▮▰▬◣◤◥◢◀▲▶▼"
        "🌍🌎🌏🚀🌌👽🔫⌖❇❈←↑→↓"
@@ -44,11 +39,11 @@ string CHARMAP =
        "\xEE\x83\x8F\xEE\x83\x90\xEE\x83\x91\xEE\x83\x92\xEE\x83\x93\xEE\x83\x94\xEE\x83\x95"
        "\xEE\x83\x96\xEE\x83\x97\xEE\x83\x98\xEE\x83\x99\xEE\x83\x9A\xEE\x81\x9B\xEE\x81\x9D";
 
-string charmap_cellToChar(vector cell)
+string charmap_cellToChar(entity me, vector cell)
 {
-       string character = substring(CHARMAP, cell.y * CHARMAP_COLS + cell.x, 1);
+       string character = substring(CHARMAP, cell.y * me.columns + cell.x, 1);
 
-       if (character != " ")
+       if(character != " ")
                return character;
        else
                return "";
@@ -57,7 +52,7 @@ string charmap_cellToChar(vector cell)
 entity makeXonoticCharmap(entity controlledInputBox)
 {
        entity me;
-       me = spawnXonoticCharmap();
+       me = NEW(XonoticCharmap);
        me.configureXonoticCharmap(me, controlledInputBox);
        return me;
 }
@@ -65,7 +60,7 @@ entity makeXonoticCharmap(entity controlledInputBox)
 void XonoticCharmap_configureXonoticCharmap(entity me, entity controlledInputBox)
 {
        me.inputBox = controlledInputBox;
-       me.realCellSize = eX / CHARMAP_COLS + eY / CHARMAP_ROWS;
+       me.configureXonoticPicker(me);
 }
 
 void XonoticCharmap_resizeNotify(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize)
@@ -88,153 +83,38 @@ void XonoticCharmap_resizeNotify(entity me, vector relOrigin, vector relSize, ve
 
        if(me.realFontSize.x > maxFontWidth || me.realFontSize.y > maxFontHeight)
                me.realFontSize = eX * maxFontWidth + eY * maxFontHeight;
-}
-
-float XonoticCharmap_mouseMove(entity me, vector coords)
-{
-       me.focusedCell_x = floor(coords.x * CHARMAP_COLS);
-       me.focusedCell_y = floor(coords.y * CHARMAP_ROWS);
 
-       if(me.focusedCell.x < 0 || me.focusedCell.y < 0 ||
-          me.focusedCell.x >= CHARMAP_COLS || me.focusedCell.y >= CHARMAP_ROWS)
-       {
-               me.focusedCell = '-1 -1 0';
-               return 0;
-       }
-
-       return 1;
+       me.charOffset = eX * me.realCellSize.x / 2 + eY * ((me.realCellSize.y - me.realFontSize.y) / 2);
 }
 
-float XonoticCharmap_mouseDrag(entity me, vector coords)
-{
-       return me.mouseMove(me, coords);
-}
-
-float XonoticCharmap_mousePress(entity me, vector coords)
-{
-       me.mouseMove(me, coords);
-
-       if(me.focusedCell.x >= 0)
-       {
-               me.pressed = 1;
-               me.previouslyFocusedCell = me.focusedCell;
-       }
-
-       return 1;
-}
-
-float XonoticCharmap_mouseRelease(entity me, vector coords)
+float XonoticCharmap_keyDown(entity me, float key, float ascii, float shift)
 {
-       if(!me.pressed)
-               return 0;
-
-       me.mouseMove(me, coords);
-
-       if(me.focusedCell == me.previouslyFocusedCell)
-               me.enterChar(me);
-
-       me.pressed = 0;
-       return 1;
+       if(SUPER(XonoticCharmap).keyDown(me, key, ascii, shift))
+               return 1;
+       return me.inputBox.keyDown(me.inputBox, key, ascii, shift);
 }
 
-float XonoticCharmap_keyDown(entity me, float key, float ascii, float shift)
+void XonoticCharmap_cellSelect(entity me, vector cell)
 {
-       switch(key)
-       {
-               case K_LEFTARROW:
-               case K_KP_LEFTARROW:
-                       me.moveFocus(me, me.focusedCell, '-1 0 0');
-                       return 1;
-               case K_RIGHTARROW:
-               case K_KP_RIGHTARROW:
-                       me.moveFocus(me, me.focusedCell, '1 0 0');
-                       return 1;
-               case K_UPARROW:
-               case K_KP_UPARROW:
-                       me.moveFocus(me, me.focusedCell, '0 -1 0');
-                       return 1;
-               case K_DOWNARROW:
-               case K_KP_DOWNARROW:
-                       me.moveFocus(me, me.focusedCell, '0 1 0');
-                       return 1;
-               case K_HOME:
-               case K_KP_HOME:
-                       me.focusedCell = '0 0 0';
-                       return 1;
-               case K_END:
-               case K_KP_END:
-                       me.focusedCell_x = CHARMAP_COLS - 1;
-                       me.focusedCell_y = CHARMAP_ROWS - 1;
-                       return 1;
-               case K_ENTER:
-               case K_KP_ENTER:
-               case K_INS:
-               case K_KP_INS:
-                       me.enterChar(me);
-                       return 1;
-               default:
-                       return me.inputBox.keyDown(me.inputBox, key, ascii, shift);
-       }
+       string character = charmap_cellToChar(me, cell);
+       if(character != "")
+               me.inputBox.enterText(me.inputBox, character);
 }
 
-void XonoticCharmap_moveFocus(entity me, vector initialCell, vector step)
+bool XonoticCharmap_cellIsValid(entity me, vector cell)
 {
-       me.focusedCell_x = mod(me.focusedCell.x + step.x + CHARMAP_COLS, CHARMAP_COLS);
-       me.focusedCell_y = mod(me.focusedCell.y + step.y + CHARMAP_ROWS, CHARMAP_ROWS);
-
-       if(me.focusedCell != initialCell) // Recursion break
-               if(charmap_cellToChar(me.focusedCell) == "")
-                       me.moveFocus(me, initialCell, step);
+       if(charmap_cellToChar(me, cell) == "")
+               return false;
+       return true;
 }
 
-void XonoticCharmap_enterChar(entity me)
+void XonoticCharmap_cellDraw(entity me, vector cell, vector cellPos)
 {
-       string character = charmap_cellToChar(me.focusedCell);
-       if(character != "")
-               me.inputBox.enterText(me.inputBox, character);
+       draw_CenterText(cellPos + me.charOffset, charmap_cellToChar(me, cell), me.realFontSize, SKINCOLOR_CHARMAP_CHAR, SKINALPHA_CHARMAP_CHAR, 0);
 }
 
 void XonoticCharmap_focusLeave(entity me)
 {
        me.inputBox.saveCvars(me.inputBox);
 }
-
-void XonoticCharmap_draw(entity me)
-{
-       string character;
-       vector cell, cellPos, charPos;
-       cell = '0 0 0';
-       cellPos = '0 0 0';
-       charPos = '0 0 0';
-
-       float CHAR_OFFSET_X = me.realCellSize.x / 2;
-       float CHAR_OFFSET_Y = (me.realCellSize.y - me.realFontSize.y) / 2;
-
-       for(cell_y = 0; cell.y < CHARMAP_ROWS; ++cell.y)
-       {
-               charPos_y = cell.y / CHARMAP_ROWS + CHAR_OFFSET_Y;
-               for(cell_x = 0; cell.x < CHARMAP_COLS; ++cell.x)
-               {
-                       character = charmap_cellToChar(cell);
-
-                       if(character == "")
-                               continue;
-
-                       // Draw focused cell
-                       if(cell == me.focusedCell && me.focused)
-                       {
-                               if(!me.pressed || me.focusedCell == me.previouslyFocusedCell)
-                               {
-                                       cellPos_x = mod(me.focusedCell.x, CHARMAP_COLS) / CHARMAP_COLS;
-                                       cellPos_y = mod(me.focusedCell.y, CHARMAP_ROWS) / CHARMAP_ROWS;
-                                       draw_Fill(cellPos, me.realCellSize, SKINCOLOR_CHARMAP_FOCUS, SKINALPHA_CHARMAP_FOCUS);
-                               }
-                       }
-
-                       // Draw character
-                       charPos_x = cell.x / CHARMAP_COLS + CHAR_OFFSET_X;
-                       draw_CenterText(charPos, character, me.realFontSize, SKINCOLOR_CHARMAP_CHAR, SKINALPHA_CHARMAP_CHAR, 0);
-               }
-       }
-}
 #endif
index 631a430dcc455947d8c63e83e0e24297ba5dd7ae..65db0f5a73bbcf4f0223998d1d07b0b30dcd003f 100644 (file)
@@ -1,5 +1,7 @@
-#ifdef INTERFACE
-CLASS(XonoticCheckBox) EXTENDS(CheckBox)
+#ifndef CHECKBOX_H
+#define CHECKBOX_H
+#include "../item/checkbox.qc"
+CLASS(XonoticCheckBox, CheckBox)
        METHOD(XonoticCheckBox, configureXonoticCheckBox, void(entity, float, float, string, string))
        METHOD(XonoticCheckBox, setChecked, void(entity, float))
        ATTRIB(XonoticCheckBox, fontSize, float, SKINFONTSIZE_NORMAL)
@@ -53,7 +55,7 @@ entity makeXonoticCheckBox(float isInverted, string theCvar, string theText)
 entity makeXonoticCheckBoxEx(float theYesValue, float theNoValue, string theCvar, string theText)
 {
        entity me;
-       me = spawnXonoticCheckBox();
+       me = NEW(XonoticCheckBox);
        me.configureXonoticCheckBox(me, theYesValue, theNoValue, theCvar, theText);
        return me;
 }
index e3043184a44f35cd2676375466fff57ec9c91014..9cce51d828fe2b99c3749e954b06e20b6a1a2f4a 100644 (file)
@@ -1,5 +1,7 @@
-#ifdef INTERFACE
-CLASS(XonoticSliderCheckBox) EXTENDS(CheckBox)
+#ifndef CHECKBOX_SLIDER_INVALID_H
+#define CHECKBOX_SLIDER_INVALID_H
+#include "../item/checkbox.qc"
+CLASS(XonoticSliderCheckBox, CheckBox)
        METHOD(XonoticSliderCheckBox, configureXonoticSliderCheckBox, void(entity, float, float, entity, string))
        METHOD(XonoticSliderCheckBox, setChecked, void(entity, float))
        METHOD(XonoticSliderCheckBox, draw, void(entity))
@@ -26,7 +28,7 @@ entity makeXonoticSliderCheckBox(float, float, entity, string);
 entity makeXonoticSliderCheckBox(float theOffValue, float isInverted, entity theControlledSlider, string theText)
 {
        entity me;
-       me = spawnXonoticSliderCheckBox();
+       me = NEW(XonoticSliderCheckBox);
        me.configureXonoticSliderCheckBox(me, theOffValue, isInverted, theControlledSlider, theText);
        return me;
 }
index aeda757f0e83718cbca511cace58aa2c9fc04d85..2efa1a102b67a3dde096c51b2b3ec51c852a0e22 100644 (file)
@@ -1,5 +1,7 @@
-#ifdef INTERFACE
-CLASS(XonoticCheckBoxString) EXTENDS(CheckBox)
+#ifndef CHECKBOX_STRING_H
+#define CHECKBOX_STRING_H
+#include "../item/checkbox.qc"
+CLASS(XonoticCheckBoxString, CheckBox)
        METHOD(XonoticCheckBoxString, configureXonoticCheckBoxString, void(entity, string, string, string, string))
        METHOD(XonoticCheckBoxString, setChecked, void(entity, float))
        ATTRIB(XonoticCheckBoxString, fontSize, float, SKINFONTSIZE_NORMAL)
@@ -27,7 +29,7 @@ entity makeXonoticCheckBoxString(string, string, string, string);
 entity makeXonoticCheckBoxString(string theYesValue, string theNoValue, string theCvar, string theText)
 {
        entity me;
-       me = spawnXonoticCheckBoxString();
+       me = NEW(XonoticCheckBoxString);
        me.configureXonoticCheckBoxString(me, theYesValue, theNoValue, theCvar, theText);
        return me;
 }
index bcbdfee8db9d3585a4aa4e51567492207cd392bc..950661d73dc8d33699eccbca95191b213626872a 100644 (file)
@@ -1,5 +1,7 @@
-#ifdef INTERFACE
-CLASS(XonoticColorButton) EXTENDS(RadioButton)
+#ifndef COLORBUTTON_H
+#define COLORBUTTON_H
+#include "../item/radiobutton.qc"
+CLASS(XonoticColorButton, RadioButton)
        METHOD(XonoticColorButton, configureXonoticColorButton, void(entity, float, float, float))
        METHOD(XonoticColorButton, setChecked, void(entity, float))
        METHOD(XonoticColorButton, draw, void(entity))
@@ -21,7 +23,7 @@ entity makeXonoticColorButton(float, float, float);
 entity makeXonoticColorButton(float theGroup, float theColor, float theValue)
 {
        entity me;
-       me = spawnXonoticColorButton();
+       me = NEW(XonoticColorButton);
        me.configureXonoticColorButton(me, theGroup, theColor, theValue);
        return me;
 }
index f16ab0ebd45fd0a16a0f941e06cfb9766941fe69..450c5fb29e1d6cf9f8770e0a271a49244e0bad4f 100644 (file)
@@ -1,5 +1,7 @@
-#ifdef INTERFACE
-CLASS(XonoticColorpicker) EXTENDS(Image)
+#ifndef COLORPICKER_H
+#define COLORPICKER_H
+#include "../item/image.qc"
+CLASS(XonoticColorpicker, Image)
        METHOD(XonoticColorpicker, configureXonoticColorpicker, void(entity, entity))
        METHOD(XonoticColorpicker, mousePress, float(entity, vector))
        METHOD(XonoticColorpicker, mouseRelease, float(entity, vector))
@@ -19,7 +21,7 @@ entity makeXonoticColorpicker(entity theTextbox);
 entity makeXonoticColorpicker(entity theTextbox)
 {
        entity me;
-       me = spawnXonoticColorpicker();
+       me = NEW(XonoticColorpicker);
        me.configureXonoticColorpicker(me, theTextbox);
        return me;
 }
index 458a72c01a6fe1dd47ced6e06c2dffb4ddfe41e3..0695f057ea034d625b7e5804e38aa85b81480dc4 100644 (file)
@@ -1,12 +1,14 @@
-#ifdef INTERFACE
-CLASS(XonoticColorpickerString) EXTENDS(Image)
+#ifndef COLORPICKER_STRING_H
+#define COLORPICKER_STRING_H
+#include "../item/image.qc"
+CLASS(XonoticColorpickerString, Image)
        METHOD(XonoticColorpickerString, configureXonoticColorpickerString, void(entity, string, string))
        METHOD(XonoticColorpickerString, mousePress, float(entity, vector))
        METHOD(XonoticColorpickerString, mouseRelease, float(entity, vector))
        METHOD(XonoticColorpickerString, mouseDrag, float(entity, vector))
        ATTRIB(XonoticColorpickerString, cvarName, string, string_null)
-       METHOD(XonoticColorPickerString, loadCvars, void(entity))
-       METHOD(XonoticColorPickerString, saveCvars, void(entity))
+       METHOD(XonoticColorpickerString, loadCvars, void(entity))
+       METHOD(XonoticColorpickerString, saveCvars, void(entity))
        ATTRIB(XonoticColorpickerString, prevcoords, vector, '0 0 0')
        ATTRIB(XonoticColorpickerString, image, string, SKINGFX_COLORPICKER)
        ATTRIB(XonoticColorpickerString, imagemargin, vector, SKINMARGIN_COLORPICKER)
@@ -21,7 +23,7 @@ entity makeXonoticColorpickerString(string theCvar, string theDefaultCvar);
 entity makeXonoticColorpickerString(string theCvar, string theDefaultCvar)
 {
        entity me;
-       me = spawnXonoticColorpickerString();
+       me = NEW(XonoticColorpickerString);
        me.configureXonoticColorpickerString(me, theCvar, theDefaultCvar);
        return me;
 }
@@ -38,7 +40,7 @@ void XonoticColorpickerString_configureXonoticColorpickerString(entity me, strin
        }
 }
 
-void XonoticColorPickerString_loadCvars(entity me)
+void XonoticColorpickerString_loadCvars(entity me)
 {
        if (!me.cvarName)
                return;
@@ -55,7 +57,7 @@ void XonoticColorPickerString_loadCvars(entity me)
                me.prevcoords = color_hslimage(stov(cvar_string(me.cvarName)), me.imagemargin);
 }
 
-void XonoticColorPickerString_saveCvars(entity me)
+void XonoticColorpickerString_saveCvars(entity me)
 {
        if (!me.cvarName)
                return;
index 8ee4e7de3a75503215591c49e643a68768c580bf..afea74cb47d80b0e618c266e24c5f39e13105640 100644 (file)
@@ -4,8 +4,10 @@
 //# define COMMANDBUTTON_REVERT 4
 #endif
 
-#ifdef INTERFACE
-CLASS(XonoticCommandButton) EXTENDS(XonoticButton)
+#ifndef COMMANDBUTTON_H
+#define COMMANDBUTTON_H
+#include "button.qc"
+CLASS(XonoticCommandButton, XonoticButton)
        METHOD(XonoticCommandButton, configureXonoticCommandButton, void(entity, string, vector, string, float))
        ATTRIB(XonoticCommandButton, onClickCommand, string, string_null)
        ATTRIB(XonoticCommandButton, flags, float, 0)
@@ -17,7 +19,7 @@ entity makeXonoticCommandButton(string theText, vector theColor, string theComma
 entity makeXonoticCommandButton(string theText, vector theColor, string theCommand, float theFlags)
 {
        entity me;
-       me = spawnXonoticCommandButton();
+       me = NEW(XonoticCommandButton);
        me.configureXonoticCommandButton(me, theText, theColor, theCommand, theFlags);
        return me;
 }
index 67848f9144978dd87bce3648aed4e65ed336c90b..57320a018240e3ac47bf8eae814280674004b705 100644 (file)
@@ -1,9 +1,11 @@
-#ifdef INTERFACE
-CLASS(XonoticCreditsList) EXTENDS(XonoticListBox)
+#ifndef CREDITS_H
+#define CREDITS_H
+#include "listbox.qc"
+CLASS(XonoticCreditsList, XonoticListBox)
        METHOD(XonoticCreditsList, configureXonoticCreditsList, void(entity))
        ATTRIB(XonoticCreditsList, rowsPerItem, float, 1)
        METHOD(XonoticCreditsList, draw, void(entity))
-       METHOD(XonoticCreditsList, drawListBoxItem, void(entity, float, vector, float))
+       METHOD(XonoticCreditsList, drawListBoxItem, void(entity, int, vector, bool, bool))
        METHOD(XonoticCreditsList, resizeNotify, void(entity, vector, vector, vector, vector))
        METHOD(XonoticCreditsList, keyDown, float(entity, float, float, float))
        METHOD(XonoticCreditsList, destroy, void(entity))
@@ -13,7 +15,7 @@ CLASS(XonoticCreditsList) EXTENDS(XonoticListBox)
        ATTRIB(XonoticCreditsList, bufferIndex, float, 0)
        ATTRIB(XonoticCreditsList, scrolling, float, 0)
 
-       ATTRIB(XonoticListBox, alphaBG, float, 0)
+       ATTRIB(XonoticCreditsList, alphaBG, float, 0)
 ENDCLASS(XonoticCreditsList)
 entity makeXonoticCreditsList();
 #endif
@@ -22,7 +24,7 @@ entity makeXonoticCreditsList();
 entity makeXonoticCreditsList()
 {
        entity me;
-       me = spawnXonoticCreditsList();
+       me = NEW(XonoticCreditsList);
        me.configureXonoticCreditsList(me);
        return me;
 }
@@ -57,7 +59,7 @@ void XonoticCreditsList_resizeNotify(entity me, vector relOrigin, vector relSize
        me.realFontSize_x = me.fontSize / (absSize.x * (1 - me.controlWidth));
        me.realUpperMargin = 0.5 * (1 - me.realFontSize.y);
 }
-void XonoticCreditsList_drawListBoxItem(entity me, float i, vector absSize, float isSelected)
+void XonoticCreditsList_drawListBoxItem(entity me, int i, vector absSize, bool isSelected, bool isFocused)
 {
        // layout: Ping, Credits name, Map name, NP, TP, MP
        string s;
diff --git a/qcsrc/menu/xonotic/crosshairbutton.qc b/qcsrc/menu/xonotic/crosshairbutton.qc
deleted file mode 100644 (file)
index 3b562cb..0000000
+++ /dev/null
@@ -1,128 +0,0 @@
-#ifdef INTERFACE
-CLASS(XonoticCrosshairButton) EXTENDS(RadioButton)
-       METHOD(XonoticCrosshairButton, configureXonoticCrosshairButton, void(entity, float, float))
-       METHOD(XonoticCrosshairButton, setChecked, void(entity, float))
-       METHOD(XonoticCrosshairButton, draw, void(entity))
-       ATTRIB(XonoticCrosshairButton, fontSize, float, SKINFONTSIZE_NORMAL)
-       ATTRIB(XonoticCrosshairButton, image, string, SKINGFX_CROSSHAIRBUTTON)
-
-       ATTRIB(XonoticCrosshairButton, useDownAsChecked, float, 1)
-       ATTRIB(XonoticCrosshairButton, src3, string, string_null)
-       ATTRIB(XonoticCrosshairButton, src4, string, string_null)
-
-       ATTRIB(XonoticCrosshairButton, cvarName, string, string_null)
-       ATTRIB(XonoticCrosshairButton, cvarValueFloat, float, 0)
-       METHOD(XonoticCrosshairButton, loadCvars, void(entity))
-       METHOD(XonoticCrosshairButton, saveCvars, void(entity))
-ENDCLASS(XonoticCrosshairButton)
-entity makeXonoticCrosshairButton(float, float);
-#endif
-
-#ifdef IMPLEMENTATION
-entity makeXonoticCrosshairButton(float theGroup, float theCrosshair)
-{
-       entity me;
-       me = spawnXonoticCrosshairButton();
-       me.configureXonoticCrosshairButton(me, theGroup, theCrosshair);
-       return me;
-}
-void XonoticCrosshairButton_configureXonoticCrosshairButton(entity me, float theGroup, float theCrosshair)
-{
-       me.cvarName = "crosshair";
-       me.cvarValueFloat = theCrosshair;
-       me.loadCvars(me);
-       me.configureRadioButton(me, string_null, me.fontSize, me.image, theGroup, 0);
-       me.srcMulti = 1;
-       if(me.cvarValueFloat == -1)
-               me.src3 = strzone(strcat("/gfx/crosshair", cvar_string("crosshair")));
-       else
-               me.src3 = strzone(strcat("/gfx/crosshair", ftos(me.cvarValueFloat)));
-       me.src4 = "/gfx/crosshairdot";
-}
-void XonoticCrosshairButton_setChecked(entity me, float val)
-{
-       if(me.cvarValueFloat != -1) // preview shouldn't work as a button
-       if(val != me.checked)
-       {
-               me.checked = val;
-               me.saveCvars(me);
-       }
-}
-void XonoticCrosshairButton_loadCvars(entity me)
-{
-       if (!me.cvarName)
-               return;
-
-       me.checked = (cvar(me.cvarName) == me.cvarValueFloat);
-}
-void XonoticCrosshairButton_saveCvars(entity me)
-{
-       if (!me.cvarName)
-               return;
-
-       if(me.checked)
-               cvar_set(me.cvarName, ftos(me.cvarValueFloat));
-       // TODO on an apply button, read _cl_color and execute the color command for it
-}
-void XonoticCrosshairButton_draw(entity me)
-{
-       vector sz, rgb;
-       float a;
-
-
-       if(me.cvarValueFloat == -1)
-       {
-               rgb = stov(cvar_string("crosshair_color"));
-               a = cvar("crosshair_alpha");
-       }
-       else if(me.checked || me.focused)
-       {
-               a = 1;
-               rgb = '1 1 1';
-       }
-       else
-       {
-               a = me.disabledAlpha;
-               rgb = '1 1 1';
-       }
-
-       if(me.cvarValueFloat == -1) // update the preview if this is the preview button
-       {
-               if(me.src3)
-                       strunzone(me.src3);
-               me.src3 = strzone(strcat("/gfx/crosshair", cvar_string("crosshair")));
-               me.focused = 1;
-               me.checked = 0;
-       }
-
-       SUPER(XonoticCrosshairButton).draw(me);
-
-       sz = draw_PictureSize(me.src3);
-       sz = globalToBoxSize(sz, me.size);
-       if(me.cvarValueFloat == -1)
-       {
-               sz = sz * cvar("crosshair_size"); // (6 * '1 1 0' + ...) * 0.08 here to make visible size changes happen also at bigger sizes
-               /*
-               if(sz_x > 0.95)
-                       sz = sz * (0.95 / sz_x);
-               if(sz_y > 0.95)
-                       sz = sz * (0.95 / sz_y);
-               */
-       }
-       else // show the crosshair picker at full size
-       {
-               sz = sz * (0.95 / sz.x);
-               if(sz.y > 0.95)
-                       sz = sz * (0.95 / sz.y);
-       }
-
-       draw_Picture('0.5 0.5 0' - 0.5 * sz, me.src3, sz, rgb, a);
-       if(cvar("crosshair_dot"))
-       {
-               if(cvar("crosshair_dot_color_custom") && (cvar_string("crosshair_dot_color") != "0"))
-                       rgb = stov(cvar_string("crosshair_dot_color"));
-
-               draw_Picture('0.5 0.5 0' - 0.5 * sz * cvar("crosshair_dot_size"), me.src4, sz * cvar("crosshair_dot_size"), rgb, a * cvar("crosshair_dot_alpha"));
-       }
-}
-#endif
diff --git a/qcsrc/menu/xonotic/crosshairpicker.qc b/qcsrc/menu/xonotic/crosshairpicker.qc
new file mode 100644 (file)
index 0000000..8922e7f
--- /dev/null
@@ -0,0 +1,79 @@
+#ifndef CROSSHAIRPICKER_H
+#define CROSSHAIRPICKER_H
+#include "picker.qc"
+CLASS(XonoticCrosshairPicker, XonoticPicker)
+       METHOD(XonoticCrosshairPicker, configureXonoticCrosshairPicker, void(entity))
+
+       ATTRIB(XonoticCrosshairPicker, rows, float, 3)
+       ATTRIB(XonoticCrosshairPicker, columns, float, 12)
+
+       METHOD(XonoticCrosshairPicker, cellSelect, void(entity, vector))
+       METHOD(XonoticCrosshairPicker, cellIsValid, bool(entity, vector))
+       METHOD(XonoticCrosshairPicker, cellDraw, void(entity, vector, vector))
+ENDCLASS(XonoticCrosshairPicker)
+entity makeXonoticCrosshairPicker();
+#endif
+
+#ifdef IMPLEMENTATION
+
+string crosshairpicker_cellToCrosshair(entity me, vector cell)
+{
+       if(cell.x < 0 || cell.x >= me.columns || cell.y < 0 || cell.y >= me.rows)
+               return "";
+       return ftos(31 + cell.y * me.columns + cell.x);
+}
+
+vector crosshairpicker_crosshairToCell(entity me, string crosshair_str)
+{
+       float crosshair = stof(crosshair_str) - 31;
+       if(crosshair - floor(crosshair) > 0)
+               return '-1 -1 0';
+       return mod(crosshair, me.columns) * eX + floor(crosshair / me.columns) * eY;
+}
+
+entity makeXonoticCrosshairPicker()
+{
+       entity me;
+       me = NEW(XonoticCrosshairPicker);
+       me.configureXonoticCrosshairPicker(me);
+       return me;
+}
+
+void XonoticCrosshairPicker_configureXonoticCrosshairPicker(entity me)
+{
+       me.configureXonoticPicker(me);
+       SUPER(XonoticCrosshairPicker).cellSelect(me, crosshairpicker_crosshairToCell(me, cvar_string("crosshair")));
+}
+
+void XonoticCrosshairPicker_cellSelect(entity me, vector cell)
+{
+       cvar_set("crosshair", crosshairpicker_cellToCrosshair(me, me.focusedCell));
+       SUPER(XonoticCrosshairPicker).cellSelect(me, me.focusedCell);
+}
+
+bool XonoticCrosshairPicker_cellIsValid(entity me, vector cell)
+{
+       if(crosshairpicker_cellToCrosshair(me, cell) == "")
+               return false;
+       return true;
+}
+
+void XonoticCrosshairPicker_cellDraw(entity me, vector cell, vector cellPos)
+{
+       vector sz;
+       string cross = strcat("/gfx/crosshair", crosshairpicker_cellToCrosshair(me, cell));
+       sz = draw_PictureSize(cross);
+       sz = globalToBoxSize(sz, me.size);
+
+       float ar = sz.x / sz.y;
+       sz.x = me.realCellSize.x;
+       sz.y = sz.x / ar;
+       sz = sz * 0.95;
+
+       vector crosshairPos = cellPos + 0.5 * me.realCellSize;
+       draw_Picture(crosshairPos - 0.5 * sz, cross, sz, SKINCOLOR_CROSSHAIRPICKER_CROSSHAIR, SKINALPHA_CROSSHAIRPICKER_CROSSHAIR);
+
+       if(cvar("crosshair_dot"))
+               draw_Picture(crosshairPos - 0.5 * sz * cvar("crosshair_dot_size"), "/gfx/crosshairdot", sz * cvar("crosshair_dot_size"), SKINCOLOR_CROSSHAIRPICKER_CROSSHAIR, SKINALPHA_CROSSHAIRPICKER_CROSSHAIR);
+}
+#endif
diff --git a/qcsrc/menu/xonotic/crosshairpreview.qc b/qcsrc/menu/xonotic/crosshairpreview.qc
new file mode 100644 (file)
index 0000000..f8de857
--- /dev/null
@@ -0,0 +1,62 @@
+#ifndef CROSSHAIRPREVIEW_H
+#define CROSSHAIRPREVIEW_H
+#include "../item.qc"
+CLASS(XonoticCrosshairPreview, Item)
+       METHOD(XonoticCrosshairPreview, configureXonoticCrosshairPreview, void(entity))
+       METHOD(XonoticCrosshairPreview, draw, void(entity))
+       ATTRIB(XonoticCrosshairPreview, src, string, string_null)
+       ATTRIB(XonoticCrosshairPreview, src2, string, string_null)
+       ATTRIB(XonoticCrosshairPreview, disabled, float, 0)
+       ATTRIB(XonoticCrosshairPreview, disabledAlpha, float, SKINALPHA_DISABLED)
+ENDCLASS(XonoticCrosshairPreview)
+entity makeXonoticCrosshairPreview();
+#endif
+
+#ifdef IMPLEMENTATION
+entity makeXonoticCrosshairPreview()
+{
+       entity me;
+       me = NEW(XonoticCrosshairPreview);
+       me.configureXonoticCrosshairPreview(me);
+       return me;
+}
+
+void XonoticCrosshairPreview_configureXonoticCrosshairPreview(entity me)
+{
+       me.src = strzone(strcat("/gfx/crosshair", cvar_string("crosshair")));
+       me.src2 = "/gfx/crosshairdot";
+}
+
+void XonoticCrosshairPreview_draw(entity me)
+{
+       float save;
+       save = draw_alpha;
+       if(me.disabled)
+               draw_alpha *= me.disabledAlpha;
+
+       vector sz, rgb;
+       float a;
+       rgb = stov(cvar_string("crosshair_color"));
+       a = cvar("crosshair_alpha");
+       if(me.src)
+               strunzone(me.src);
+       me.src = strzone(strcat("/gfx/crosshair", cvar_string("crosshair")));
+
+       sz = draw_PictureSize(me.src);
+       sz = globalToBoxSize(sz, me.size);
+       sz = sz * cvar("crosshair_size");
+
+       draw_Picture('0.5 0.5 0' - 0.5 * sz, me.src, sz, rgb, a);
+       if(cvar("crosshair_dot"))
+       {
+               if(cvar("crosshair_dot_color_custom") && (cvar_string("crosshair_dot_color") != "0"))
+                       rgb = stov(cvar_string("crosshair_dot_color"));
+
+               draw_Picture('0.5 0.5 0' - 0.5 * sz * cvar("crosshair_dot_size"), me.src2, sz * cvar("crosshair_dot_size"), rgb, a * cvar("crosshair_dot_alpha"));
+       }
+
+       draw_alpha = save;
+
+       SUPER(XonoticCrosshairPreview).draw(me);
+}
+#endif
index 421142aac0746ca798ebe8157080071ee4254c79..9a95ed163963c58607afd2a0709bd408e6d5cad6 100644 (file)
@@ -1,8 +1,10 @@
-#ifdef INTERFACE
-CLASS(XonoticCvarList) EXTENDS(XonoticListBox)
+#ifndef CVARLIST_H
+#define CVARLIST_H
+#include "listbox.qc"
+CLASS(XonoticCvarList, XonoticListBox)
        METHOD(XonoticCvarList, configureXonoticCvarList, void(entity))
        ATTRIB(XonoticCvarList, rowsPerItem, float, 1)
-       METHOD(XonoticCvarList, drawListBoxItem, void(entity, float, vector, float))
+       METHOD(XonoticCvarList, drawListBoxItem, void(entity, int, vector, bool, bool))
        METHOD(XonoticCvarList, resizeNotify, void(entity, vector, vector, vector, vector))
        METHOD(XonoticCvarList, keyDown, float(entity, float, float, float))
 
@@ -44,7 +46,7 @@ void CvarList_End_Editing(entity box, entity me);
 entity makeXonoticCvarList()
 {
        entity me;
-       me = spawnXonoticCvarList();
+       me = NEW(XonoticCvarList);
        me.configureXonoticCvarList(me);
        return me;
 }
@@ -152,7 +154,7 @@ void XonoticCvarList_resizeNotify(entity me, vector relOrigin, vector relSize, v
 
        me.setSelected(me, me.selectedItem);
 }
-void XonoticCvarList_drawListBoxItem(entity me, float i, vector absSize, float isSelected)
+void XonoticCvarList_drawListBoxItem(entity me, int i, vector absSize, bool isSelected, bool isFocused)
 {
        string k, v, d;
        float t;
@@ -164,6 +166,11 @@ void XonoticCvarList_drawListBoxItem(entity me, float i, vector absSize, float i
 
        if(isSelected)
                draw_Fill('0 0 0', '1 1 0', SKINCOLOR_LISTBOX_SELECTED, SKINALPHA_LISTBOX_SELECTED);
+       else if(isFocused)
+       {
+               me.focusedItemAlpha = getFadedAlpha(me.focusedItemAlpha, SKINALPHA_LISTBOX_FOCUSED, SKINFADEALPHA_LISTBOX_FOCUSED);
+               draw_Fill('0 0 0', '1 1 0', SKINCOLOR_LISTBOX_FOCUSED, me.focusedItemAlpha);
+       }
 
        k = bufstr_get(me.handle, i);
 
index 6882fcc5eb78b2d49d6733639fd18b31b2298eea..f46ee407b6c82ecc8fa272df54e6eb7df379645c 100644 (file)
@@ -1,9 +1,11 @@
-#ifdef INTERFACE
-CLASS(XonoticDemoList) EXTENDS(XonoticListBox)
+#ifndef DEMOLIST_H
+#define DEMOLIST_H
+#include "listbox.qc"
+CLASS(XonoticDemoList, XonoticListBox)
        METHOD(XonoticDemoList, configureXonoticDemoList, void(entity))
        ATTRIB(XonoticDemoList, rowsPerItem, float, 1)
        METHOD(XonoticDemoList, resizeNotify, void(entity, vector, vector, vector, vector))
-       METHOD(XonoticDemoList, drawListBoxItem, void(entity, float, vector, float))
+       METHOD(XonoticDemoList, drawListBoxItem, void(entity, int, vector, bool, bool))
        METHOD(XonoticDemoList, getDemos, void(entity))
        METHOD(XonoticDemoList, startDemo, void(entity))
        METHOD(XonoticDemoList, timeDemo, void(entity))
@@ -38,7 +40,7 @@ void DemoList_Filter_Change(entity box, entity me);
 entity makeXonoticDemoList()
 {
        entity me;
-       me = spawnXonoticDemoList();
+       me = NEW(XonoticDemoList);
        me.configureXonoticDemoList(me);
        return me;
 }
@@ -133,11 +135,16 @@ void XonoticDemoList_resizeNotify(entity me, vector relOrigin, vector relSize, v
        me.columnNameSize = 1 - 2 * me.realFontSize.x;
 }
 
-void XonoticDemoList_drawListBoxItem(entity me, float i, vector absSize, float isSelected)
+void XonoticDemoList_drawListBoxItem(entity me, int i, vector absSize, bool isSelected, bool isFocused)
 {
        string s;
        if(isSelected)
                draw_Fill('0 0 0', '1 1 0', SKINCOLOR_LISTBOX_SELECTED, SKINALPHA_LISTBOX_SELECTED);
+       else if(isFocused)
+       {
+               me.focusedItemAlpha = getFadedAlpha(me.focusedItemAlpha, SKINALPHA_LISTBOX_FOCUSED, SKINFADEALPHA_LISTBOX_FOCUSED);
+               draw_Fill('0 0 0', '1 1 0', SKINCOLOR_LISTBOX_FOCUSED, me.focusedItemAlpha);
+       }
 
        s = me.demoName(me,i);
        s = draw_TextShortenToWidth(s, me.columnNameSize, 0, me.realFontSize);
index 6ca90254a3eb24b70318fe5972a58e85473cdfd0..c1ea16c6b7cbca86cd7131ab19456b199c388305 100644 (file)
@@ -1,5 +1,7 @@
-#ifdef INTERFACE
-CLASS(XonoticDialog) EXTENDS(Dialog)
+#ifndef DIALOG_H
+#define DIALOG_H
+#include "../item/dialog.qc"
+CLASS(XonoticDialog, Dialog)
        // still to be customized by user
        /*
        ATTRIB(XonoticDialog, closable, float, 1)
index e90ae4b42590d08435472ea66b76c31e5a317fe4..a9966266301ece966058bd2d53d484b657b03a65 100644 (file)
@@ -1,5 +1,7 @@
-#ifdef INTERFACE
-CLASS(XonoticCreditsDialog) EXTENDS(XonoticDialog)
+#ifndef DIALOG_CREDITS_H
+#define DIALOG_CREDITS_H
+#include "dialog.qc"
+CLASS(XonoticCreditsDialog, XonoticDialog)
        METHOD(XonoticCreditsDialog, fill, void(entity))
        METHOD(XonoticCreditsDialog, focusEnter, void(entity))
        ATTRIB(XonoticCreditsDialog, title, string, _("Credits"))
index c9238a979313f1086226ce5082b1e2c92038aaf5..894a702d8a026a155c1c05a1d4553003c474ec6a 100644 (file)
@@ -1,5 +1,7 @@
-#ifdef INTERFACE
-CLASS(XonoticFirstRunDialog) EXTENDS(XonoticRootDialog)
+#ifndef DIALOG_FIRSTRUN_H
+#define DIALOG_FIRSTRUN_H
+#include "rootdialog.qc"
+CLASS(XonoticFirstRunDialog, XonoticRootDialog)
        METHOD(XonoticFirstRunDialog, fill, void(entity)) // to be overridden by user to fill the dialog with controls
        ATTRIB(XonoticFirstRunDialog, title, string, _("Welcome"))
        ATTRIB(XonoticFirstRunDialog, color, vector, SKINCOLOR_DIALOG_FIRSTRUN)
index 307efdec023ea0a27c7eb5029290f668f8ad65ea..9f14754bd37f793f9917e1192e59c28d334fb66f 100644 (file)
@@ -1,5 +1,7 @@
-#ifdef INTERFACE
-CLASS(XonoticHUDAmmoDialog) EXTENDS(XonoticRootDialog)
+#ifndef DIALOG_HUDPANEL_AMMO_H
+#define DIALOG_HUDPANEL_AMMO_H
+#include "rootdialog.qc"
+CLASS(XonoticHUDAmmoDialog, XonoticRootDialog)
        METHOD(XonoticHUDAmmoDialog, fill, void(entity))
        ATTRIB(XonoticHUDAmmoDialog, title, string, _("Ammo Panel"))
        ATTRIB(XonoticHUDAmmoDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT)
index 226bd972403cafd7ba560c8984eabd5df2b24efc..7733fd35003a0fc65a326f57f7d1a2efee6c7f6f 100644 (file)
@@ -1,5 +1,7 @@
-#ifdef INTERFACE
-CLASS(XonoticHUDBuffsDialog) EXTENDS(XonoticRootDialog)
+#ifndef DIALOG_HUDPANEL_BUFFS_H
+#define DIALOG_HUDPANEL_BUFFS_H
+#include "rootdialog.qc"
+CLASS(XonoticHUDBuffsDialog, XonoticRootDialog)
        METHOD(XonoticHUDBuffsDialog, fill, void(entity))
        ATTRIB(XonoticHUDBuffsDialog, title, string, _("Buffs Panel"))
        ATTRIB(XonoticHUDBuffsDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT)
index bb7312f13e213002ecd65a4f2c07d2818c75e299..7e74cdf5e8f959b94488867fe4c0c1e0f82e85ad 100644 (file)
@@ -1,5 +1,7 @@
-#ifdef INTERFACE
-CLASS(XonoticHUDCenterprintDialog) EXTENDS(XonoticRootDialog)
+#ifndef DIALOG_HUDPANEL_CENTERPRINT_H
+#define DIALOG_HUDPANEL_CENTERPRINT_H
+#include "rootdialog.qc"
+CLASS(XonoticHUDCenterprintDialog, XonoticRootDialog)
        METHOD(XonoticHUDCenterprintDialog, fill, void(entity))
        ATTRIB(XonoticHUDCenterprintDialog, title, string, _("Centerprint Panel"))
        ATTRIB(XonoticHUDCenterprintDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT)
index e16f76ac3ea8d8f8022b1d8e2f8d1cde4ca5c19a..c56c312efc0461b39e2365f481d82f5106af340f 100644 (file)
@@ -1,5 +1,7 @@
-#ifdef INTERFACE
-CLASS(XonoticHUDChatDialog) EXTENDS(XonoticRootDialog)
+#ifndef DIALOG_HUDPANEL_CHAT_H
+#define DIALOG_HUDPANEL_CHAT_H
+#include "rootdialog.qc"
+CLASS(XonoticHUDChatDialog, XonoticRootDialog)
        METHOD(XonoticHUDChatDialog, fill, void(entity))
        ATTRIB(XonoticHUDChatDialog, title, string, _("Chat Panel"))
        ATTRIB(XonoticHUDChatDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT)
index 534f1ebfe146da507f81f2fc1fea49e6278a3e59..0220ea2325f1818cd5eef5408afdfaaba810bf10 100644 (file)
@@ -1,5 +1,7 @@
-#ifdef INTERFACE
-CLASS(XonoticHUDEngineInfoDialog) EXTENDS(XonoticRootDialog)
+#ifndef DIALOG_HUDPANEL_ENGINEINFO_H
+#define DIALOG_HUDPANEL_ENGINEINFO_H
+#include "rootdialog.qc"
+CLASS(XonoticHUDEngineInfoDialog, XonoticRootDialog)
        METHOD(XonoticHUDEngineInfoDialog, fill, void(entity))
        ATTRIB(XonoticHUDEngineInfoDialog, title, string, _("Engine Info Panel"))
        ATTRIB(XonoticHUDEngineInfoDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT)
index dc864203b46c0c7a1c0a54abe3925af18c5e357a..f0482bd73efbb4dbfb9c567cf2ff9e55bc3b7043 100644 (file)
@@ -1,5 +1,7 @@
-#ifdef INTERFACE
-CLASS(XonoticHUDHealthArmorDialog) EXTENDS(XonoticRootDialog)
+#ifndef DIALOG_HUDPANEL_HEALTHARMOR_H
+#define DIALOG_HUDPANEL_HEALTHARMOR_H
+#include "rootdialog.qc"
+CLASS(XonoticHUDHealthArmorDialog, XonoticRootDialog)
        METHOD(XonoticHUDHealthArmorDialog, fill, void(entity))
        ATTRIB(XonoticHUDHealthArmorDialog, title, string, _("Health/Armor Panel"))
        ATTRIB(XonoticHUDHealthArmorDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT)
index b705531209bda727d8f066e9cac3a810858fb485..84625df73dd693e95c40119456346ddc8dbf4b68 100644 (file)
@@ -1,5 +1,7 @@
-#ifdef INTERFACE
-CLASS(XonoticHUDInfoMessagesDialog) EXTENDS(XonoticRootDialog)
+#ifndef DIALOG_HUDPANEL_INFOMESSAGES_H
+#define DIALOG_HUDPANEL_INFOMESSAGES_H
+#include "rootdialog.qc"
+CLASS(XonoticHUDInfoMessagesDialog, XonoticRootDialog)
        METHOD(XonoticHUDInfoMessagesDialog, fill, void(entity))
        ATTRIB(XonoticHUDInfoMessagesDialog, title, string, _("Info Messages Panel"))
        ATTRIB(XonoticHUDInfoMessagesDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT)
index 3133a7e83a1228651c4e6b512ef35ab057105d36..9737c548055a1a367f560279afac18e311634c1c 100644 (file)
@@ -1,5 +1,7 @@
-#ifdef INTERFACE
-CLASS(XonoticHUDModIconsDialog) EXTENDS(XonoticRootDialog)
+#ifndef DIALOG_HUDPANEL_MODICONS_H
+#define DIALOG_HUDPANEL_MODICONS_H
+#include "rootdialog.qc"
+CLASS(XonoticHUDModIconsDialog, XonoticRootDialog)
        METHOD(XonoticHUDModIconsDialog, fill, void(entity))
        ATTRIB(XonoticHUDModIconsDialog, title, string, _("Mod Icons Panel"))
        ATTRIB(XonoticHUDModIconsDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT)
index 722b5d539d169de9e9ca106279e7f341f129c0b4..d0586710cf63ad55fc88e3a32184d418e81d18c8 100644 (file)
@@ -1,5 +1,7 @@
-#ifdef INTERFACE
-CLASS(XonoticHUDNotificationDialog) EXTENDS(XonoticRootDialog)
+#ifndef DIALOG_HUDPANEL_NOTIFICATION_H
+#define DIALOG_HUDPANEL_NOTIFICATION_H
+#include "rootdialog.qc"
+CLASS(XonoticHUDNotificationDialog, XonoticRootDialog)
        METHOD(XonoticHUDNotificationDialog, fill, void(entity))
        ATTRIB(XonoticHUDNotificationDialog, title, string, _("Notification Panel"))
        ATTRIB(XonoticHUDNotificationDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT)
index 6e4917d93c0f8bb75be6906680c94c54d2faae28..606f01aaab8e6ee3b0741b3166760780f22f0fa2 100644 (file)
@@ -1,5 +1,7 @@
-#ifdef INTERFACE
-CLASS(XonoticHUDPhysicsDialog) EXTENDS(XonoticRootDialog)
+#ifndef DIALOG_HUDPANEL_PHYSICS_H
+#define DIALOG_HUDPANEL_PHYSICS_H
+#include "rootdialog.qc"
+CLASS(XonoticHUDPhysicsDialog, XonoticRootDialog)
        METHOD(XonoticHUDPhysicsDialog, fill, void(entity))
        ATTRIB(XonoticHUDPhysicsDialog, title, string, _("Physics Panel"))
        ATTRIB(XonoticHUDPhysicsDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT)
index 3449e0604a046ffa0ddac263a988770c82fad713..45a2049fc26b0cc87e6c15f28c3866ab352d29fc 100644 (file)
@@ -1,5 +1,7 @@
-#ifdef INTERFACE
-CLASS(XonoticHUDPowerupsDialog) EXTENDS(XonoticRootDialog)
+#ifndef DIALOG_HUDPANEL_POWERUPS_H
+#define DIALOG_HUDPANEL_POWERUPS_H
+#include "rootdialog.qc"
+CLASS(XonoticHUDPowerupsDialog, XonoticRootDialog)
        METHOD(XonoticHUDPowerupsDialog, fill, void(entity))
        ATTRIB(XonoticHUDPowerupsDialog, title, string, _("Powerups Panel"))
        ATTRIB(XonoticHUDPowerupsDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT)
index 79f581d13456f2f5bb93fd34ca5d324137375254..4499d7c0f62a3370c5b9bcf11f27cb81588caad4 100644 (file)
@@ -1,5 +1,7 @@
-#ifdef INTERFACE
-CLASS(XonoticHUDPressedKeysDialog) EXTENDS(XonoticRootDialog)
+#ifndef DIALOG_HUDPANEL_PRESSEDKEYS_H
+#define DIALOG_HUDPANEL_PRESSEDKEYS_H
+#include "rootdialog.qc"
+CLASS(XonoticHUDPressedKeysDialog, XonoticRootDialog)
        METHOD(XonoticHUDPressedKeysDialog, fill, void(entity))
        ATTRIB(XonoticHUDPressedKeysDialog, title, string, _("Pressed Keys Panel"))
        ATTRIB(XonoticHUDPressedKeysDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT)
index b8ecbee59bcb49bd555eb636e6294d5c59801217..3333a0e641ac0b43d500e92c8f23c03ffb6d25d5 100644 (file)
@@ -1,5 +1,7 @@
-#ifdef INTERFACE
-CLASS(XonoticHUDRaceTimerDialog) EXTENDS(XonoticRootDialog)
+#ifndef DIALOG_HUDPANEL_RACETIMER_H
+#define DIALOG_HUDPANEL_RACETIMER_H
+#include "rootdialog.qc"
+CLASS(XonoticHUDRaceTimerDialog, XonoticRootDialog)
        METHOD(XonoticHUDRaceTimerDialog, fill, void(entity))
        ATTRIB(XonoticHUDRaceTimerDialog, title, string, _("Race Timer Panel"))
        ATTRIB(XonoticHUDRaceTimerDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT)
index bdff50cb5ec915e270a37e38ac4bb96892377959..0d159b2766095b6f52537bc402369572444c9528 100644 (file)
@@ -1,5 +1,7 @@
-#ifdef INTERFACE
-CLASS(XonoticHUDRadarDialog) EXTENDS(XonoticRootDialog)
+#ifndef DIALOG_HUDPANEL_RADAR_H
+#define DIALOG_HUDPANEL_RADAR_H
+#include "rootdialog.qc"
+CLASS(XonoticHUDRadarDialog, XonoticRootDialog)
        METHOD(XonoticHUDRadarDialog, fill, void(entity))
        ATTRIB(XonoticHUDRadarDialog, title, string, _("Radar Panel"))
        ATTRIB(XonoticHUDRadarDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT)
index edd4da66e0cb9654b326ec9e185fbee29206d4c8..690fc3b109adcf45cd09f6e82d90c31da001bff5 100644 (file)
@@ -1,5 +1,7 @@
-#ifdef INTERFACE
-CLASS(XonoticHUDScoreDialog) EXTENDS(XonoticRootDialog)
+#ifndef DIALOG_HUDPANEL_SCORE_H
+#define DIALOG_HUDPANEL_SCORE_H
+#include "rootdialog.qc"
+CLASS(XonoticHUDScoreDialog, XonoticRootDialog)
        METHOD(XonoticHUDScoreDialog, fill, void(entity))
        ATTRIB(XonoticHUDScoreDialog, title, string, _("Score Panel"))
        ATTRIB(XonoticHUDScoreDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT)
index 754a5f1003481dfe06d65cf3dfa5c5c7f84a6269..d140dea22276632a2f5fc0bb2e5c46e9761ae984 100644 (file)
@@ -1,5 +1,7 @@
-#ifdef INTERFACE
-CLASS(XonoticHUDTimerDialog) EXTENDS(XonoticRootDialog)
+#ifndef DIALOG_HUDPANEL_TIMER_H
+#define DIALOG_HUDPANEL_TIMER_H
+#include "rootdialog.qc"
+CLASS(XonoticHUDTimerDialog, XonoticRootDialog)
        METHOD(XonoticHUDTimerDialog, fill, void(entity))
        ATTRIB(XonoticHUDTimerDialog, title, string, _("Timer Panel"))
        ATTRIB(XonoticHUDTimerDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT)
index e2b398ef2ed2e839dda0c74ac11e4812b1be73d5..62d439e33b370fc8bbb587bf6b4ee643cd7880fe 100644 (file)
@@ -1,5 +1,7 @@
-#ifdef INTERFACE
-CLASS(XonoticHUDVoteDialog) EXTENDS(XonoticRootDialog)
+#ifndef DIALOG_HUDPANEL_VOTE_H
+#define DIALOG_HUDPANEL_VOTE_H
+#include "rootdialog.qc"
+CLASS(XonoticHUDVoteDialog, XonoticRootDialog)
        METHOD(XonoticHUDVoteDialog, fill, void(entity))
        ATTRIB(XonoticHUDVoteDialog, title, string, _("Vote Panel"))
        ATTRIB(XonoticHUDVoteDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT)
index ce1479cb1d775da4681ec211f58a7f8d2a7371ed..7f58e6c4abe904435eaa553c1ab14cc3715149df 100644 (file)
@@ -1,5 +1,7 @@
-#ifdef INTERFACE
-CLASS(XonoticHUDWeaponsDialog) EXTENDS(XonoticRootDialog)
+#ifndef DIALOG_HUDPANEL_WEAPONS_H
+#define DIALOG_HUDPANEL_WEAPONS_H
+#include "rootdialog.qc"
+CLASS(XonoticHUDWeaponsDialog, XonoticRootDialog)
        METHOD(XonoticHUDWeaponsDialog, fill, void(entity))
        ATTRIB(XonoticHUDWeaponsDialog, title, string, _("Weapons Panel"))
        ATTRIB(XonoticHUDWeaponsDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT)
index 7cf0ea6dab934c6e8d5b6b125e60e3d88688c966..f8f6b9e6e4414654b354f75886a2404db63b52b8 100644 (file)
@@ -1,5 +1,7 @@
-#ifdef INTERFACE
-CLASS(XonoticHUDExitDialog) EXTENDS(XonoticRootDialog)
+#ifndef DIALOG_HUDSETUP_EXIT_H
+#define DIALOG_HUDSETUP_EXIT_H
+#include "rootdialog.qc"
+CLASS(XonoticHUDExitDialog, XonoticRootDialog)
        METHOD(XonoticHUDExitDialog, fill, void(entity))
        ATTRIB(XonoticHUDExitDialog, title, string, _("Panel HUD Setup"))
        ATTRIB(XonoticHUDExitDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT)
index 8b67094a725a945be5ef7ec5fc4f3215edda6441..14587e2a9f1933fb78f17038a54618e637bba0bb 100644 (file)
@@ -1,5 +1,7 @@
-#ifdef INTERFACE
-CLASS(XonoticMonsterToolsDialog) EXTENDS(XonoticRootDialog)
+#ifndef DIALOG_MONSTERTOOLS_H
+#define DIALOG_MONSTERTOOLS_H
+#include "rootdialog.qc"
+CLASS(XonoticMonsterToolsDialog, XonoticRootDialog)
        METHOD(XonoticMonsterToolsDialog, fill, void(entity)) // to be overridden by user to fill the dialog with controls
        ATTRIB(XonoticMonsterToolsDialog, title, string, _("Monster Tools"))
        ATTRIB(XonoticMonsterToolsDialog, color, vector, SKINCOLOR_DIALOG_SANDBOXTOOLS)
index 7d234c7fe84907a024e1de737d5b73810f0014d0..64cfbd91dd415e04198517a1d4ef991c580fd7f7 100644 (file)
@@ -1,5 +1,7 @@
-#ifdef INTERFACE
-CLASS(XonoticMultiplayerDialog) EXTENDS(XonoticDialog)
+#ifndef DIALOG_MULTIPLAYER_H
+#define DIALOG_MULTIPLAYER_H
+#include "dialog.qc"
+CLASS(XonoticMultiplayerDialog, XonoticDialog)
        METHOD(XonoticMultiplayerDialog, fill, void(entity))
        ATTRIB(XonoticMultiplayerDialog, title, string, _("Multiplayer"))
        ATTRIB(XonoticMultiplayerDialog, color, vector, SKINCOLOR_DIALOG_MULTIPLAYER)
@@ -17,9 +19,6 @@ void XonoticMultiplayerDialog_fill(entity me)
        me.TR(me);
                me.TD(me, 1, 1, e = mc.makeTabButton(mc, _("Servers"), makeXonoticServerListTab()));
                me.TD(me, 1, 1, e = mc.makeTabButton(mc, _("Create"), makeXonoticServerCreateTab()));
-               //me.TD(me, 1, 1, e = mc.makeTabButton(mc, _("Demos"), makeXonoticDemoBrowserTab()));
-               //me.TD(me, 1, 1, e = mc.makeTabButton(mc, _("Screenshots"), makeXonoticScreenshotBrowserTab()));
-               //me.TD(me, 1, 1, e = mc.makeTabButton(mc, _("Players"), makeXonoticDemoBrowserTab()));
                me.TD(me, 1, 1, e = mc.makeTabButton(mc, _("Media"), makeXonoticMediaTab()));
                me.TD(me, 1, 1, e = mc.makeTabButton(mc, _("Profile"), makeXonoticProfileTab()));
 
index 4e76cbc6d3a5095560d41dd71da3bbb969476678..e56f2eef3d991e447f6b5e9d09ffdbff7a30bdd1 100644 (file)
@@ -1,9 +1,10 @@
-#ifdef INTERFACE
-CLASS(XonoticServerCreateTab) EXTENDS(XonoticTab)
+#ifndef DIALOG_MULTIPLAYER_CREATE_H
+#define DIALOG_MULTIPLAYER_CREATE_H
+#include "tab.qc"
+CLASS(XonoticServerCreateTab, XonoticTab)
        METHOD(XonoticServerCreateTab, fill, void(entity))
        METHOD(XonoticServerCreateTab, gameTypeChangeNotify, void(entity))
        METHOD(XonoticServerCreateTab, gameTypeSelectNotify, void(entity))
-       ATTRIB(XonoticServerCreateTab, title, string, _("Create"))
        ATTRIB(XonoticServerCreateTab, intendedWidth, float, 0.9)
        ATTRIB(XonoticServerCreateTab, rows, float, 23)
        ATTRIB(XonoticServerCreateTab, columns, float, 6.2) // added extra .2 for center space
@@ -33,7 +34,7 @@ void GameType_ConfigureSliders(entity e, entity l, string pLabel, float pMin, fl
                e.configureXonoticTextSlider(e, pCvar);
 
                // clear old values
-               float i;
+               int i;
                for(i = 0; i <= e.nValues; ++i);
                {
                        if(e.(valueStrings[i])) { strunzone(e.(valueStrings[i])); }
@@ -56,7 +57,7 @@ void GameType_ConfigureSliders(entity e, entity l, string pLabel, float pMin, fl
 entity makeXonoticServerCreateTab()
 {
        entity me;
-       me = spawnXonoticServerCreateTab();
+       me = NEW(XonoticServerCreateTab);
        me.configureDialog(me);
        return me;
 }
index 9baf36127dfe56648994b79735a84a5c124a06a3..5254f5aa37223a251bd7364992b80a1684767489 100644 (file)
@@ -1,5 +1,7 @@
-#ifdef INTERFACE
-CLASS(XonoticMapInfoDialog) EXTENDS(XonoticDialog)
+#ifndef DIALOG_MULTIPLAYER_CREATE_MAPINFO_H
+#define DIALOG_MULTIPLAYER_CREATE_MAPINFO_H
+#include "dialog.qc"
+CLASS(XonoticMapInfoDialog, XonoticDialog)
        METHOD(XonoticMapInfoDialog, fill, void(entity))
        METHOD(XonoticMapInfoDialog, loadMapInfo, void(entity, float, entity))
        ATTRIB(XonoticMapInfoDialog, title, string, _("Map Information"))
@@ -26,7 +28,7 @@ ENDCLASS(XonoticMapInfoDialog)
 #endif
 
 #ifdef IMPLEMENTATION
-void XonoticMapInfoDialog_loadMapInfo(entity me, float i, entity mlb)
+void XonoticMapInfoDialog_loadMapInfo(entity me, int i, entity mlb)
 {
        me.currentMapIndex = i;
        me.startButton.onClickEntity = mlb;
@@ -67,7 +69,8 @@ void XonoticMapInfoDialog_loadMapInfo(entity me, float i, entity mlb)
 void XonoticMapInfoDialog_fill(entity me)
 {
        entity e;
-       float w, wgt, i, n;
+       int i;
+       float w, wgt, n;
        me.TR(me);
                me.TDempty(me, 0.2);
                me.TD(me, me.rows - 2, 3, e = makeXonoticImage(string_null, 4.0/3.0));
index d7825e06a395705cdac822d833107c6943a488fc..8ab5296383e97575f1c18ae106fb588bab2e061b 100644 (file)
@@ -1,7 +1,9 @@
-#include "../../common/weapons/weapons.qh"
+#include "../../common/weapons/all.qh"
 
-#ifdef INTERFACE
-CLASS(XonoticMutatorsDialog) EXTENDS(XonoticDialog)
+#ifndef DIALOG_MULTIPLAYER_CREATE_MUTATORS_H
+#define DIALOG_MULTIPLAYER_CREATE_MUTATORS_H
+#include "dialog.qc"
+CLASS(XonoticMutatorsDialog, XonoticDialog)
        METHOD(XonoticMutatorsDialog, toString, string(entity))
        METHOD(XonoticMutatorsDialog, fill, void(entity))
        METHOD(XonoticMutatorsDialog, showNotify, void(entity))
index 4636ebbdbbfe3321e25b1a2f7a18b246e414849c..a4e480e18ab4197e5f0fdd52b0ac27fcab1a1e8d 100644 (file)
@@ -1,7 +1,8 @@
-#ifdef INTERFACE
-CLASS(XonoticServerListTab) EXTENDS(XonoticTab)
+#ifndef DIALOG_MULTIPLAYER_JOIN_H
+#define DIALOG_MULTIPLAYER_JOIN_H
+#include "tab.qc"
+CLASS(XonoticServerListTab, XonoticTab)
        METHOD(XonoticServerListTab, fill, void(entity))
-       ATTRIB(XonoticServerListTab, title, string, _("Join"))
        ATTRIB(XonoticServerListTab, intendedWidth, float, 0.9)
        ATTRIB(XonoticServerListTab, rows, float, 23)
        ATTRIB(XonoticServerListTab, columns, float, 6.5)
@@ -14,7 +15,7 @@ entity makeXonoticServerListTab();
 entity makeXonoticServerListTab()
 {
        entity me;
-       me = spawnXonoticServerListTab();
+       me = NEW(XonoticServerListTab);
        me.configureDialog(me);
        return me;
 }
index dabb1be541bf3b50131d7ef827e61dc9aae7d890..a5ad6332054becb57d53167ccb7ddc9eaae92e3d 100644 (file)
@@ -1,7 +1,9 @@
 #include "../../common/mapinfo.qh"
 
-#ifdef INTERFACE
-CLASS(XonoticServerInfoDialog) EXTENDS(XonoticDialog)
+#ifndef DIALOG_MULTIPLAYER_JOIN_SERVERINFO_H
+#define DIALOG_MULTIPLAYER_JOIN_SERVERINFO_H
+#include "dialog.qc"
+CLASS(XonoticServerInfoDialog, XonoticDialog)
        METHOD(XonoticServerInfoDialog, fill, void(entity))
        METHOD(XonoticServerInfoDialog, loadServerInfo, void(entity, float))
        ATTRIB(XonoticServerInfoDialog, title, string, _("Server Information"))
index 1ec0c76e9e7b35fff87ed408a40de939a55d0b57..03ffd0f36dc361d814707081bb8b6efd18eb9890 100644 (file)
@@ -1,7 +1,8 @@
-#ifdef INTERFACE
-CLASS(XonoticMediaTab) EXTENDS(XonoticTab)
+#ifndef DIALOG_MULTIPLAYER_MEDIA_H
+#define DIALOG_MULTIPLAYER_MEDIA_H
+#include "tab.qc"
+CLASS(XonoticMediaTab, XonoticTab)
        METHOD(XonoticMediaTab, fill, void(entity))
-       ATTRIB(XonoticMediaTab, title, string, _("Media"))
        ATTRIB(XonoticMediaTab, intendedWidth, float, 0.9)
        ATTRIB(XonoticMediaTab, rows, float, 23)
        ATTRIB(XonoticMediaTab, columns, float, 3)
@@ -14,7 +15,7 @@ entity makeXonoticMediaTab();
 entity makeXonoticMediaTab()
 {
        entity me;
-       me = spawnXonoticMediaTab();
+       me = NEW(XonoticMediaTab);
        me.configureDialog(me);
        return me;
 }
index ab2886a28542f66987de95c3ba02ea108ee38cb1..788aa5381bac5ca7c2ac8de7d1ae2d67d3dc7360 100644 (file)
@@ -1,7 +1,8 @@
-#ifdef INTERFACE
-CLASS(XonoticDemoBrowserTab) EXTENDS(XonoticTab)
+#ifndef DIALOG_MULTIPLAYER_MEDIA_DEMO_H
+#define DIALOG_MULTIPLAYER_MEDIA_DEMO_H
+#include "tab.qc"
+CLASS(XonoticDemoBrowserTab, XonoticTab)
        METHOD(XonoticDemoBrowserTab, fill, void(entity))
-       ATTRIB(XonoticDemoBrowserTab, title, string, _("Demo"))
        ATTRIB(XonoticDemoBrowserTab, intendedWidth, float, 0.9)
        ATTRIB(XonoticDemoBrowserTab, rows, float, 21)
        ATTRIB(XonoticDemoBrowserTab, columns, float, 6.5)
@@ -9,14 +10,11 @@ CLASS(XonoticDemoBrowserTab) EXTENDS(XonoticTab)
        ATTRIB(XonoticDemoBrowserTab, democlicktype, float, 0)
 ENDCLASS(XonoticDemoBrowserTab)
 entity makeXonoticDemoBrowserTab();
-#ifdef IMPLEMENTATION
-// private:
-const float DMO_PLAY = 1;
-const float DMO_TIME = 2;
-#endif
 #endif
 
 #ifdef IMPLEMENTATION
+const float DMO_PLAY = 1;
+const float DMO_TIME = 2;
 void DemoConfirm_Check_Gamestatus(entity btn, entity me)
 {
        if(!(gamestatus & (GAME_CONNECTED | GAME_ISSERVER))) // we're not in a match, lets watch the demo
@@ -38,7 +36,7 @@ void DemoConfirm_Check_Gamestatus(entity btn, entity me)
 entity makeXonoticDemoBrowserTab()
 {
        entity me;
-       me = spawnXonoticDemoBrowserTab();
+       me = NEW(XonoticDemoBrowserTab);
        me.configureDialog(me);
        return me;
 }
index 136997eec0afae2a1b2451d1b5eb5d8e6af68e6f..8d410ca7de87629fbfd38a9cfbb12c173a4d50ec 100644 (file)
@@ -1,5 +1,7 @@
-#ifdef INTERFACE
-CLASS(XonoticDemoStartConfirmDialog) EXTENDS(XonoticDialog)
+#ifndef DIALOG_MULTIPLAYER_MEDIA_DEMO_STARTCONFIRM_H
+#define DIALOG_MULTIPLAYER_MEDIA_DEMO_STARTCONFIRM_H
+#include "dialog.qc"
+CLASS(XonoticDemoStartConfirmDialog, XonoticDialog)
        METHOD(XonoticDemoStartConfirmDialog, fill, void(entity))
        ATTRIB(XonoticDemoStartConfirmDialog, title, string, _("Disconnect"))
        ATTRIB(XonoticDemoStartConfirmDialog, color, vector, SKINCOLOR_DIALOG_HUDCONFIRM)
index 5c9bf8cb3d12ba9d6b633d1f1cd8cf27448728f8..fc3aa4448d36d678a3227e08a32abbb1d5019cac 100644 (file)
@@ -1,5 +1,7 @@
-#ifdef INTERFACE
-CLASS(XonoticDemoTimeConfirmDialog) EXTENDS(XonoticDialog)
+#ifndef DIALOG_MULTIPLAYER_MEDIA_DEMO_TIMECONFIRM_H
+#define DIALOG_MULTIPLAYER_MEDIA_DEMO_TIMECONFIRM_H
+#include "dialog.qc"
+CLASS(XonoticDemoTimeConfirmDialog, XonoticDialog)
        METHOD(XonoticDemoTimeConfirmDialog, fill, void(entity))
        ATTRIB(XonoticDemoTimeConfirmDialog, title, string, _("Disconnect"))
        ATTRIB(XonoticDemoTimeConfirmDialog, color, vector, SKINCOLOR_DIALOG_HUDCONFIRM)
index 0b7e4231ce50e4c1742e79d17fbcf714145d228f..6c0791ff7ca66833470e02386876af59b5878774 100644 (file)
@@ -1,7 +1,8 @@
-#ifdef INTERFACE
-CLASS(XonoticMusicPlayerTab) EXTENDS(XonoticTab)
+#ifndef DIALOG_MULTIPLAYER_MEDIA_MUSICPLAYER_H
+#define DIALOG_MULTIPLAYER_MEDIA_MUSICPLAYER_H
+#include "tab.qc"
+CLASS(XonoticMusicPlayerTab, XonoticTab)
        METHOD(XonoticMusicPlayerTab, fill, void(entity))
-       ATTRIB(XonoticMusicPlayerTab, title, string, _("Music"))
        ATTRIB(XonoticMusicPlayerTab, intendedWidth, float, 0.9)
        ATTRIB(XonoticMusicPlayerTab, rows, float, 21)
        ATTRIB(XonoticMusicPlayerTab, columns, float, 6.5)
@@ -14,7 +15,7 @@ entity makeXonoticMusicPlayerTab();
 entity makeXonoticMusicPlayerTab()
 {
        entity me;
-       me = spawnXonoticMusicPlayerTab();
+       me = NEW(XonoticMusicPlayerTab);
        me.configureDialog(me);
        return me;
 }
index 89a76b608dce46dcb73c662188a790298b15f749..c6526f2ec8db9044663a6922081d8bb41199fd40 100644 (file)
@@ -1,7 +1,8 @@
-#ifdef INTERFACE
-CLASS(XonoticScreenshotBrowserTab) EXTENDS(XonoticTab)
+#ifndef DIALOG_MULTIPLAYER_MEDIA_SCREENSHOT_H
+#define DIALOG_MULTIPLAYER_MEDIA_SCREENSHOT_H
+#include "tab.qc"
+CLASS(XonoticScreenshotBrowserTab, XonoticTab)
        METHOD(XonoticScreenshotBrowserTab, fill, void(entity))
-       ATTRIB(XonoticScreenshotBrowserTab, title, string, "Screenshot")
        ATTRIB(XonoticScreenshotBrowserTab, intendedWidth, float, 1)
        ATTRIB(XonoticScreenshotBrowserTab, rows, float, 21)
        ATTRIB(XonoticScreenshotBrowserTab, columns, float, 6.5)
@@ -18,7 +19,7 @@ entity makeXonoticScreenshotBrowserTab();
 entity makeXonoticScreenshotBrowserTab()
 {
        entity me;
-       me = spawnXonoticScreenshotBrowserTab();
+       me = NEW(XonoticScreenshotBrowserTab);
        me.configureDialog(me);
        return me;
 }
index bcf168a93a3036da416233dd427d6027d2df0eca..fa63a17b01c717a1501d381b9b3d0c24a79056b1 100644 (file)
@@ -1,5 +1,7 @@
-#ifdef INTERFACE
-CLASS(XonoticScreenshotViewerDialog) EXTENDS(XonoticDialog)
+#ifndef DIALOG_MULTIPLAYER_MEDIA_SCREENSHOT_VIEWER_H
+#define DIALOG_MULTIPLAYER_MEDIA_SCREENSHOT_VIEWER_H
+#include "dialog.qc"
+CLASS(XonoticScreenshotViewerDialog, XonoticDialog)
        METHOD(XonoticScreenshotViewerDialog, fill, void(entity))
        METHOD(XonoticScreenshotViewerDialog, keyDown, float(entity, float, float, float))
        METHOD(XonoticScreenshotViewerDialog, loadScreenshot, void(entity, string))
index 8c24885439e8ec9b16ac9aff2837f032fc0289dd..9faf42888e83ef6e4f84c9ea4ba8152815029a6b 100644 (file)
@@ -1,8 +1,9 @@
-#ifdef INTERFACE
-CLASS(XonoticProfileTab) EXTENDS(XonoticTab)
+#ifndef DIALOG_MULTIPLAYER_PROFILE_H
+#define DIALOG_MULTIPLAYER_PROFILE_H
+#include "tab.qc"
+CLASS(XonoticProfileTab, XonoticTab)
        METHOD(XonoticProfileTab, fill, void(entity))
        METHOD(XonoticProfileTab, draw, void(entity))
-       ATTRIB(XonoticProfileTab, title, string, _("Profile"))
        ATTRIB(XonoticProfileTab, intendedWidth, float, 0.9)
        ATTRIB(XonoticProfileTab, rows, float, 23)
        ATTRIB(XonoticProfileTab, columns, float, 6.1) // added extra .2 for center space
@@ -16,7 +17,7 @@ entity makeXonoticProfileTab();
 entity makeXonoticProfileTab()
 {
        entity me;
-       me = spawnXonoticProfileTab();
+       me = NEW(XonoticProfileTab);
        me.configureDialog(me);
        return me;
 }
index 71de59dac2e33166fb3479d29655656498a8089c..fa4cacecb46fb5bec1c402812b20f84cc60b5116 100644 (file)
@@ -1,5 +1,7 @@
-#ifdef INTERFACE
-CLASS(XonoticQuitDialog) EXTENDS(XonoticDialog)
+#ifndef DIALOG_QUIT_H
+#define DIALOG_QUIT_H
+#include "dialog.qc"
+CLASS(XonoticQuitDialog, XonoticDialog)
        METHOD(XonoticQuitDialog, fill, void(entity))
        ATTRIB(XonoticQuitDialog, title, string, _("Quit"))
        ATTRIB(XonoticQuitDialog, color, vector, SKINCOLOR_DIALOG_QUIT)
index fa7f40aea11911cdbf41db33b354c2e9e24d7e33..bcc1ea1f0c6fbe2b2deadd8418b036e5677e77b8 100644 (file)
@@ -1,5 +1,7 @@
-#ifdef INTERFACE
-CLASS(XonoticSandboxToolsDialog) EXTENDS(XonoticRootDialog)
+#ifndef DIALOG_SANDBOXTOOLS_H
+#define DIALOG_SANDBOXTOOLS_H
+#include "rootdialog.qc"
+CLASS(XonoticSandboxToolsDialog, XonoticRootDialog)
        METHOD(XonoticSandboxToolsDialog, fill, void(entity)) // to be overridden by user to fill the dialog with controls
        ATTRIB(XonoticSandboxToolsDialog, title, string, _("Sandbox Tools")) // ;)
        ATTRIB(XonoticSandboxToolsDialog, color, vector, SKINCOLOR_DIALOG_SANDBOXTOOLS)
index a992e80593e4b14b62b86aa96f683f5d4df4695e..e17ab14e6cf14ecaf9ff8a53f8d2b759babdb862 100644 (file)
@@ -1,5 +1,7 @@
-#ifdef INTERFACE
-CLASS(XonoticSettingsDialog) EXTENDS(XonoticDialog)
+#ifndef DIALOG_SETTINGS_H
+#define DIALOG_SETTINGS_H
+#include "dialog.qc"
+CLASS(XonoticSettingsDialog, XonoticDialog)
        METHOD(XonoticSettingsDialog, fill, void(entity))
        ATTRIB(XonoticSettingsDialog, title, string, _("Settings"))
        ATTRIB(XonoticSettingsDialog, color, vector, SKINCOLOR_DIALOG_SETTINGS)
index cccaa2652818b5bbf91dc9bfe9c204a33f85bdcf..af8faddacecceb7a6fa9531152b26fd09a8c1bc9 100644 (file)
@@ -1,7 +1,8 @@
-#ifdef INTERFACE
-CLASS(XonoticAudioSettingsTab) EXTENDS(XonoticTab)
+#ifndef DIALOG_SETTINGS_AUDIO_H
+#define DIALOG_SETTINGS_AUDIO_H
+#include "tab.qc"
+CLASS(XonoticAudioSettingsTab, XonoticTab)
        METHOD(XonoticAudioSettingsTab, fill, void(entity))
-       ATTRIB(XonoticAudioSettingsTab, title, string, _("Audio"))
        ATTRIB(XonoticAudioSettingsTab, intendedWidth, float, 0.9)
        ATTRIB(XonoticAudioSettingsTab, rows, float, 15.5)
        ATTRIB(XonoticAudioSettingsTab, columns, float, 6.2) // added extra .2 for center space
@@ -14,7 +15,7 @@ entity makeXonoticAudioSettingsTab();
 entity makeXonoticAudioSettingsTab()
 {
        entity me;
-       me = spawnXonoticAudioSettingsTab();
+       me = NEW(XonoticAudioSettingsTab);
        me.configureDialog(me);
        return me;
 }
index fcbbbbe0e19b6a740576762a673d725b16e21bd4..d06465082b395303a4a1857c4982c7bb7f6258a2 100644 (file)
@@ -1,7 +1,8 @@
-#ifdef INTERFACE
-CLASS(XonoticEffectsSettingsTab) EXTENDS(XonoticTab)
+#ifndef DIALOG_SETTINGS_EFFECTS_H
+#define DIALOG_SETTINGS_EFFECTS_H
+#include "tab.qc"
+CLASS(XonoticEffectsSettingsTab, XonoticTab)
        METHOD(XonoticEffectsSettingsTab, fill, void(entity))
-       ATTRIB(XonoticEffectsSettingsTab, title, string, _("Effects"))
        ATTRIB(XonoticEffectsSettingsTab, intendedWidth, float, 0.9)
        ATTRIB(XonoticEffectsSettingsTab, rows, float, 15.5)
        ATTRIB(XonoticEffectsSettingsTab, columns, float, 6.2) // added extra .2 for center space
@@ -13,7 +14,7 @@ entity makeXonoticEffectsSettingsTab();
 entity makeXonoticEffectsSettingsTab()
 {
        entity me;
-       me = spawnXonoticEffectsSettingsTab();
+       me = NEW(XonoticEffectsSettingsTab);
        me.configureDialog(me);
        return me;
 }
index 5fb563ebd7be2243e3092c01fd6f29c431411d2f..5b14b7bdb698669a8cd0531ed77d8dedbdafb7f0 100644 (file)
@@ -1,7 +1,8 @@
-#ifdef INTERFACE
-CLASS(XonoticGameSettingsTab) EXTENDS(XonoticTab)
+#ifndef DIALOG_SETTINGS_GAME_H
+#define DIALOG_SETTINGS_GAME_H
+#include "tab.qc"
+CLASS(XonoticGameSettingsTab, XonoticTab)
        METHOD(XonoticGameSettingsTab, fill, void(entity))
-       ATTRIB(XonoticGameSettingsTab, title, string, _("Game"))
        ATTRIB(XonoticGameSettingsTab, intendedWidth, float, 0.9)
        ATTRIB(XonoticGameSettingsTab, rows, float, 15.5)
        ATTRIB(XonoticGameSettingsTab, columns, float, 6.5)
@@ -13,7 +14,7 @@ entity makeXonoticGameSettingsTab();
 entity makeXonoticGameSettingsTab()
 {
        entity me;
-       me = spawnXonoticGameSettingsTab();
+       me = NEW(XonoticGameSettingsTab);
        me.configureDialog(me);
        return me;
 }
index 28cf3708f3af0833b98028ef9b42e433a934292c..cee4bd5c72a68a8a8c0c3fa4b77a874c069f5e66 100644 (file)
@@ -1,9 +1,9 @@
-#ifdef INTERFACE
-CLASS(XonoticGameCrosshairSettingsTab) EXTENDS(XonoticTab)
-       //METHOD(XonoticGameCrosshairSettingsTab, toString, string(entity))
+#ifndef DIALOG_SETTINGS_GAME_CROSSHAIR_H
+#define DIALOG_SETTINGS_GAME_CROSSHAIR_H
+#include "tab.qc"
+CLASS(XonoticGameCrosshairSettingsTab, XonoticTab)
        METHOD(XonoticGameCrosshairSettingsTab, fill, void(entity))
        METHOD(XonoticGameCrosshairSettingsTab, showNotify, void(entity))
-       ATTRIB(XonoticGameCrosshairSettingsTab, title, string, _("Crosshair"))
        ATTRIB(XonoticGameCrosshairSettingsTab, intendedWidth, float, 0.9)
        ATTRIB(XonoticGameCrosshairSettingsTab, rows, float, 13)
        ATTRIB(XonoticGameCrosshairSettingsTab, columns, float, 6.2)
@@ -19,7 +19,7 @@ void XonoticGameCrosshairSettingsTab_showNotify(entity me)
 entity makeXonoticGameCrosshairSettingsTab()
 {
        entity me;
-       me = spawnXonoticGameCrosshairSettingsTab();
+       me = NEW(XonoticGameCrosshairSettingsTab);
        me.configureDialog(me);
        return me;
 }
@@ -27,7 +27,6 @@ entity makeXonoticGameCrosshairSettingsTab()
 void XonoticGameCrosshairSettingsTab_fill(entity me)
 {
        entity e;
-       float i;
 
        // crosshair_enabled: 0 = no crosshair options, 1 = no crosshair selection, but everything else enabled, 2 = all crosshair options enabled
        // FIXME: In the future, perhaps make one global crosshair_type cvar which has 0 for disabled, 1 for custom, 2 for per weapon, etc?
@@ -40,26 +39,12 @@ void XonoticGameCrosshairSettingsTab_fill(entity me)
                me.TD(me, 1, 1, e = makeXonoticRadioButton(3, "crosshair_enabled", "2", _("Custom")));
        me.TR(me);
                me.TDempty(me, 0.1);
-               for(i = 31; i <= 42; ++i) {
-                       me.TDNoMargin(me, 1, 2 / 12, e = makeXonoticCrosshairButton(4, i), '1 1 0');
-                               setDependentAND(e, "crosshair_per_weapon", 0, 0, "crosshair_enabled", 1, 2);
-               }
-               // show a larger preview of the selected crosshair
-               me.TDempty(me, 0.1);
-               me.TDNoMargin(me, 3, 0.8, e = makeXonoticCrosshairButton(7, -1), '1 1 0'); // crosshair -1 makes this a preview
+               me.TD(me, 3, 2, e = makeXonoticCrosshairPicker());
+                       setDependentAND(e, "crosshair_per_weapon", 0, 0, "crosshair_enabled", 1, 2);
+               me.TD(me, 3, 0.9, e = makeXonoticCrosshairPreview());
                        setDependentAND(e, "crosshair_per_weapon", 0, 0, "crosshair_enabled", 1, 2);
        me.TR(me);
-               me.TDempty(me, 0.1);
-               for(i = 43; i <= 54; ++i) {
-                       me.TDNoMargin(me, 1, 2 / 12, e = makeXonoticCrosshairButton(4, i), '1 1 0');
-                               setDependentAND(e, "crosshair_per_weapon", 0, 0, "crosshair_enabled", 1, 2);
-               }
        me.TR(me);
-               me.TDempty(me, 0.1);
-               for(i = 55; i <= 66; ++i) {
-                       me.TDNoMargin(me, 1, 2 / 12, e = makeXonoticCrosshairButton(4, i), '1 1 0');
-                               setDependentAND(e, "crosshair_per_weapon", 0, 0, "crosshair_enabled", 1, 2);
-               }
        me.TR(me);
                me.TDempty(me, 0.1);
                me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Crosshair size:")));
index bb0587184be7b6ca1491c4cc2730a3eb9831091a..941daa7922ecf70ac744ba5c7ffb5f4c8c4de2e5 100644 (file)
@@ -1,9 +1,9 @@
-#ifdef INTERFACE
-CLASS(XonoticGameHUDSettingsTab) EXTENDS(XonoticTab)
-       //METHOD(XonoticGameHUDSettingsTab, toString, string(entity))
+#ifndef DIALOG_SETTINGS_GAME_HUD_H
+#define DIALOG_SETTINGS_GAME_HUD_H
+#include "tab.qc"
+CLASS(XonoticGameHUDSettingsTab, XonoticTab)
        METHOD(XonoticGameHUDSettingsTab, fill, void(entity))
        METHOD(XonoticGameHUDSettingsTab, showNotify, void(entity))
-       ATTRIB(XonoticGameHUDSettingsTab, title, string, _("HUD"))
        ATTRIB(XonoticGameHUDSettingsTab, intendedWidth, float, 0.9)
        ATTRIB(XonoticGameHUDSettingsTab, rows, float, 13)
        ATTRIB(XonoticGameHUDSettingsTab, columns, float, 6.2)
@@ -31,7 +31,7 @@ void XonoticGameHUDSettingsTab_showNotify(entity me)
 entity makeXonoticGameHUDSettingsTab()
 {
        entity me;
-       me = spawnXonoticGameHUDSettingsTab();
+       me = NEW(XonoticGameHUDSettingsTab);
        me.configureDialog(me);
        return me;
 }
index 12312c36bbe7b6b4e1e27caf235d0931fab69171..d0b460b9167ae897d238161f15c33461b1eb6b19 100644 (file)
@@ -1,5 +1,7 @@
-#ifdef INTERFACE
-CLASS(XonoticHUDConfirmDialog) EXTENDS(XonoticDialog)
+#ifndef DIALOG_SETTINGS_GAME_HUDCONFIRM_H
+#define DIALOG_SETTINGS_GAME_HUDCONFIRM_H
+#include "dialog.qc"
+CLASS(XonoticHUDConfirmDialog, XonoticDialog)
        METHOD(XonoticHUDConfirmDialog, fill, void(entity))
        ATTRIB(XonoticHUDConfirmDialog, title, string, _("Enter HUD editor"))
        ATTRIB(XonoticHUDConfirmDialog, color, vector, SKINCOLOR_DIALOG_HUDCONFIRM)
index 034608d096d396ca59142133ff54018ef5c9b62f..d52a102d4259f812fac042856d707e434fe0faea 100644 (file)
@@ -1,9 +1,9 @@
-#ifdef INTERFACE
-CLASS(XonoticGameMessageSettingsTab) EXTENDS(XonoticTab)
-       //METHOD(XonoticGameWeaponsSettingsTab, toString, string(entity))
+#ifndef DIALOG_SETTINGS_GAME_MESSAGES_H
+#define DIALOG_SETTINGS_GAME_MESSAGES_H
+#include "tab.qc"
+CLASS(XonoticGameMessageSettingsTab, XonoticTab)
        METHOD(XonoticGameMessageSettingsTab, fill, void(entity))
        METHOD(XonoticGameMessageSettingsTab, showNotify, void(entity))
-       ATTRIB(XonoticGameMessageSettingsTab, title, string, _("Messages"))
        ATTRIB(XonoticGameMessageSettingsTab, intendedWidth, float, 0.9)
        ATTRIB(XonoticGameMessageSettingsTab, rows, float, 13)
        ATTRIB(XonoticGameMessageSettingsTab, columns, float, 6)
@@ -20,7 +20,7 @@ void XonoticGameMessageSettingsTab_showNotify(entity me)
 entity makeXonoticGameMessageSettingsTab()
 {
        entity me;
-       me = spawnXonoticGameMessageSettingsTab();
+       me = NEW(XonoticGameMessageSettingsTab);
        me.configureDialog(me);
        return me;
 }
index 1f9a23f2e488c852b25073a943cfdf28ac6020d3..db3e4082c99a2cf5d3ec391dc933e8924cd8e55a 100644 (file)
@@ -1,9 +1,9 @@
-#ifdef INTERFACE
-CLASS(XonoticGameModelSettingsTab) EXTENDS(XonoticTab)
-       //METHOD(XonoticGameModelSettingsTab, toString, string(entity))
+#ifndef DIALOG_SETTINGS_GAME_MODEL_H
+#define DIALOG_SETTINGS_GAME_MODEL_H
+#include "tab.qc"
+CLASS(XonoticGameModelSettingsTab, XonoticTab)
        METHOD(XonoticGameModelSettingsTab, fill, void(entity))
        METHOD(XonoticGameModelSettingsTab, showNotify, void(entity))
-       ATTRIB(XonoticGameModelSettingsTab, title, string, _("Model"))
        ATTRIB(XonoticGameModelSettingsTab, intendedWidth, float, 0.9)
        ATTRIB(XonoticGameModelSettingsTab, rows, float, 13)
        ATTRIB(XonoticGameModelSettingsTab, columns, float, 5)
@@ -19,7 +19,7 @@ void XonoticGameModelSettingsTab_showNotify(entity me)
 entity makeXonoticGameModelSettingsTab()
 {
        entity me;
-       me = spawnXonoticGameModelSettingsTab();
+       me = NEW(XonoticGameModelSettingsTab);
        me.configureDialog(me);
        return me;
 }
index 44e741934ce1348892e7f22ae42dd5f1933a9e81..40a526d56ae863e25e25de98ea47fa27b78e994f 100644 (file)
@@ -1,9 +1,9 @@
-#ifdef INTERFACE
-CLASS(XonoticGameViewSettingsTab) EXTENDS(XonoticTab)
-       //METHOD(XonoticGameCrosshairSettingsTab, toString, string(entity))
+#ifndef DIALOG_SETTINGS_GAME_VIEW_H
+#define DIALOG_SETTINGS_GAME_VIEW_H
+#include "tab.qc"
+CLASS(XonoticGameViewSettingsTab, XonoticTab)
        METHOD(XonoticGameViewSettingsTab, fill, void(entity))
        METHOD(XonoticGameViewSettingsTab, showNotify, void(entity))
-       ATTRIB(XonoticGameViewSettingsTab, title, string, _("View"))
        ATTRIB(XonoticGameViewSettingsTab, intendedWidth, float, 0.9)
        ATTRIB(XonoticGameViewSettingsTab, rows, float, 13)
        ATTRIB(XonoticGameViewSettingsTab, columns, float, 6.2)
@@ -19,7 +19,7 @@ void XonoticGameViewSettingsTab_showNotify(entity me)
 entity makeXonoticGameViewSettingsTab()
 {
        entity me;
-       me = spawnXonoticGameViewSettingsTab();
+       me = NEW(XonoticGameViewSettingsTab);
        me.configureDialog(me);
        return me;
 }
index bc7cc7d7ff554d2aa56893dc56e08e19f136a1b1..c59a9620d477d7826198061fdd67190f5f70d91f 100644 (file)
@@ -1,9 +1,9 @@
-#ifdef INTERFACE
-CLASS(XonoticGameWeaponsSettingsTab) EXTENDS(XonoticTab)
-       //METHOD(XonoticGameWeaponsSettingsTab, toString, string(entity))
+#ifndef DIALOG_SETTINGS_GAME_WEAPONS_H
+#define DIALOG_SETTINGS_GAME_WEAPONS_H
+#include "tab.qc"
+CLASS(XonoticGameWeaponsSettingsTab, XonoticTab)
        METHOD(XonoticGameWeaponsSettingsTab, fill, void(entity))
        METHOD(XonoticGameWeaponsSettingsTab, showNotify, void(entity))
-       ATTRIB(XonoticGameWeaponsSettingsTab, title, string, _("Weapons"))
        ATTRIB(XonoticGameWeaponsSettingsTab, intendedWidth, float, 0.9)
        ATTRIB(XonoticGameWeaponsSettingsTab, rows, float, 13)
        ATTRIB(XonoticGameWeaponsSettingsTab, columns, float, 6)
@@ -20,7 +20,7 @@ void XonoticGameWeaponsSettingsTab_showNotify(entity me)
 entity makeXonoticGameWeaponsSettingsTab()
 {
        entity me;
-       me = spawnXonoticGameWeaponsSettingsTab();
+       me = NEW(XonoticGameWeaponsSettingsTab);
        me.configureDialog(me);
        return me;
 }
index b4ac6134834ba254d571ed93db991eede16e8bfd..f8e53c03a9fd069804bb0e9a37d8a4a2da6c9aef 100644 (file)
@@ -1,7 +1,8 @@
-#ifdef INTERFACE
-CLASS(XonoticInputSettingsTab) EXTENDS(XonoticTab)
+#ifndef DIALOG_SETTINGS_INPUT_H
+#define DIALOG_SETTINGS_INPUT_H
+#include "tab.qc"
+CLASS(XonoticInputSettingsTab, XonoticTab)
        METHOD(XonoticInputSettingsTab, fill, void(entity))
-       ATTRIB(XonoticInputSettingsTab, title, string, _("Input"))
        ATTRIB(XonoticInputSettingsTab, intendedWidth, float, 0.9)
        ATTRIB(XonoticInputSettingsTab, rows, float, 15.5)
        ATTRIB(XonoticInputSettingsTab, columns, float, 6.2) // added extra .2 for center space
@@ -13,7 +14,7 @@ entity makeXonoticInputSettingsTab();
 entity makeXonoticInputSettingsTab()
 {
        entity me;
-       me = spawnXonoticInputSettingsTab();
+       me = NEW(XonoticInputSettingsTab);
        me.configureDialog(me);
        return me;
 }
index aaf182fcd80e93a92e15ca4ca5af48ae27481534..d6ad2e7090a255ee66e9ee48e8de6e2c1118af6e 100644 (file)
@@ -1,5 +1,7 @@
-#ifdef INTERFACE
-CLASS(XonoticUserbindEditDialog) EXTENDS(XonoticDialog)
+#ifndef DIALOG_SETTINGS_INPUT_USERBIND_H
+#define DIALOG_SETTINGS_INPUT_USERBIND_H
+#include "dialog.qc"
+CLASS(XonoticUserbindEditDialog, XonoticDialog)
        METHOD(XonoticUserbindEditDialog, loadUserBind, void(entity, string, string, string))
        METHOD(XonoticUserbindEditDialog, fill, void(entity))
        ATTRIB(XonoticUserbindEditDialog, title, string, _("User defined key bind"))
index 2ea9c1e9c263418960a277dbd04563f0fb351501..79e196170669f430519c20fe627d15c8d85fa4c9 100644 (file)
@@ -1,7 +1,8 @@
-#ifdef INTERFACE
-CLASS(XonoticMiscSettingsTab) EXTENDS(XonoticTab)
+#ifndef DIALOG_SETTINGS_MISC_H
+#define DIALOG_SETTINGS_MISC_H
+#include "tab.qc"
+CLASS(XonoticMiscSettingsTab, XonoticTab)
        METHOD(XonoticMiscSettingsTab, fill, void(entity))
-       ATTRIB(XonoticMiscSettingsTab, title, string, _("Misc"))
        ATTRIB(XonoticMiscSettingsTab, intendedWidth, float, 0.9)
        ATTRIB(XonoticMiscSettingsTab, rows, float, 15.5)
        ATTRIB(XonoticMiscSettingsTab, columns, float, 6.2)
@@ -13,7 +14,7 @@ entity makeXonoticMiscSettingsTab();
 entity makeXonoticMiscSettingsTab()
 {
        entity me;
-       me = spawnXonoticMiscSettingsTab();
+       me = NEW(XonoticMiscSettingsTab);
        me.configureDialog(me);
        return me;
 }
index c2ea2a5b66167c8dfc366bd8361ba0238a7e9c22..af75e64b92000ee69bf9d86f22d650cae7f6f2c8 100644 (file)
@@ -1,5 +1,7 @@
-#ifdef INTERFACE
-CLASS(XonoticCvarsDialog) EXTENDS(XonoticDialog)
+#ifndef DIALOG_SETTINGS_MISC_CVARS_H
+#define DIALOG_SETTINGS_MISC_CVARS_H
+#include "dialog.qc"
+CLASS(XonoticCvarsDialog, XonoticDialog)
        METHOD(XonoticCvarsDialog, fill, void(entity))
        METHOD(XonoticCvarsDialog, showNotify, void(entity))
        ATTRIB(XonoticCvarsDialog, title, string, _("Advanced settings"))
index 8f6da0a55207b6b4c69426670ffddfa6b12d61ec..2f99321598be9001429aead38c46d7b32c464632 100644 (file)
@@ -1,5 +1,7 @@
-#ifdef INTERFACE
-CLASS(XonoticResetDialog) EXTENDS(XonoticDialog)
+#ifndef DIALOG_SETTINGS_MISC_RESET_H
+#define DIALOG_SETTINGS_MISC_RESET_H
+#include "dialog.qc"
+CLASS(XonoticResetDialog, XonoticDialog)
        METHOD(XonoticResetDialog, fill, void(entity))
        ATTRIB(XonoticResetDialog, title, string, _("Factory reset"))
        ATTRIB(XonoticResetDialog, color, vector, SKINCOLOR_DIALOG_QUIT)
index 180efccb9bdd323ba86ef8cedc490175e46cd233..35246ae1700159de66f3dc23760cf1ce93204b48 100644 (file)
@@ -1,7 +1,8 @@
-#ifdef INTERFACE
-CLASS(XonoticUserSettingsTab) EXTENDS(XonoticTab)
+#ifndef DIALOG_SETTINGS_USER_H
+#define DIALOG_SETTINGS_USER_H
+#include "tab.qc"
+CLASS(XonoticUserSettingsTab, XonoticTab)
        METHOD(XonoticUserSettingsTab, fill, void(entity))
-       ATTRIB(XonoticUserSettingsTab, title, string, _("User"))
        ATTRIB(XonoticUserSettingsTab, intendedWidth, float, 0.9)
        ATTRIB(XonoticUserSettingsTab, rows, float, 15.5)
        ATTRIB(XonoticUserSettingsTab, columns, float, 6)
@@ -13,7 +14,7 @@ entity makeXonoticUserSettingsTab();
 entity makeXonoticUserSettingsTab()
 {
        entity me;
-       me = spawnXonoticUserSettingsTab();
+       me = NEW(XonoticUserSettingsTab);
        me.configureDialog(me);
        return me;
 }
index c830b5583a04615e72f72ffe739784ea29ae16e3..0a340eaff4452b035654a596c5dbe711fd997432 100644 (file)
@@ -1,5 +1,7 @@
-#ifdef INTERFACE
-CLASS(XonoticLanguageWarningDialog) EXTENDS(XonoticDialog)
+#ifndef DIALOG_SETTINGS_USER_LANGUAGEWARNING_H
+#define DIALOG_SETTINGS_USER_LANGUAGEWARNING_H
+#include "dialog.qc"
+CLASS(XonoticLanguageWarningDialog, XonoticDialog)
        METHOD(XonoticLanguageWarningDialog, fill, void(entity)) // to be overridden by user to fill the dialog with controls
        ATTRIB(XonoticLanguageWarningDialog, title, string, _("Warning"))
        ATTRIB(XonoticLanguageWarningDialog, color, vector, SKINCOLOR_DIALOG_HUDCONFIRM)
index 36929cbd716a669170fb8cd06903ba214e05a69b..61a93f62e2696c06ff047745363e45cbb69278db 100644 (file)
@@ -1,7 +1,8 @@
-#ifdef INTERFACE
-CLASS(XonoticVideoSettingsTab) EXTENDS(XonoticTab)
+#ifndef DIALOG_SETTINGS_VIDEO_H
+#define DIALOG_SETTINGS_VIDEO_H
+#include "tab.qc"
+CLASS(XonoticVideoSettingsTab, XonoticTab)
        METHOD(XonoticVideoSettingsTab, fill, void(entity))
-       ATTRIB(XonoticVideoSettingsTab, title, string, _("Video"))
        ATTRIB(XonoticVideoSettingsTab, intendedWidth, float, 0.9)
        ATTRIB(XonoticVideoSettingsTab, rows, float, 15.5)
        ATTRIB(XonoticVideoSettingsTab, columns, float, 6.2) // added extra .2 for center space
@@ -14,7 +15,7 @@ entity makeXonoticVideoSettingsTab();
 entity makeXonoticVideoSettingsTab()
 {
        entity me;
-       me = spawnXonoticVideoSettingsTab();
+       me = NEW(XonoticVideoSettingsTab);
        me.configureDialog(me);
        return me;
 }
index 6e13f65b818ea6cb348a1d47a744e43072d33299..1620349bf58864aea5f1f462c90853469d6180a4 100644 (file)
@@ -1,5 +1,7 @@
-#ifdef INTERFACE
-CLASS(XonoticSingleplayerDialog) EXTENDS(XonoticDialog)
+#ifndef DIALOG_SINGLEPLAYER_H
+#define DIALOG_SINGLEPLAYER_H
+#include "dialog.qc"
+CLASS(XonoticSingleplayerDialog, XonoticDialog)
        METHOD(XonoticSingleplayerDialog, fill, void(entity))
        ATTRIB(XonoticSingleplayerDialog, title, string, _("Singleplayer"))
        ATTRIB(XonoticSingleplayerDialog, color, vector, SKINCOLOR_DIALOG_SINGLEPLAYER)
index 0d1c05af44a10a89281bc4c668d06dd1827608ba..bc9d1c4eae6d7cc334d601153601734daac59eb3 100644 (file)
@@ -1,5 +1,7 @@
-#ifdef INTERFACE
-CLASS(XonoticWinnerDialog) EXTENDS(XonoticDialog)
+#ifndef DIALOG_SINGLEPLAYER_WINNER_H
+#define DIALOG_SINGLEPLAYER_WINNER_H
+#include "dialog.qc"
+CLASS(XonoticWinnerDialog, XonoticDialog)
        METHOD(XonoticWinnerDialog, fill, void(entity))
        METHOD(XonoticWinnerDialog, focusEnter, void(entity))
        ATTRIB(XonoticWinnerDialog, title, string, _("Winner"))
index 1ab68c3fbe34cf16416325451690cf34542d58d3..8ed9d7ef23d0c1484d09e4fc4f18449a3b93af10 100644 (file)
@@ -1,5 +1,7 @@
-#ifdef INTERFACE
-CLASS(XonoticTeamSelectDialog) EXTENDS(XonoticRootDialog)
+#ifndef DIALOG_TEAMSELECT_H
+#define DIALOG_TEAMSELECT_H
+#include "rootdialog.qc"
+CLASS(XonoticTeamSelectDialog, XonoticRootDialog)
        METHOD(XonoticTeamSelectDialog, fill, void(entity)) // to be overridden by user to fill the dialog with controls
        METHOD(XonoticTeamSelectDialog, showNotify, void(entity))
        ATTRIB(XonoticTeamSelectDialog, title, string, _("Team Selection")) // ;)
index cc10f3da9ea5d722627ab283f2a4d6ab83d06dbc..ae202560c4b5c2de648f33d1a318cc05d45ed8ba 100644 (file)
@@ -1,5 +1,7 @@
-#ifdef INTERFACE
-CLASS(XonoticGametypeButton) EXTENDS(RadioButton)
+#ifndef GAMETYPEBUTTON_H
+#define GAMETYPEBUTTON_H
+#include "../item/radiobutton.qc"
+CLASS(XonoticGametypeButton, RadioButton)
        METHOD(XonoticGametypeButton, configureXonoticGametypeButton, void(entity, float, string, string))
        METHOD(XonoticGametypeButton, setChecked, void(entity, float))
        ATTRIB(XonoticGametypeButton, fontSize, float, SKINFONTSIZE_NORMAL)
@@ -26,7 +28,7 @@ void GameTypeButton_Click(entity me, entity other);
 entity makeXonoticGametypeButton(float theGroup, string theCvar, string theText)
 {
        entity me;
-       me = spawnXonoticGametypeButton();
+       me = NEW(XonoticGametypeButton);
        me.configureXonoticGametypeButton(me, theGroup, theCvar, theText);
        return me;
 }
index 0d36c836340f7b463d2c0af41c9197990ec67619..030af6715339257b23ddb7d4a07531f1a489635c 100644 (file)
@@ -1,8 +1,10 @@
-#ifdef INTERFACE
-CLASS(XonoticGametypeList) EXTENDS(XonoticListBox)
+#ifndef GAMETYPELIST_H
+#define GAMETYPELIST_H
+#include "listbox.qc"
+CLASS(XonoticGametypeList, XonoticListBox)
        METHOD(XonoticGametypeList, configureXonoticGametypeList, void(entity))
        ATTRIB(XonoticGametypeList, rowsPerItem, float, 2)
-       METHOD(XonoticGametypeList, drawListBoxItem, void(entity, float, vector, float))
+       METHOD(XonoticGametypeList, drawListBoxItem, void(entity, int, vector, bool, bool))
        METHOD(XonoticGametypeList, resizeNotify, void(entity, vector, vector, vector, vector))
        METHOD(XonoticGametypeList, setSelected, void(entity, float))
        METHOD(XonoticGametypeList, loadCvars, void(entity))
@@ -25,7 +27,7 @@ entity makeXonoticGametypeList();
 entity makeXonoticGametypeList(void)
 {
        entity me;
-       me = spawnXonoticGametypeList();
+       me = NEW(XonoticGametypeList);
        me.configureXonoticGametypeList(me);
        return me;
 }
@@ -34,9 +36,11 @@ void XonoticGametypeList_configureXonoticGametypeList(entity me)
        me.configureXonoticListBox(me);
        me.nItems = GameType_GetCount();
 
-       // we want the pics mipmapped
-       for(int i = 0; i < GameType_GetCount(); ++i)
-               draw_PreloadPictureWithFlags(GameType_GetIcon(i), PRECACHE_PIC_MIPMAP);
+       if(SKINBOOL_GAMETYPELIST_ICON_BLUR)
+       {
+               for(int i = 0; i < GameType_GetCount(); ++i)
+                       draw_PreloadPictureWithFlags(GameType_GetIcon(i), PRECACHE_PIC_MIPMAP);
+       }
 
        me.loadCvars(me);
 }
@@ -76,12 +80,17 @@ void XonoticGametypeList_saveCvars(entity me)
                owner.gameTypeChangeNotify(owner);
        }
 }
-void XonoticGametypeList_drawListBoxItem(entity me, float i, vector absSize, float isSelected)
+void XonoticGametypeList_drawListBoxItem(entity me, int i, vector absSize, bool isSelected, bool isFocused)
 {
        string s1, s2;
 
        if(isSelected)
                draw_Fill('0 0 0', '1 1 0', SKINCOLOR_LISTBOX_SELECTED, SKINALPHA_LISTBOX_SELECTED);
+       else if(isFocused)
+       {
+               me.focusedItemAlpha = getFadedAlpha(me.focusedItemAlpha, SKINALPHA_LISTBOX_FOCUSED, SKINFADEALPHA_LISTBOX_FOCUSED);
+               draw_Fill('0 0 0', '1 1 0', SKINCOLOR_LISTBOX_FOCUSED, me.focusedItemAlpha);
+       }
 
        draw_Picture(me.columnIconOrigin * eX, GameType_GetIcon(i), me.columnIconSize * eX + eY, '1 1 1', SKINALPHA_LISTBOX_SELECTED);
        s1 = GameType_GetName(i);
index 9f0de67b8a1deb592ddf0aff2eb8c6f5b03097d0..e8f5a8269351a4f81648181517415e6c3c8130e5 100644 (file)
@@ -1,5 +1,7 @@
-#ifdef INTERFACE
-CLASS(XonoticImage) EXTENDS(Image)
+#ifndef IMAGE_H
+#define IMAGE_H
+#include "../item/image.qc"
+CLASS(XonoticImage, Image)
        METHOD(XonoticImage, configureXonoticImage, void(entity, string, float))
 ENDCLASS(XonoticImage)
 entity makeXonoticImage(string theImage, float theAspect);
@@ -9,7 +11,7 @@ entity makeXonoticImage(string theImage, float theAspect);
 entity makeXonoticImage(string theImage, float theAspect)
 {
        entity me;
-       me = spawnXonoticImage();
+       me = NEW(XonoticImage);
        me.configureXonoticImage(me, theImage, theAspect);
        return me;
 }
index 5d7d179995028719bc107d1158edcd91678bc1e8..de1580160edb904f3de775482c9dcdc8c03cab35 100644 (file)
@@ -1,5 +1,7 @@
-#ifdef INTERFACE
-CLASS(XonoticInputBox) EXTENDS(InputBox)
+#ifndef INPUTBOX_H
+#define INPUTBOX_H
+#include "../item/inputbox.qc"
+CLASS(XonoticInputBox, InputBox)
        METHOD(XonoticInputBox, configureXonoticInputBox, void(entity, float, string))
        METHOD(XonoticInputBox, focusLeave, void(entity))
        METHOD(XonoticInputBox, setText, void(entity, string))
@@ -38,7 +40,7 @@ entity makeXonoticInputBox(float, string);
 entity makeXonoticInputBox(float doEditColorCodes, string theCvar)
 {
        entity me;
-       me = spawnXonoticInputBox();
+       me = NEW(XonoticInputBox);
        me.configureXonoticInputBox(me, doEditColorCodes, theCvar);
        return me;
 }
@@ -58,18 +60,18 @@ void XonoticInputBox_focusLeave(entity me)
 {
        me.saveCvars(me);
 }
-void XonoticInputBox_setText(entity me, string new)
+void XonoticInputBox_setText(entity me, string val)
 {
-       if(me.text != new)
+       if(me.text != val)
        {
-               SUPER(XonoticInputBox).setText(me, new);
+               SUPER(XonoticInputBox).setText(me, val);
                if(me.onChange)
                        me.onChange(me, me.onChangeEntity);
                if(me.saveImmediately)
                        me.saveCvars(me);
        }
        else
-               SUPER(XonoticInputBox).setText(me, new);
+               SUPER(XonoticInputBox).setText(me, val);
 }
 void XonoticInputBox_loadCvars(entity me)
 {
index a083207715250430fc1a9dd465b66c8c68dca477..8953b1db9b3f716e11dd0d49eb83a2566c8cf859 100644 (file)
@@ -1,8 +1,10 @@
-#ifdef INTERFACE
-CLASS(XonoticKeyBinder) EXTENDS(XonoticListBox)
+#ifndef KEYBINDER_H
+#define KEYBINDER_H
+#include "listbox.qc"
+CLASS(XonoticKeyBinder, XonoticListBox)
        METHOD(XonoticKeyBinder, configureXonoticKeyBinder, void(entity))
-       ATTRIB(XonoticKeyBinder, rowsPerItem, float, 1)
-       METHOD(XonoticKeyBinder, drawListBoxItem, void(entity, float, vector, float))
+       ATTRIB(XonoticKeyBinder, rowsPerItem, int, 1)
+       METHOD(XonoticKeyBinder, drawListBoxItem, void(entity, int, vector, bool, bool))
        METHOD(XonoticKeyBinder, doubleClickListBoxItem, void(entity, float, vector))
        METHOD(XonoticKeyBinder, resizeNotify, void(entity, vector, vector, vector, vector))
        METHOD(XonoticKeyBinder, setSelected, void(entity, float))
@@ -16,7 +18,7 @@ CLASS(XonoticKeyBinder) EXTENDS(XonoticListBox)
        ATTRIB(XonoticKeyBinder, columnKeysOrigin, float, 0)
        ATTRIB(XonoticKeyBinder, columnKeysSize, float, 0)
 
-       ATTRIB(XonoticKeyBinder, previouslySelected, float, -1)
+       ATTRIB(XonoticKeyBinder, previouslySelected, int, -1)
        ATTRIB(XonoticKeyBinder, inMouseHandler, float, 0)
        ATTRIB(XonoticKeyBinder, userbindEditButton, entity, NULL)
        ATTRIB(XonoticKeyBinder, keyGrabButton, entity, NULL)
@@ -28,21 +30,22 @@ entity makeXonoticKeyBinder();
 void KeyBinder_Bind_Change(entity btn, entity me);
 void KeyBinder_Bind_Clear(entity btn, entity me);
 void KeyBinder_Bind_Edit(entity btn, entity me);
+void KeyBinder_Bind_Reset_All(entity btn, entity me);
 #endif
 
 #ifdef IMPLEMENTATION
 
 const string KEY_NOT_BOUND_CMD = "// not bound";
 
-const float MAX_KEYS_PER_FUNCTION = 2;
-const float MAX_KEYBINDS = 256;
+const int MAX_KEYS_PER_FUNCTION = 2;
+const int MAX_KEYBINDS = 256;
 string Xonotic_KeyBinds_Functions[MAX_KEYBINDS];
 string Xonotic_KeyBinds_Descriptions[MAX_KEYBINDS];
-float Xonotic_KeyBinds_Count = -1;
+int Xonotic_KeyBinds_Count = -1;
 
 void Xonotic_KeyBinds_Read()
 {
-       float fh;
+       int fh;
        string s;
 
        Xonotic_KeyBinds_Count = 0;
@@ -65,13 +68,14 @@ void Xonotic_KeyBinds_Read()
 entity makeXonoticKeyBinder()
 {
        entity me;
-       me = spawnXonoticKeyBinder();
+       me = NEW(XonoticKeyBinder);
        me.configureXonoticKeyBinder(me);
        return me;
 }
 void replace_bind(string from, string to)
 {
-       float n, j, k;
+       int n, j;
+       float k; // not sure if float or int
        n = tokenize(findkeysforcommand(from, 0)); // uses '...' strings
        for(j = 0; j < n; ++j)
        {
@@ -130,9 +134,10 @@ void KeyBinder_Bind_Change(entity btn, entity me)
        me.clearButton.disabled = 1;
        keyGrabber = me;
 }
-void XonoticKeyBinder_keyGrabbed(entity me, float key, float ascii)
+void XonoticKeyBinder_keyGrabbed(entity me, int key, bool ascii)
 {
-       float n, j, k, nvalid;
+       int n, j, nvalid;
+       float k;
        string func;
 
        me.keyGrabButton.forcePressed = 0;
@@ -249,7 +254,7 @@ void XonoticKeyBinder_doubleClickListBoxItem(entity me, float i, vector where)
 {
        KeyBinder_Bind_Change(NULL, me);
 }
-void XonoticKeyBinder_setSelected(entity me, float i)
+void XonoticKeyBinder_setSelected(entity me, int i)
 {
        // handling of "unselectable" items
        i = floor(0.5 + bound(0, i, me.nItems - 1));
@@ -276,10 +281,9 @@ void XonoticKeyBinder_setSelected(entity me, float i)
                me.userbindEditButton.disabled = (substring(Xonotic_KeyBinds_Descriptions[i], 0, 1) != "$");
        SUPER(XonoticKeyBinder).setSelected(me, i);
 }
-float XonoticKeyBinder_keyDown(entity me, float key, float ascii, float shift)
+float XonoticKeyBinder_keyDown(entity me, int key, bool ascii, float shift)
 {
-       float r;
-       r = 1;
+       bool r = true;
        switch(key)
        {
                case K_ENTER:
@@ -298,10 +302,11 @@ float XonoticKeyBinder_keyDown(entity me, float key, float ascii, float shift)
        }
        return r;
 }
-void XonoticKeyBinder_drawListBoxItem(entity me, float i, vector absSize, float isSelected)
+void XonoticKeyBinder_drawListBoxItem(entity me, int i, vector absSize, bool isSelected, bool isFocused)
 {
        string s;
-       float j, k, n;
+       int j, n;
+       float k;
        vector theColor;
        float theAlpha;
        string func, descr;
@@ -326,6 +331,12 @@ void XonoticKeyBinder_drawListBoxItem(entity me, float i, vector absSize, float
                        else
                                draw_Fill('0 0 0', '1 1 0', SKINCOLOR_LISTBOX_SELECTED, SKINALPHA_LISTBOX_SELECTED);
                }
+               else if(isFocused)
+               {
+                       me.focusedItemAlpha = getFadedAlpha(me.focusedItemAlpha, SKINALPHA_LISTBOX_FOCUSED, SKINFADEALPHA_LISTBOX_FOCUSED);
+                       draw_Fill('0 0 0', '1 1 0', SKINCOLOR_LISTBOX_FOCUSED, me.focusedItemAlpha);
+               }
+
                theAlpha = SKINALPHA_KEYGRABBER_KEYS;
                theColor = SKINCOLOR_KEYGRABBER_KEYS;
                extraMargin = me.realFontSize.x * 0.5;
index 8aa0d2c077dd4efde44e0b94d249ba0512fc58ea..af9d75211b3987809ec4bedb3eff1e85d3813990 100644 (file)
@@ -1,8 +1,10 @@
-#ifdef INTERFACE
-CLASS(XonoticLanguageList) EXTENDS(XonoticListBox)
+#ifndef LANGUAGELIST_H
+#define LANGUAGELIST_H
+#include "listbox.qc"
+CLASS(XonoticLanguageList, XonoticListBox)
        METHOD(XonoticLanguageList, configureXonoticLanguageList, void(entity))
        ATTRIB(XonoticLanguageList, rowsPerItem, float, 1)
-       METHOD(XonoticLanguageList, drawListBoxItem, void(entity, float, vector, float))
+       METHOD(XonoticLanguageList, drawListBoxItem, void(entity, int, vector, bool, bool))
        METHOD(XonoticLanguageList, resizeNotify, void(entity, vector, vector, vector, vector))
        METHOD(XonoticLanguageList, setSelected, void(entity, float))
        METHOD(XonoticLanguageList, loadCvars, void(entity))
@@ -43,7 +45,7 @@ const float LANGPARM_COUNT = 4;
 entity makeXonoticLanguageList()
 {
        entity me;
-       me = spawnXonoticLanguageList();
+       me = NEW(XonoticLanguageList);
        me.configureXonoticLanguageList(me);
        return me;
 }
@@ -55,11 +57,16 @@ void XonoticLanguageList_configureXonoticLanguageList(entity me)
        me.loadCvars(me);
 }
 
-void XonoticLanguageList_drawListBoxItem(entity me, float i, vector absSize, float isSelected)
+void XonoticLanguageList_drawListBoxItem(entity me, int i, vector absSize, bool isSelected, bool isFocused)
 {
        string s, p;
        if(isSelected)
                draw_Fill('0 0 0', '1 1 0', SKINCOLOR_LISTBOX_SELECTED, SKINALPHA_LISTBOX_SELECTED);
+       else if(isFocused)
+       {
+               me.focusedItemAlpha = getFadedAlpha(me.focusedItemAlpha, SKINALPHA_LISTBOX_FOCUSED, SKINFADEALPHA_LISTBOX_FOCUSED);
+               draw_Fill('0 0 0', '1 1 0', SKINCOLOR_LISTBOX_FOCUSED, me.focusedItemAlpha);
+       }
 
        s = me.languageParameter(me, i, LANGPARM_NAME_LOCALIZED);
 
index 0ab574fa2f1b3869422e5b137d6a49459695580b..c4a0923858afa4ff668826089e038f0391779055 100644 (file)
@@ -1,5 +1,7 @@
-#ifdef INTERFACE
-CLASS(XonoticListBox) EXTENDS(ListBox)
+#ifndef LISTBOX_H
+#define LISTBOX_H
+#include "../item/listbox.qc"
+CLASS(XonoticListBox, ListBox)
        METHOD(XonoticListBox, configureXonoticListBox, void(entity))
        ATTRIB(XonoticListBox, fontSize, float, SKINFONTSIZE_NORMAL)
        ATTRIB(XonoticListBox, scrollbarWidth, float, SKINWIDTH_SCROLLBAR)
@@ -21,7 +23,7 @@ entity makeXonoticListBox();
 entity makeXonoticListBox()
 {
        entity me;
-       me = spawnXonoticListBox();
+       me = NEW(XonoticListBox);
        me.configureXonoticListBox(me);
        return me;
 }
index 45a0f93dcc571fee3b676a596c8348f37bfadd76..7af6e9363d3ce440dbc60d944a55b400c77d3475 100644 (file)
@@ -1,5 +1,7 @@
-#ifdef INTERFACE
-CLASS(MainWindow) EXTENDS(ModalController)
+#ifndef MAINWINDOW_H
+#define MAINWINDOW_H
+#include "../item/modalcontroller.qc"
+CLASS(MainWindow, ModalController)
        METHOD(MainWindow, configureMainWindow, void(entity))
        METHOD(MainWindow, draw, void(entity))
        ATTRIB(MainWindow, firstRunDialog, entity, NULL)
@@ -48,162 +50,165 @@ void MainWindow_configureMainWindow(entity me)
        entity n, i;
 
        // dialog run upon startup
-       me.firstRunDialog = i = spawnXonoticFirstRunDialog();
+       me.firstRunDialog = i = NEW(XonoticFirstRunDialog);
        i.configureDialog(i);
        me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
 
 
        // hud_configure dialogs
-       i = spawnXonoticHUDExitDialog();
+       i = NEW(XonoticHUDExitDialog);
        i.configureDialog(i);
        me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
 
-       i = spawnXonoticHUDNotificationDialog();
+       i = NEW(XonoticHUDNotificationDialog);
        i.configureDialog(i);
-       me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
+       me.addItemRightCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
 
-       i = spawnXonoticHUDAmmoDialog();
+       i = NEW(XonoticHUDAmmoDialog);
        i.configureDialog(i);
-       me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
+       me.addItemRightCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
 
-       i = spawnXonoticHUDHealthArmorDialog();
+       i = NEW(XonoticHUDHealthArmorDialog);
        i.configureDialog(i);
-       me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
+       me.addItemRightCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
 
-       i = spawnXonoticHUDChatDialog();
+       i = NEW(XonoticHUDChatDialog);
        i.configureDialog(i);
-       me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
+       me.addItemRightCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
 
-       i = spawnXonoticHUDModIconsDialog();
+       i = NEW(XonoticHUDModIconsDialog);
        i.configureDialog(i);
-       me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
+       me.addItemRightCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
 
-       i = spawnXonoticHUDPowerupsDialog();
+       i = NEW(XonoticHUDPowerupsDialog);
        i.configureDialog(i);
-       me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
+       me.addItemRightCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
 
-       i = spawnXonoticHUDPressedKeysDialog();
+       i = NEW(XonoticHUDPressedKeysDialog);
        i.configureDialog(i);
-       me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
+       me.addItemRightCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
 
-       i = spawnXonoticHUDRaceTimerDialog();
+       i = NEW(XonoticHUDRaceTimerDialog);
        i.configureDialog(i);
-       me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
-
-       i = spawnXonoticHUDRadarDialog();
-       i.configureDialog(i);
-       me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
+       me.addItemRightCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
 
-       i = spawnXonoticHUDScoreDialog();
+       i = NEW(XonoticHUDRadarDialog);
        i.configureDialog(i);
-       me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
+       me.addItemRightCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
 
-       i = spawnXonoticHUDTimerDialog();
+       i = NEW(XonoticHUDScoreDialog);
        i.configureDialog(i);
-       me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
+       me.addItemRightCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
 
-       i = spawnXonoticHUDVoteDialog();
+       i = NEW(XonoticHUDTimerDialog);
        i.configureDialog(i);
-       me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
+       me.addItemRightCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
 
-       i = spawnXonoticHUDWeaponsDialog();
+       i = NEW(XonoticHUDVoteDialog);
        i.configureDialog(i);
-       me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
+       me.addItemRightCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
 
-       i = spawnXonoticHUDEngineInfoDialog();
+       i = NEW(XonoticHUDWeaponsDialog);
        i.configureDialog(i);
-       me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
+       me.addItemRightCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
 
-       i = spawnXonoticHUDInfoMessagesDialog();
+       i = NEW(XonoticHUDEngineInfoDialog);
        i.configureDialog(i);
-       me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
+       me.addItemRightCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
 
-       i = spawnXonoticHUDPhysicsDialog();
+       i = NEW(XonoticHUDInfoMessagesDialog);
        i.configureDialog(i);
-       me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
+       me.addItemRightCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
 
-       me.screenshotViewerDialog = i = spawnXonoticScreenshotViewerDialog();
+       i = NEW(XonoticHUDPhysicsDialog);
        i.configureDialog(i);
-       me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
+       me.addItemRightCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
 
-       i = spawnXonoticHUDCenterprintDialog();
+       i = NEW(XonoticHUDCenterprintDialog);
        i.configureDialog(i);
-       me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
+       me.addItemRightCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
 
-       i = spawnXonoticHUDBuffsDialog();
+       i = NEW(XonoticHUDBuffsDialog);
        i.configureDialog(i);
-       me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
+       me.addItemRightCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
 
 
        // dialogs used by settings
-       me.userbindEditDialog = i = spawnXonoticUserbindEditDialog();
+       me.userbindEditDialog = i = NEW(XonoticUserbindEditDialog);
        i.configureDialog(i);
        me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
 
-       me.cvarsDialog = i = spawnXonoticCvarsDialog();
+       me.cvarsDialog = i = NEW(XonoticCvarsDialog);
        i.configureDialog(i);
        me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
 
-       me.resetDialog = i = spawnXonoticResetDialog();
+       me.resetDialog = i = NEW(XonoticResetDialog);
        i.configureDialog(i);
        me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
 
-       me.languageWarningDialog = i = spawnXonoticLanguageWarningDialog();
+       me.languageWarningDialog = i = NEW(XonoticLanguageWarningDialog);
        i.configureDialog(i);
        me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
 
-       me.hudconfirmDialog = i = spawnXonoticHUDConfirmDialog();
+       me.hudconfirmDialog = i = NEW(XonoticHUDConfirmDialog);
        i.configureDialog(i);
        me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
 
 
        // dialog used by singleplayer
-       me.winnerDialog = i = spawnXonoticWinnerDialog();
+       me.winnerDialog = i = NEW(XonoticWinnerDialog);
        i.configureDialog(i);
        me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
 
 
        // dialog used by multiplayer/join
-       me.serverInfoDialog = i = spawnXonoticServerInfoDialog();
+       me.serverInfoDialog = i = NEW(XonoticServerInfoDialog);
        i.configureDialog(i);
        me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
 
-       me.demostartconfirmDialog = i = spawnXonoticDemoStartConfirmDialog();
+       me.demostartconfirmDialog = i = NEW(XonoticDemoStartConfirmDialog);
        i.configureDialog(i);
        me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
 
-       me.demotimeconfirmDialog = i = spawnXonoticDemoTimeConfirmDialog();
+       me.demotimeconfirmDialog = i = NEW(XonoticDemoTimeConfirmDialog);
        i.configureDialog(i);
        me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
 
 
        // dialogs used by multiplayer/create
-       me.mapInfoDialog = i = spawnXonoticMapInfoDialog();
+       me.mapInfoDialog = i = NEW(XonoticMapInfoDialog);
+       i.configureDialog(i);
+       me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
+
+       me.mutatorsDialog = i = NEW(XonoticMutatorsDialog);
        i.configureDialog(i);
        me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
 
-       me.mutatorsDialog = i = spawnXonoticMutatorsDialog();
+
+       // dialogs used by multiplayer/media
+       me.screenshotViewerDialog = i = NEW(XonoticScreenshotViewerDialog);
        i.configureDialog(i);
        me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
 
+
        // mutator dialogs
-       i = spawnXonoticSandboxToolsDialog();
+       i = NEW(XonoticSandboxToolsDialog);
        i.configureDialog(i);
        me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z * SKINALPHA_DIALOG_SANDBOXTOOLS);
 
 
        // miscellaneous dialogs
-       i = spawnXonoticTeamSelectDialog();
+       i = NEW(XonoticTeamSelectDialog);
        i.configureDialog(i);
        me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
 
-       i = spawnXonoticMonsterToolsDialog();
+       i = NEW(XonoticMonsterToolsDialog);
        i.configureDialog(i);
        me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z * SKINALPHA_DIALOG_SANDBOXTOOLS);
 
 
        // main dialogs/windows
-       me.mainNexposee = n = spawnXonoticNexposee();
+       me.mainNexposee = n = NEW(XonoticNexposee);
        /*
                if(checkextension("DP_GECKO_SUPPORT"))
                {
@@ -213,28 +218,28 @@ void MainWindow_configureMainWindow(entity me)
                        n.setNexposee(n, i, '0.1 0.1 0', SKINALPHAS_MAINMENU_x, SKINALPHAS_MAINMENU_y);
                }
        */
-               i = spawnXonoticSingleplayerDialog();
+               i = NEW(XonoticSingleplayerDialog);
                i.configureDialog(i);
                n.addItemCentered(n, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
                n.setNexposee(n, i, SKINPOSITION_DIALOG_SINGLEPLAYER, SKINALPHAS_MAINMENU_x, SKINALPHAS_MAINMENU_y);
 
-               i = spawnXonoticMultiplayerDialog();
+               i = NEW(XonoticMultiplayerDialog);
                i.configureDialog(i);
                n.addItemCentered(n, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
                n.setNexposee(n, i, SKINPOSITION_DIALOG_MULTIPLAYER, SKINALPHAS_MAINMENU_x, SKINALPHAS_MAINMENU_y);
 
-               i = spawnXonoticSettingsDialog();
+               i = NEW(XonoticSettingsDialog);
                i.configureDialog(i);
                n.addItemCentered(n, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
                n.setNexposee(n, i, SKINPOSITION_DIALOG_SETTINGS, SKINALPHAS_MAINMENU_x, SKINALPHAS_MAINMENU_y);
 
-               i = spawnXonoticCreditsDialog();
+               i = NEW(XonoticCreditsDialog);
                i.configureDialog(i);
                n.addItemCentered(n, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
                n.setNexposee(n, i, SKINPOSITION_DIALOG_CREDITS, SKINALPHAS_MAINMENU_x, SKINALPHAS_MAINMENU_y);
                n.pullNexposee(n, i, eY * (SKINHEIGHT_TITLE * SKINFONTSIZE_TITLE / conheight));
 
-               i = spawnXonoticQuitDialog();
+               i = NEW(XonoticQuitDialog);
                i.configureDialog(i);
                n.addItemCentered(n, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
                n.setNexposee(n, i, SKINPOSITION_DIALOG_QUIT, SKINALPHAS_MAINMENU_x, SKINALPHAS_MAINMENU_y);
index d88ad0e8e6747beddf8296226b33a7d03fad2289..f2749abb5ce17847a399e06d7f87a0fa872637b3 100644 (file)
@@ -1,9 +1,11 @@
-#ifdef INTERFACE
-CLASS(XonoticMapList) EXTENDS(XonoticListBox)
+#ifndef MAPLIST_H
+#define MAPLIST_H
+#include "listbox.qc"
+CLASS(XonoticMapList, XonoticListBox)
        METHOD(XonoticMapList, configureXonoticMapList, void(entity))
        ATTRIB(XonoticMapList, rowsPerItem, float, 4)
        METHOD(XonoticMapList, draw, void(entity))
-       METHOD(XonoticMapList, drawListBoxItem, void(entity, float, vector, float))
+       METHOD(XonoticMapList, drawListBoxItem, void(entity, int, vector, bool, bool))
        METHOD(XonoticMapList, clickListBoxItem, void(entity, float, vector))
        METHOD(XonoticMapList, doubleClickListBoxItem, void(entity, float, vector))
        METHOD(XonoticMapList, resizeNotify, void(entity, vector, vector, vector, vector))
@@ -40,7 +42,7 @@ CLASS(XonoticMapList) EXTENDS(XonoticListBox)
 
        METHOD(XonoticMapList, destroy, void(entity))
 
-       ATTRIB(XonoticListBox, alphaBG, float, 0)
+       ATTRIB(XonoticMapList, alphaBG, float, 0)
 ENDCLASS(XonoticMapList)
 entity makeXonoticMapList();
 void MapList_All(entity btn, entity me);
@@ -57,7 +59,7 @@ void XonoticMapList_destroy(entity me)
 entity makeXonoticMapList()
 {
        entity me;
-       me = spawnXonoticMapList();
+       me = NEW(XonoticMapList);
        me.configureXonoticMapList(me);
        return me;
 }
@@ -159,7 +161,7 @@ void XonoticMapList_doubleClickListBoxItem(entity me, float i, vector where)
                }
 }
 
-void XonoticMapList_drawListBoxItem(entity me, float i, vector absSize, float isSelected)
+void XonoticMapList_drawListBoxItem(entity me, int i, vector absSize, bool isSelected, bool isFocused)
 {
        // layout: Ping, Map name, Map name, NP, TP, MP
        string s;
@@ -177,8 +179,16 @@ void XonoticMapList_drawListBoxItem(entity me, float i, vector absSize, float is
 
        if(isSelected)
                draw_Fill('0 0 0', '1 1 0', SKINCOLOR_LISTBOX_SELECTED, SKINALPHA_LISTBOX_SELECTED);
-       else if(included)
-               draw_Fill('0 0 0', '1 1 0', SKINCOLOR_MAPLIST_INCLUDEDBG, SKINALPHA_MAPLIST_INCLUDEDBG);
+       else
+       {
+               if(included)
+                       draw_Fill('0 0 0', '1 1 0', SKINCOLOR_MAPLIST_INCLUDEDBG, SKINALPHA_MAPLIST_INCLUDEDBG);
+               if(isFocused)
+               {
+                       me.focusedItemAlpha = getFadedAlpha(me.focusedItemAlpha, SKINALPHA_LISTBOX_FOCUSED, SKINFADEALPHA_LISTBOX_FOCUSED);
+                       draw_Fill('0 0 0', '1 1 0', SKINCOLOR_LISTBOX_FOCUSED, me.focusedItemAlpha);
+               }
+       }
 
        if(draw_PictureSize(strcat("/maps/", MapInfo_Map_bspname)) == '0 0 0')
                draw_Picture(me.columnPreviewOrigin * eX, "nopreview_map", me.columnPreviewSize * eX + eY, '1 1 1', theAlpha);
index b375393c02a30047a31ed6442a0c7d16d6bc4a5a..966b11a988a0e9fbb2604c682dafea668a113255 100644 (file)
@@ -1,5 +1,7 @@
-#ifdef INTERFACE
-CLASS(XonoticNexposee) EXTENDS(Nexposee)
+#ifndef NEXPOSEE_H
+#define NEXPOSEE_H
+#include "../item/nexposee.qc"
+CLASS(XonoticNexposee, Nexposee)
        METHOD(XonoticNexposee, configureXonoticNexposee, void(entity))
        METHOD(XonoticNexposee, close, void(entity))
 ENDCLASS(XonoticNexposee)
@@ -10,7 +12,7 @@ entity makeXonoticNexposee();
 entity makeXonoticNexposee()
 {
        entity me;
-       me = spawnXonoticNexposee();
+       me = NEW(XonoticNexposee);
        me.configureXonoticNexposee(me);
        return me;
 }
diff --git a/qcsrc/menu/xonotic/picker.qc b/qcsrc/menu/xonotic/picker.qc
new file mode 100644 (file)
index 0000000..dd57467
--- /dev/null
@@ -0,0 +1,207 @@
+#ifndef PICKER_H
+#define PICKER_H
+#include "../item.qc"
+CLASS(XonoticPicker, Item)
+       METHOD(XonoticPicker, configureXonoticPicker, void(entity))
+       METHOD(XonoticPicker, mousePress, float(entity, vector))
+       METHOD(XonoticPicker, mouseRelease, float(entity, vector))
+       METHOD(XonoticPicker, mouseMove, float(entity, vector))
+       METHOD(XonoticPicker, mouseDrag, float(entity, vector))
+       METHOD(XonoticPicker, keyDown, float(entity, float, float, float))
+       METHOD(XonoticPicker, draw, void(entity))
+       ATTRIB(XonoticPicker, focusable, float, 1)
+       ATTRIB(XonoticPicker, disabled, float, 0)
+       ATTRIB(XonoticPicker, alpha, float, 1)
+       ATTRIB(XonoticPicker, disabledAlpha, float, SKINALPHA_DISABLED)
+
+       ATTRIB(XonoticPicker, rows, float, 3)
+       ATTRIB(XonoticPicker, columns, float, 2)
+
+       METHOD(XonoticPicker, moveFocus, void(entity, vector, vector))
+       METHOD(XonoticPicker, cellSelect, void(entity, vector))
+       METHOD(XonoticPicker, cellDraw, void(entity, vector, vector))
+       METHOD(XonoticPicker, cellIsValid, bool(entity, vector))
+       ATTRIB(XonoticPicker, realCellSize, vector, '0 0 0')
+       ATTRIB(XonoticPicker, selectedCell, vector, '-1 -1 0')
+       ATTRIB(XonoticPicker, focusedCell, vector, '-1 -1 0')
+       ATTRIB(XonoticPicker, focusedCellAlpha, float, 0)
+       ATTRIB(XonoticPicker, focusedCellTime, float, 0)
+       ATTRIB(XonoticPicker, pressedCell, vector, '-1 -1 0')
+ENDCLASS(XonoticPicker)
+entity makeXonoticPicker();
+#endif
+
+#ifdef IMPLEMENTATION
+
+entity makeXonoticPicker()
+{
+       entity me;
+       me = NEW(XonoticPicker);
+       me.configureXonoticPicker(me);
+       return me;
+}
+
+void XonoticPicker_configureXonoticPicker(entity me)
+{
+       me.realCellSize = eX / me.columns + eY / me.rows;
+}
+
+float XonoticPicker_mouseMove(entity me, vector coords)
+{
+       vector prevFocusedCell = me.focusedCell;
+       me.focusedCell_x = floor(coords.x * me.columns);
+       me.focusedCell_y = floor(coords.y * me.rows);
+
+       if(me.focusedCell.x < 0 || me.focusedCell.y < 0 ||
+          me.focusedCell.x >= me.columns || me.focusedCell.y >= me.rows)
+       {
+               me.focusedCell = '-1 -1 0';
+               return 0;
+       }
+
+       if(me.focusedCell != prevFocusedCell)
+               me.focusedCellAlpha = SKINALPHA_LISTBOX_FOCUSED;
+
+       return 1;
+}
+
+float XonoticPicker_mouseDrag(entity me, vector coords)
+{
+       return me.mouseMove(me, coords);
+}
+
+float XonoticPicker_mousePress(entity me, vector coords)
+{
+       me.mouseMove(me, coords);
+
+       if(me.focusedCell.x >= 0)
+       {
+               me.pressed = 1;
+               me.pressedCell = me.focusedCell;
+       }
+
+       return 1;
+}
+
+float XonoticPicker_mouseRelease(entity me, vector coords)
+{
+       if(!me.pressed)
+               return 0;
+
+       me.mouseMove(me, coords);
+
+       if(me.focusedCell == me.pressedCell)
+               me.cellSelect(me, me.focusedCell);
+
+       me.pressed = 0;
+       return 1;
+}
+
+float XonoticPicker_keyDown(entity me, float key, float ascii, float shift)
+{
+       switch(key)
+       {
+               case K_END:
+               case K_KP_END:
+                       // lower left cell then left arrow to select the last valid cell
+                       me.focusedCell = eY * (me.rows - 1);
+               case K_LEFTARROW:
+               case K_KP_LEFTARROW:
+                       me.moveFocus(me, me.focusedCell, '-1 0 0');
+                       return 1;
+               case K_HOME:
+               case K_KP_HOME:
+                       // upper right cell then right arrow to select the first valid cell
+                       me.focusedCell = eX * (me.columns - 1);
+               case K_RIGHTARROW:
+               case K_KP_RIGHTARROW:
+                       me.moveFocus(me, me.focusedCell, '1 0 0');
+                       return 1;
+               case K_UPARROW:
+               case K_KP_UPARROW:
+                       me.moveFocus(me, me.focusedCell, '0 -1 0');
+                       return 1;
+               case K_DOWNARROW:
+               case K_KP_DOWNARROW:
+                       me.moveFocus(me, me.focusedCell, '0 1 0');
+                       return 1;
+               case K_ENTER:
+               case K_KP_ENTER:
+               case K_INS:
+               case K_KP_INS:
+                       me.cellSelect(me, me.focusedCell);
+                       return 1;
+       }
+       return 0;
+}
+
+void XonoticPicker_moveFocus(entity me, vector initialCell, vector step)
+{
+       me.focusedCell_x = mod(me.focusedCell.x + step.x + me.columns, me.columns);
+       me.focusedCell_y = mod(me.focusedCell.y + step.y + me.rows, me.rows);
+
+       if(me.focusedCell != initialCell) // Recursion break
+               if(!me.cellIsValid(me, me.focusedCell))
+                       me.moveFocus(me, initialCell, step);
+
+       me.focusedCellAlpha = SKINALPHA_LISTBOX_FOCUSED;
+}
+
+void XonoticPicker_cellSelect(entity me, vector cell)
+{
+       me.selectedCell = cell;
+}
+
+bool XonoticPicker_cellIsValid(entity me, vector cell)
+{
+       return true;
+}
+
+void XonoticPicker_cellDraw(entity me, vector cell, vector cellPos)
+{
+}
+
+void XonoticPicker_draw(entity me)
+{
+       float save;
+
+       me.focusable = !me.disabled;
+
+       save = draw_alpha;
+       if(me.disabled)
+               draw_alpha *= me.disabledAlpha;
+
+       vector cell, cellPos;
+       cell = '0 0 0';
+       cellPos = '0 0 0';
+
+       for(cell_y = 0; cell.y < me.rows; ++cell.y)
+       {
+               cellPos_y = mod(cell.y, me.rows) / me.rows;
+               for(cell_x = 0; cell.x < me.columns; ++cell.x)
+               {
+                       if(!me.cellIsValid(me, cell))
+                               continue;
+
+                       cellPos_x = mod(cell.x, me.columns) / me.columns;
+
+                       if(cell == me.selectedCell)
+                               draw_Fill(cellPos, me.realCellSize, SKINCOLOR_LISTBOX_SELECTED, SKINALPHA_LISTBOX_SELECTED);
+                       else if(cell == me.focusedCell && me.focused)
+                       {
+                               if(!me.pressed || me.focusedCell == me.pressedCell)
+                               {
+                                       me.focusedCellAlpha = getFadedAlpha(me.focusedCellAlpha, SKINALPHA_LISTBOX_FOCUSED, SKINFADEALPHA_LISTBOX_FOCUSED);
+                                       draw_Fill(cellPos, me.realCellSize, SKINCOLOR_LISTBOX_FOCUSED, me.focusedCellAlpha);
+                               }
+                       }
+
+                       me.cellDraw(me, cell, cellPos);
+               }
+       }
+
+       draw_alpha = save;
+
+       SUPER(XonoticPicker).draw(me);
+}
+#endif
index d4dc5af05df05e60fa6eaec11eaa50ff45e85365..db3ac8a207aae1b99524a3cc11c1aa40adfed1f1 100644 (file)
@@ -1,8 +1,10 @@
-#ifdef INTERFACE
-CLASS(XonoticPlayerList) EXTENDS(XonoticListBox)
+#ifndef PLAYERLIST_H
+#define PLAYERLIST_H
+#include "listbox.qc"
+CLASS(XonoticPlayerList, XonoticListBox)
        ATTRIB(XonoticPlayerList, rowsPerItem, float, 1)
        METHOD(XonoticPlayerList, resizeNotify, void(entity, vector, vector, vector, vector))
-       METHOD(XonoticPlayerList, drawListBoxItem, void(entity, float, vector, float))
+       METHOD(XonoticPlayerList, drawListBoxItem, void(entity, int, vector, bool, bool))
        ATTRIB(XonoticPlayerList, allowFocusSound, float, 0)
        ATTRIB(XonoticPlayerList, realFontSize, vector, '0 0 0')
        ATTRIB(XonoticPlayerList, columnNameOrigin, float, 0)
@@ -30,7 +32,7 @@ const float PLAYERPARM_COUNT = 4;
 entity makeXonoticPlayerList()
 {
        entity me;
-       me = spawnXonoticPlayerList();
+       me = NEW(XonoticPlayerList);
        me.configureXonoticListBox(me);
        return me;
 }
@@ -92,7 +94,7 @@ void XonoticPlayerList_resizeNotify(entity me, vector relOrigin, vector relSize,
        me.columnScoreOrigin = me.columnNameOrigin + me.columnNameSize + me.realFontSize.x;
 }
 
-void XonoticPlayerList_drawListBoxItem(entity me, float i, vector absSize, float isSelected)
+void XonoticPlayerList_drawListBoxItem(entity me, int i, vector absSize, bool isSelected, bool isFocused)
 {
        string s;
        string score;
index f498f8d2133cf01628bb8b4518bacc51e2588641..760e8f93d9c7c99a77e6230a5e5047363b502dfa 100644 (file)
@@ -1,5 +1,7 @@
-#ifdef INTERFACE
-CLASS(XonoticPlayerModelSelector) EXTENDS(XonoticImage)
+#ifndef PLAYERMODEL_H
+#define PLAYERMODEL_H
+#include "image.qc"
+CLASS(XonoticPlayerModelSelector, XonoticImage)
        METHOD(XonoticPlayerModelSelector, configureXonoticPlayerModelSelector, void(entity))
        METHOD(XonoticPlayerModelSelector, loadCvars, void(entity))
        METHOD(XonoticPlayerModelSelector, saveCvars, void(entity))
@@ -31,7 +33,7 @@ void PlayerModelSelector_Prev_Click(entity btn, entity me);
 entity makeXonoticPlayerModelSelector()
 {
        entity me;
-       me = spawnXonoticPlayerModelSelector();
+       me = NEW(XonoticPlayerModelSelector);
        me.configureXonoticPlayerModelSelector(me);
        return me;
 }
index fbe3c92c6793f03d25d3bede3118f9ccfd533857..5dd7b6b926d0862185524f522bd12a7513939562 100644 (file)
@@ -1,10 +1,12 @@
-#ifdef INTERFACE
-CLASS(XonoticPlayList) EXTENDS(XonoticListBox)
+#ifndef PLAYLIST_H
+#define PLAYLIST_H
+#include "listbox.qc"
+CLASS(XonoticPlayList, XonoticListBox)
        METHOD(XonoticPlayList, configureXonoticPlayList, void(entity))
        ATTRIB(XonoticPlayList, rowsPerItem, float, 1)
        METHOD(XonoticPlayList, resizeNotify, void(entity, vector, vector, vector, vector))
        METHOD(XonoticPlayList, draw, void(entity))
-       METHOD(XonoticPlayList, drawListBoxItem, void(entity, float, vector, float))
+       METHOD(XonoticPlayList, drawListBoxItem, void(entity, int, vector, bool, bool))
        METHOD(XonoticPlayList, stopSound, void(entity))
        METHOD(XonoticPlayList, startSound, void(entity, float))
        METHOD(XonoticPlayList, resumeSound, void(entity))
@@ -42,7 +44,7 @@ void NextSound_Click(entity btn, entity me);
 entity makeXonoticPlayList()
 {
        entity me;
-       me = spawnXonoticPlayList();
+       me = NEW(XonoticPlayList);
        me.configureXonoticPlayList(me);
        return me;
 }
@@ -170,11 +172,16 @@ void XonoticPlayList_draw(entity me)
        SUPER(XonoticPlayList).draw(me);
 }
 
-void XonoticPlayList_drawListBoxItem(entity me, float i, vector absSize, float isSelected)
+void XonoticPlayList_drawListBoxItem(entity me, int i, vector absSize, bool isSelected, bool isFocused)
 {
        string s;
        if(isSelected)
                draw_Fill('0 0 0', '1 1 0', SKINCOLOR_LISTBOX_SELECTED, SKINALPHA_LISTBOX_SELECTED);
+       else if(isFocused)
+       {
+               me.focusedItemAlpha = getFadedAlpha(me.focusedItemAlpha, SKINALPHA_LISTBOX_FOCUSED, SKINFADEALPHA_LISTBOX_FOCUSED);
+               draw_Fill('0 0 0', '1 1 0', SKINCOLOR_LISTBOX_FOCUSED, me.focusedItemAlpha);
+       }
 
        if(i == me.playingTrack)
        {
index 85cc4fc5c559a3c56125fcce05e8aef6f1f7bf6e..05c8238d488b8b460cb6277dcefde8604ce967e1 100644 (file)
@@ -1,5 +1,7 @@
-#ifdef INTERFACE
-CLASS(XonoticRadioButton) EXTENDS(RadioButton)
+#ifndef RADIOBUTTON_H
+#define RADIOBUTTON_H
+#include "../item/radiobutton.qc"
+CLASS(XonoticRadioButton, RadioButton)
        METHOD(XonoticRadioButton, configureXonoticRadioButton, void(entity, float, string, string, string))
        METHOD(XonoticRadioButton, draw, void(entity))
        METHOD(XonoticRadioButton, setChecked, void(entity, float))
@@ -27,7 +29,7 @@ entity makeXonoticRadioButton(float, string, string, string);
 entity makeXonoticRadioButton(float theGroup, string theCvar, string theValue, string theText)
 {
        entity me;
-       me = spawnXonoticRadioButton();
+       me = NEW(XonoticRadioButton);
        me.configureXonoticRadioButton(me, theGroup, theCvar, theValue, theText);
        return me;
 }
index e8c9db364e9d3caaa31f4ee904b82ebc08c33523..209fcade83d408af69ab57a4b8c727ba78d91810 100644 (file)
@@ -1,5 +1,7 @@
-#ifdef INTERFACE
-CLASS(XonoticRootDialog) EXTENDS(XonoticDialog)
+#ifndef ROOTDIALOG_H
+#define ROOTDIALOG_H
+#include "dialog.qc"
+CLASS(XonoticRootDialog, XonoticDialog)
        // still to be customized by user
        /*
        ATTRIB(XonoticDialog, closable, float, 1)
index a800a849486aceae4d7651f2adbaf41a4c36db40..f2eb0b00d7ee6596afe0b9b0cbe62d9a826adee9 100644 (file)
@@ -1,5 +1,7 @@
-#ifdef INTERFACE
-CLASS(XonoticScreenshotImage) EXTENDS(XonoticImage)
+#ifndef SCREENSHOTIMAGE_H
+#define SCREENSHOTIMAGE_H
+#include "image.qc"
+CLASS(XonoticScreenshotImage, XonoticImage)
        METHOD(XonoticScreenshotImage, configureXonoticScreenshotImage, void(entity))
        METHOD(XonoticScreenshotImage, load, void(entity, string))
        METHOD(XonoticScreenshotImage, draw, void(entity))
@@ -21,7 +23,7 @@ entity makeXonoticScreenshotImage();
 entity makeXonoticScreenshotImage()
 {
        entity me;
-       me = spawnXonoticScreenshotImage();
+       me = NEW(XonoticScreenshotImage);
        me.configureXonoticScreenshotImage(me);
        return me;
 }
index 225eefb249d1660579047ed82d775660dbefee41..d6fcaf86e3d0d97b0494e823ac311df0fb2183af 100644 (file)
@@ -1,11 +1,13 @@
-#ifdef INTERFACE
-CLASS(XonoticScreenshotList) EXTENDS(XonoticListBox)
+#ifndef SCREENSHOTLIST_H
+#define SCREENSHOTLIST_H
+#include "listbox.qc"
+CLASS(XonoticScreenshotList, XonoticListBox)
        METHOD(XonoticScreenshotList, configureXonoticScreenshotList, void(entity))
        ATTRIB(XonoticScreenshotList, rowsPerItem, float, 1)
        METHOD(XonoticScreenshotList, resizeNotify, void(entity, vector, vector, vector, vector))
        METHOD(XonoticScreenshotList, setSelected, void(entity, float))
        METHOD(XonoticScreenshotList, draw, void(entity))
-       METHOD(XonoticScreenshotList, drawListBoxItem, void(entity, float, vector, float))
+       METHOD(XonoticScreenshotList, drawListBoxItem, void(entity, int, vector, bool, bool))
        METHOD(XonoticScreenshotList, getScreenshots, void(entity))
        METHOD(XonoticScreenshotList, previewScreenshot, void(entity))
        METHOD(XonoticScreenshotList, startScreenshot, void(entity))
@@ -49,7 +51,7 @@ void ScreenshotList_Filter_Change(entity box, entity me);
 entity makeXonoticScreenshotList()
 {
        entity me;
-       me = spawnXonoticScreenshotList();
+       me = NEW(XonoticScreenshotList);
        me.configureXonoticScreenshotList(me);
        return me;
 }
@@ -165,11 +167,16 @@ void XonoticScreenshotList_setSelected(entity me, float i)
        }
 }
 
-void XonoticScreenshotList_drawListBoxItem(entity me, float i, vector absSize, float isSelected)
+void XonoticScreenshotList_drawListBoxItem(entity me, int i, vector absSize, bool isSelected, bool isFocused)
 {
        string s;
        if(isSelected)
                draw_Fill('0 0 0', '1 1 0', SKINCOLOR_LISTBOX_SELECTED, SKINALPHA_LISTBOX_SELECTED);
+       else if(isFocused)
+       {
+               me.focusedItemAlpha = getFadedAlpha(me.focusedItemAlpha, SKINALPHA_LISTBOX_FOCUSED, SKINFADEALPHA_LISTBOX_FOCUSED);
+               draw_Fill('0 0 0', '1 1 0', SKINCOLOR_LISTBOX_FOCUSED, me.focusedItemAlpha);
+       }
 
        s = me.screenshotName(me,i);
        s = draw_TextShortenToWidth(s, me.columnNameSize, 0, me.realFontSize);
index c6c53cc8e01f4afa88df9f5ac838840b7ed1120c..33203c52b9dc72c10f80ad23183b609494d3310a 100644 (file)
@@ -1,9 +1,11 @@
-#ifdef INTERFACE
-CLASS(XonoticServerList) EXTENDS(XonoticListBox)
+#ifndef SERVERLIST_H
+#define SERVERLIST_H
+#include "listbox.qc"
+CLASS(XonoticServerList, XonoticListBox)
        METHOD(XonoticServerList, configureXonoticServerList, void(entity))
        ATTRIB(XonoticServerList, rowsPerItem, float, 1)
        METHOD(XonoticServerList, draw, void(entity))
-       METHOD(XonoticServerList, drawListBoxItem, void(entity, float, vector, float))
+       METHOD(XonoticServerList, drawListBoxItem, void(entity, int, vector, bool, bool))
        METHOD(XonoticServerList, doubleClickListBoxItem, void(entity, float, vector))
        METHOD(XonoticServerList, resizeNotify, void(entity, vector, vector, vector, vector))
        METHOD(XonoticServerList, keyDown, float(entity, float, float, float))
@@ -126,10 +128,10 @@ void ServerList_Info_Click(entity btn, entity me);
 void ServerList_Update_favoriteButton(entity btn, entity me);
 
 // fields for category entities
-const float MAX_CATEGORIES = 9;
-const float CATEGORY_FIRST = 1;
+const int MAX_CATEGORIES = 9;
+const int CATEGORY_FIRST = 1;
 entity categories[MAX_CATEGORIES];
-float category_ent_count;
+int category_ent_count;
 .string cat_name;
 .string cat_string;
 .string cat_enoverride_string;
@@ -138,9 +140,9 @@ float category_ent_count;
 .float cat_dioverride;
 
 // fields for drawing categories
-float category_name[MAX_CATEGORIES];
-float category_item[MAX_CATEGORIES];
-float category_draw_count;
+int category_name[MAX_CATEGORIES];
+int category_item[MAX_CATEGORIES];
+int category_draw_count;
 
 #define SLIST_CATEGORIES \
        SLIST_CATEGORY(CAT_FAVORITED,    "",            "",             ZCTX(_("SLCAT^Favorites"))) \
@@ -155,7 +157,7 @@ float category_draw_count;
 
 #define SLIST_CATEGORY_AUTOCVAR(name) autocvar_menu_slist_categories_##name##_override
 #define SLIST_CATEGORY(name,enoverride,dioverride,str) \
-       float name; \
+       int name; \
        string SLIST_CATEGORY_AUTOCVAR(name) = enoverride;
 SLIST_CATEGORIES
 #undef SLIST_CATEGORY
@@ -180,7 +182,7 @@ void RegisterSLCategories()
        SLIST_CATEGORIES
        #undef SLIST_CATEGORY
 
-       float i, x, catnum;
+       int i, x, catnum;
        string s;
 
        #define PROCESS_OVERRIDE(override_string,override_field) \
@@ -219,7 +221,7 @@ void RegisterSLCategories()
 }
 
 // Supporting Functions
-entity RetrieveCategoryEnt(float catnum)
+entity RetrieveCategoryEnt(int catnum)
 {
        if((catnum > 0) && (catnum <= category_ent_count))
        {
@@ -232,10 +234,10 @@ entity RetrieveCategoryEnt(float catnum)
        }
 }
 
-float IsServerInList(string list, string srv)
+bool IsServerInList(string list, string srv)
 {
        string p;
-       float i, n;
+       int i, n;
        if(srv == "")
                return false;
        srv = netaddress_resolve(srv, 26000);
@@ -260,12 +262,12 @@ float IsServerInList(string list, string srv)
        return false;
 }
 
-float CheckCategoryOverride(float cat)
+int CheckCategoryOverride(int cat)
 {
        entity catent = RetrieveCategoryEnt(cat);
        if(catent)
        {
-               float override = (autocvar_menu_slist_categories ? catent.cat_enoverride : catent.cat_dioverride);
+               int override = (autocvar_menu_slist_categories ? catent.cat_enoverride : catent.cat_dioverride);
                if(override) { return override; }
                else { return cat; }
        }
@@ -276,10 +278,10 @@ float CheckCategoryOverride(float cat)
        }
 }
 
-float CheckCategoryForEntry(float entry)
+int CheckCategoryForEntry(int entry)
 {
        string s, k, v, modtype = "";
-       float j, m, impure = 0, freeslots = 0, sflags = 0;
+       int j, m, impure = 0, freeslots = 0, sflags = 0;
        s = gethostcachestring(SLIST_FIELD_QCSTATUS, entry);
        m = tokenizebyseparator(s, ":");
 
@@ -381,12 +383,12 @@ float CheckCategoryForEntry(float entry)
 void XonoticServerList_toggleFavorite(entity me, string srv)
 {
        string s, s0, s1, s2, srv_resolved, p;
-       float i, n, f;
+       int i, n;
+       bool f = false;
        srv_resolved = netaddress_resolve(srv, 26000);
        p = crypto_getidfp(srv_resolved);
        s = cvar_string("net_slist_favorites");
        n = tokenize_console(s);
-       f = 0;
        for(i = 0; i < n; ++i)
        {
                if(substring(argv(i), 0, 1) != "[" && strlen(argv(i)) == 44 && strstrofs(argv(i), ".", 0) < 0)
@@ -410,7 +412,7 @@ void XonoticServerList_toggleFavorite(entity me, string srv)
                cvar_set("net_slist_favorites", strcat(s0, s1, s2));
                s = cvar_string("net_slist_favorites");
                n = tokenize_console(s);
-               f = 1;
+               f = true;
                --i;
        }
 
@@ -440,7 +442,7 @@ void ServerList_Update_favoriteButton(entity btn, entity me)
 entity makeXonoticServerList()
 {
        entity me;
-       me = spawnXonoticServerList();
+       me = NEW(XonoticServerList);
        me.configureXonoticServerList(me);
        return me;
 }
@@ -456,10 +458,9 @@ void XonoticServerList_configureXonoticServerList(entity me)
        // clear list
        me.nItems = 0;
 }
-void XonoticServerList_setSelected(entity me, float i)
+void XonoticServerList_setSelected(entity me, int i)
 {
-       float save;
-       save = me.selectedItem;
+       //int save = me.selectedItem;
        SUPER(XonoticServerList).setSelected(me, i);
        /*
        if(me.selectedItem == save)
@@ -478,14 +479,15 @@ void XonoticServerList_setSelected(entity me, float i)
        me.ipAddressBox.cursorPos = strlen(me.selectedServer);
        me.ipAddressBoxFocused = -1;
 }
-void XonoticServerList_refreshServerList(entity me, float mode)
+void XonoticServerList_refreshServerList(entity me, int mode)
 {
        //print("refresh of type ", ftos(mode), "\n");
 
        if(mode >= REFRESHSERVERLIST_REFILTER)
        {
-               float m, i, n;
-               float listflags = 0;
+               float m;
+               int i, n;
+               int listflags = 0;
                string s, typestr, modstr;
 
                s = me.filterString;
@@ -573,7 +575,8 @@ void XonoticServerList_focusEnter(entity me)
 
 void XonoticServerList_draw(entity me)
 {
-       float i, found, owned;
+       int i;
+       bool found = false, owned;
 
        if(_Nex_ExtResponseSystem_BannedServersNeedsRefresh)
        {
@@ -714,7 +717,6 @@ void XonoticServerList_draw(entity me)
        me.infoButton.disabled = ((me.nItems == 0) || !owned);
        me.favoriteButton.disabled = ((me.nItems == 0) && (me.ipAddressBox.text == ""));
 
-       found = 0;
        if(me.selectedServer)
        {
                for(i = 0; i < me.nItems; ++i)
@@ -722,7 +724,7 @@ void XonoticServerList_draw(entity me)
                        if(gethostcachestring(SLIST_FIELD_CNAME, i) == me.selectedServer)
                        {
                                me.selectedItem = i;
-                               found = 1;
+                               found = true;
                                break;
                        }
                }
@@ -861,7 +863,7 @@ void ServerList_ShowFull_Click(entity box, entity me)
        me.ipAddressBox.cursorPos = 0;
        me.ipAddressBoxFocused = -1;
 }
-void XonoticServerList_setSortOrder(entity me, float fld, float direction)
+void XonoticServerList_setSortOrder(entity me, int fld, int direction)
 {
        if(me.currentSortField == fld)
                direction = -me.currentSortOrder;
@@ -922,8 +924,7 @@ void XonoticServerList_resizeNotify(entity me, vector relOrigin, vector relSize,
        me.positionSortButton(me, me.sortButton4, me.columnTypeOrigin, me.columnTypeSize, _("Type"), ServerList_TypeSort_Click);
        me.positionSortButton(me, me.sortButton5, me.columnPlayersOrigin, me.columnPlayersSize, _("Players"), ServerList_PlayerSort_Click);
 
-       float f;
-       f = me.currentSortField;
+       int f = me.currentSortField;
        if(f >= 0)
        {
                me.currentSortField = -1;
@@ -958,18 +959,20 @@ void ServerList_Info_Click(entity btn, entity me)
        vector sz = boxToGlobalSize(eY * me.itemHeight + eX * (1 - me.controlWidth), me.size);
        DialogOpenButton_Click_withCoords(me, main.serverInfoDialog, org, sz);
 }
-void XonoticServerList_doubleClickListBoxItem(entity me, float i, vector where)
+void XonoticServerList_doubleClickListBoxItem(entity me, int i, vector where)
 {
        ServerList_Connect_Click(NULL, me);
 }
-void XonoticServerList_drawListBoxItem(entity me, float i, vector absSize, float isSelected)
+void XonoticServerList_drawListBoxItem(entity me, int i, vector absSize, bool isSelected, bool isFocused)
 {
        // layout: Ping, Server name, Map name, NP, TP, MP
-       float p, q;
-       float isv4, isv6;
+       float p;
+       int q;
+       bool isv4, isv6;
        vector theColor;
        float theAlpha;
-       float m, pure, freeslots, j, sflags;
+       bool pure = false;
+       int freeslots = -1, sflags = -1, j, m;
        string s, typestr, versionstr, k, v, modname;
 
        //printf("time: %f, i: %d, item: %d, nitems: %d\n", time, i, item, me.nItems);
@@ -1016,6 +1019,11 @@ void XonoticServerList_drawListBoxItem(entity me, float i, vector absSize, float
 
        if(isSelected)
                draw_Fill('0 0 0', '1 1 0', SKINCOLOR_LISTBOX_SELECTED, SKINALPHA_LISTBOX_SELECTED);
+       else if(isFocused)
+       {
+               me.focusedItemAlpha = getFadedAlpha(me.focusedItemAlpha, SKINALPHA_LISTBOX_FOCUSED, SKINFADEALPHA_LISTBOX_FOCUSED);
+               draw_Fill('0 0 0', '1 1 0', SKINCOLOR_LISTBOX_FOCUSED, me.focusedItemAlpha);
+       }
 
        s = gethostcachestring(SLIST_FIELD_QCSTATUS, i);
        m = tokenizebyseparator(s, ":");
@@ -1026,9 +1034,7 @@ void XonoticServerList_drawListBoxItem(entity me, float i, vector absSize, float
                versionstr = argv(1);
        }
        freeslots = -1;
-       sflags = -1;
        modname = "";
-       pure = 0;
        for(j = 2; j < m; ++j)
        {
                if(argv(j) == "")
@@ -1036,11 +1042,11 @@ void XonoticServerList_drawListBoxItem(entity me, float i, vector absSize, float
                k = substring(argv(j), 0, 1);
                v = substring(argv(j), 1, -1);
                if(k == "P")
-                       pure = stof(v);
+                       pure = stob(v);
                else if(k == "S")
                        freeslots = stof(v);
                else if(k == "F")
-                       sflags = stof(v);
+                       sflags = stoi(v);
                else if(k == "M")
                        modname = v;
        }
@@ -1064,7 +1070,7 @@ void XonoticServerList_drawListBoxItem(entity me, float i, vector absSize, float
        if(modname != "CTS")
        if(modname != "NIX")
        if(modname != "NewToys")
-               pure = 0;
+               pure = false;
 
        if(gethostcachenumber(SLIST_FIELD_FREESLOTS, i) <= 0)
                theAlpha = SKINALPHA_SERVERLIST_FULL;
@@ -1076,9 +1082,9 @@ void XonoticServerList_drawListBoxItem(entity me, float i, vector absSize, float
                theAlpha = 1;
 
        p = gethostcachenumber(SLIST_FIELD_PING, i);
-       const float PING_LOW = 75;
-       const float PING_MED = 200;
-       const float PING_HIGH = 500;
+       const int PING_LOW = 75;
+       const int PING_MED = 200;
+       const int PING_HIGH = 500;
        if(p < PING_LOW)
                theColor = SKINCOLOR_SERVERLIST_LOWPING + (SKINCOLOR_SERVERLIST_MEDPING - SKINCOLOR_SERVERLIST_LOWPING) * (p / PING_LOW);
        else if(p < PING_MED)
@@ -1102,15 +1108,15 @@ void XonoticServerList_drawListBoxItem(entity me, float i, vector absSize, float
 
        s = gethostcachestring(SLIST_FIELD_CNAME, i);
 
-       isv4 = isv6 = 0;
+       isv4 = isv6 = false;
        if(substring(s, 0, 1) == "[")
        {
-               isv6 = 1;
+               isv6 = true;
                me.seenIPv6 += 1;
        }
        else if(strstrofs("0123456789", substring(s, 0, 1), 0) >= 0)
        {
-               isv4 = 1;
+               isv4 = true;
                me.seenIPv4 += 1;
        }
 
@@ -1154,57 +1160,46 @@ void XonoticServerList_drawListBoxItem(entity me, float i, vector absSize, float
        iconPos_x = (me.columnIconsSize - 3 * iconSize.x) * 0.5;
        iconPos_y = (1 - iconSize.y) * 0.5;
 
-       string n;
-
-       if (!(me.seenIPv4 && me.seenIPv6))
+       // IP
+       if(me.seenIPv4 && me.seenIPv6)
        {
-               iconPos.x += iconSize.x * 0.5;
-       }
-       else if(me.seenIPv4 && me.seenIPv6)
-       {
-               n = string_null;
                if(isv6)
-                       draw_PreloadPictureWithFlags(n = strcat(SKINGFX_SERVERLIST_ICON, "_ipv6"), 0); // PRECACHE_PIC_MIPMAP
+                       draw_Picture(iconPos, "icon_ipv6", iconSize, '1 1 1', 1);
                else if(isv4)
-                       draw_PreloadPictureWithFlags(n = strcat(SKINGFX_SERVERLIST_ICON, "_ipv4"), 0); // PRECACHE_PIC_MIPMAP
-               if(n)
-                       draw_Picture(iconPos, n, iconSize, '1 1 1', 1);
-               iconPos.x += iconSize.x;
+                       draw_Picture(iconPos, "icon_ipv4", iconSize, '1 1 1', 1);
        }
 
+       iconPos.x += iconSize.x;
+
+       // AES
        if(q > 0)
-       {
-               draw_PreloadPictureWithFlags(n = strcat(SKINGFX_SERVERLIST_ICON, "_aeslevel", ftos(q)), 0); // PRECACHE_PIC_MIPMAP
-               draw_Picture(iconPos, n, iconSize, '1 1 1', 1);
-       }
+               draw_Picture(iconPos, strcat("icon_aeslevel", ftos(q)), iconSize, '1 1 1', 1);
+
        iconPos.x += iconSize.x;
 
+       // Mod
        if(modname == "Xonotic")
        {
                if(pure == 0)
-               {
-                       draw_PreloadPictureWithFlags(n = strcat(SKINGFX_SERVERLIST_ICON, "_pure1"), PRECACHE_PIC_MIPMAP);
-                       draw_Picture(iconPos, n, iconSize, '1 1 1', 1);
-               }
+                       draw_Picture(iconPos, "icon_pure1", iconSize, '1 1 1', 1);
        }
        else
        {
-               draw_PreloadPictureWithFlags(n = strcat(SKINGFX_SERVERLIST_ICON, "_mod_", modname), PRECACHE_PIC_MIPMAP);
-               if(draw_PictureSize(n) == '0 0 0')
-                       draw_PreloadPictureWithFlags(n = strcat(SKINGFX_SERVERLIST_ICON, "_mod_"), PRECACHE_PIC_MIPMAP);
+               string icon = strcat("icon_mod_", modname);
+               if(draw_PictureSize(icon) == '0 0 0')
+                       icon = "icon_mod_";
+
                if(pure == 0)
-                       draw_Picture(iconPos, n, iconSize, '1 1 1', 1);
+                       draw_Picture(iconPos, icon, iconSize, '1 1 1', 1);
                else
-                       draw_Picture(iconPos, n, iconSize, '1 1 1', SKINALPHA_SERVERLIST_ICON_NONPURE);
+                       draw_Picture(iconPos, icon, iconSize, '1 1 1', SKINALPHA_SERVERLIST_ICON_NONPURE);
        }
+
        iconPos.x += iconSize.x;
 
+       // Stats
        if(sflags >= 0 && (sflags & SERVERFLAG_PLAYERSTATS))
-       {
-               draw_PreloadPictureWithFlags(n = strcat(SKINGFX_SERVERLIST_ICON, "_stats1"), 0); // PRECACHE_PIC_MIPMAP
-               draw_Picture(iconPos, n, iconSize, '1 1 1', 1);
-       }
-       iconPos.x += iconSize.x;
+               draw_Picture(iconPos, "icon_stats1", iconSize, '1 1 1', 1);
 
        // --------------
        //  RENDER TEXT
@@ -1231,7 +1226,7 @@ void XonoticServerList_drawListBoxItem(entity me, float i, vector absSize, float
        draw_Text(me.realUpperMargin * eY + (me.columnPlayersOrigin + (me.columnPlayersSize - draw_TextWidth(s, 0, me.realFontSize)) * 0.5) * eX, s, me.realFontSize, theColor, theAlpha, 0);
 }
 
-float XonoticServerList_keyDown(entity me, float scan, float ascii, float shift)
+bool XonoticServerList_keyDown(entity me, int scan, bool ascii, bool shift)
 {
        vector org, sz;
 
@@ -1241,7 +1236,7 @@ float XonoticServerList_keyDown(entity me, float scan, float ascii, float shift)
        if(scan == K_ENTER || scan == K_KP_ENTER)
        {
                ServerList_Connect_Click(NULL, me);
-               return 1;
+               return true;
        }
        else if(scan == K_MOUSE2 || scan == K_SPACE)
        {
@@ -1250,9 +1245,9 @@ float XonoticServerList_keyDown(entity me, float scan, float ascii, float shift)
                        m_play_click_sound(MENU_SOUND_OPEN);
                        main.serverInfoDialog.loadServerInfo(main.serverInfoDialog, me.selectedItem);
                        DialogOpenButton_Click_withCoords(me, main.serverInfoDialog, org, sz);
-                       return 1;
+                       return true;
                }
-               return 0;
+               return false;
        }
        else if(scan == K_INS || scan == K_MOUSE3 || scan == K_KP_INS)
        {
@@ -1260,28 +1255,30 @@ float XonoticServerList_keyDown(entity me, float scan, float ascii, float shift)
                {
                        me.toggleFavorite(me, me.selectedServer);
                        me.ipAddressBoxFocused = -1;
-                       return 1;
+                       return true;
                }
-               return 0;
+               return false;
        }
        else if(SUPER(XonoticServerList).keyDown(me, scan, ascii, shift))
-               return 1;
+               return true;
        else if(!me.controlledTextbox)
-               return 0;
+               return false;
        else
                return me.controlledTextbox.keyDown(me.controlledTextbox, scan, ascii, shift);
 }
 
-float XonoticServerList_getTotalHeight(entity me) {
+float XonoticServerList_getTotalHeight(entity me)
+{
        float num_normal_rows = me.nItems;
-       float num_headers = category_draw_count;
+       int num_headers = category_draw_count;
        return me.itemHeight * (num_normal_rows + me.categoriesHeight * num_headers);
 }
-float XonoticServerList_getItemAtPos(entity me, float pos) {
+int XonoticServerList_getItemAtPos(entity me, float pos)
+{
        pos = pos / me.itemHeight;
-       float i;
+       int i;
        for (i = category_draw_count - 1; i >= 0; --i) {
-               float itemidx = category_item[i];
+               int itemidx = category_item[i];
                float itempos = i * me.categoriesHeight + category_item[i];
                if (pos >= itempos + me.categoriesHeight + 1)
                        return itemidx + 1 + floor(pos - (itempos + me.categoriesHeight + 1));
@@ -1291,10 +1288,11 @@ float XonoticServerList_getItemAtPos(entity me, float pos) {
        // No category matches? Note that category 0 is... 0. Therefore no headings exist at all.
        return floor(pos);
 }
-float XonoticServerList_getItemStart(entity me, float item) {
-       float i;
+float XonoticServerList_getItemStart(entity me, int item)
+{
+       int i;
        for (i = category_draw_count - 1; i >= 0; --i) {
-               float itemidx = category_item[i];
+               int itemidx = category_item[i];
                float itempos = i * me.categoriesHeight + category_item[i];
                if (item >= itemidx + 1)
                        return (itempos + me.categoriesHeight + 1 + item - (itemidx + 1)) * me.itemHeight;
@@ -1304,8 +1302,9 @@ float XonoticServerList_getItemStart(entity me, float item) {
        // No category matches? Note that category 0 is... 0. Therefore no headings exist at all.
        return item * me.itemHeight;
 }
-float XonoticServerList_getItemHeight(entity me, float item) {
-       float i;
+float XonoticServerList_getItemHeight(entity me, int item)
+{
+       int i;
        for (i = 0; i < category_draw_count; ++i) {
                // Matches exactly the headings with increased height.
                if (item == category_item[i])
index 9990c83fe162ee2c2ab4f37ea7e1c43a1fcf24ce..7400b379f6c52fca110bb8387b7b9b21ef4845df 100644 (file)
@@ -1,9 +1,11 @@
-#ifdef INTERFACE
-CLASS(XonoticSkinList) EXTENDS(XonoticListBox)
+#ifndef SKINLIST_H
+#define SKINLIST_H
+#include "listbox.qc"
+CLASS(XonoticSkinList, XonoticListBox)
        METHOD(XonoticSkinList, configureXonoticSkinList, void(entity))
        ATTRIB(XonoticSkinList, rowsPerItem, float, 4)
        METHOD(XonoticSkinList, resizeNotify, void(entity, vector, vector, vector, vector))
-       METHOD(XonoticSkinList, drawListBoxItem, void(entity, float, vector, float))
+       METHOD(XonoticSkinList, drawListBoxItem, void(entity, int, vector, bool, bool))
        METHOD(XonoticSkinList, getSkins, void(entity))
        METHOD(XonoticSkinList, setSkin, void(entity))
        METHOD(XonoticSkinList, loadCvars, void(entity))
@@ -42,7 +44,7 @@ const float SKINPARM_COUNT = 4;
 entity makeXonoticSkinList()
 {
        entity me;
-       me = spawnXonoticSkinList();
+       me = NEW(XonoticSkinList);
        me.configureXonoticSkinList(me);
        return me;
 }
@@ -83,7 +85,7 @@ string XonoticSkinList_skinParameter(entity me, float i, float key)
 void XonoticSkinList_getSkins(entity me)
 {
        float glob, buf, i, n, fh;
-       string s;
+       string s, name;
 
        buf = buf_create();
        glob = search_begin("gfx/menu/*/skinvalues.txt", true, true);
@@ -98,7 +100,8 @@ void XonoticSkinList_getSkins(entity me)
        for(i = 0; i < n; ++i)
        {
                s = search_getfilename(glob, i);
-               bufstr_set(buf, i * SKINPARM_COUNT + SKINPARM_NAME, substring(s, 9, strlen(s) - 24)); // the * part
+               name = substring(s, 9, strlen(s) - 24); // the * part
+               bufstr_set(buf, i * SKINPARM_COUNT + SKINPARM_NAME, name);
                bufstr_set(buf, i * SKINPARM_COUNT + SKINPARM_TITLE, _("<TITLE>"));
                bufstr_set(buf, i * SKINPARM_COUNT + SKINPARM_AUTHOR, _("<AUTHOR>"));
                if(draw_PictureSize(strcat("/gfx/menu/", substring(s, 9, strlen(s) - 24), "/skinpreview")) == '0 0 0')
@@ -115,7 +118,12 @@ void XonoticSkinList_getSkins(entity me)
                {
                        // these two are handled by skinlist.qc
                        if(substring(s, 0, 6) == "title ")
-                               bufstr_set(buf, i * SKINPARM_COUNT + SKINPARM_TITLE, substring(s, 6, strlen(s) - 6));
+                       {
+                               if (name == cvar_defstring("menu_skin"))
+                                       bufstr_set(buf, i * SKINPARM_COUNT + SKINPARM_TITLE, strcat(substring(s, 6, strlen(s) - 6), " (", _("Default"), ")"));
+                               else
+                                       bufstr_set(buf, i * SKINPARM_COUNT + SKINPARM_TITLE, substring(s, 6, strlen(s) - 6));
+                       }
                        else if(substring(s, 0, 7) == "author ")
                                bufstr_set(buf, i * SKINPARM_COUNT + SKINPARM_AUTHOR, substring(s, 7, strlen(s) - 7));
                }
@@ -149,12 +157,17 @@ void XonoticSkinList_resizeNotify(entity me, vector relOrigin, vector relSize, v
        me.columnNameSize = 1 - me.columnPreviewSize - 2 * me.realFontSize.x;
 }
 
-void XonoticSkinList_drawListBoxItem(entity me, float i, vector absSize, float isSelected)
+void XonoticSkinList_drawListBoxItem(entity me, int i, vector absSize, bool isSelected, bool isFocused)
 {
        string s;
 
        if(isSelected)
                draw_Fill('0 0 0', '1 1 0', SKINCOLOR_LISTBOX_SELECTED, SKINALPHA_LISTBOX_SELECTED);
+       else if(isFocused)
+       {
+               me.focusedItemAlpha = getFadedAlpha(me.focusedItemAlpha, SKINALPHA_LISTBOX_FOCUSED, SKINFADEALPHA_LISTBOX_FOCUSED);
+               draw_Fill('0 0 0', '1 1 0', SKINCOLOR_LISTBOX_FOCUSED, me.focusedItemAlpha);
+       }
 
        s = me.skinParameter(me, i, SKINPARM_PREVIEW);
        draw_Picture(me.columnPreviewOrigin * eX, s, me.columnPreviewSize * eX + eY, '1 1 1', 1);
index d63fe1c336c8ae2d2577803b67bd12cbfe59b5cb..d95cac7e9eebedce1ddb3c4df75369e06b4a0251 100644 (file)
@@ -1,5 +1,7 @@
-#ifdef INTERFACE
-CLASS(XonoticSlider) EXTENDS(Slider)
+#ifndef SLIDER_H
+#define SLIDER_H
+#include "../item/slider.qc"
+CLASS(XonoticSlider, Slider)
        METHOD(XonoticSlider, configureXonoticSlider, void(entity, float, float, float, string))
        METHOD(XonoticSlider, setValue, void(entity, float))
        ATTRIB(XonoticSlider, fontSize, float, SKINFONTSIZE_NORMAL)
@@ -28,7 +30,7 @@ entity makeXonoticSlider(float, float, float, string);
 entity makeXonoticSlider(float theValueMin, float theValueMax, float theValueStep, string theCvar)
 {
        entity me;
-       me = spawnXonoticSlider();
+       me = NEW(XonoticSlider);
        me.configureXonoticSlider(me, theValueMin, theValueMax, theValueStep, theCvar);
        return me;
 }
index 07632320ed29d89da88f90d7e914c00576833b35..29d2a86ac94425cc4ce88f0da4107735368acd6a 100644 (file)
@@ -1,7 +1,9 @@
 #include "../../warpzonelib/mathlib.qh"
 
-#ifdef INTERFACE
-CLASS(XonoticDecibelsSlider) EXTENDS(XonoticSlider)
+#ifndef SLIDER_DECIBELS_H
+#define SLIDER_DECIBELS_H
+#include "slider.qc"
+CLASS(XonoticDecibelsSlider, XonoticSlider)
        METHOD(XonoticDecibelsSlider, loadCvars, void(entity))
        METHOD(XonoticDecibelsSlider, saveCvars, void(entity))
        METHOD(XonoticDecibelsSlider, valueToText, string(entity, float))
@@ -42,7 +44,7 @@ float fromDecibelOfSquare(float f, float mi)
 entity makeXonoticDecibelsSlider(float theValueMin, float theValueMax, float theValueStep, string theCvar)
 {
        entity me;
-       me = spawnXonoticDecibelsSlider();
+       me = NEW(XonoticDecibelsSlider);
        me.configureXonoticSlider(me, theValueMin, theValueMax, theValueStep, theCvar);
        return me;
 }
index 818dcb84b842c2ad2dd7c9b9456ecbbcd22e5e0b..9a098165e47eb4666c692a483255a4aced7eb0e7 100644 (file)
@@ -1,5 +1,7 @@
-#ifdef INTERFACE
-CLASS(XonoticParticlesSlider) EXTENDS(XonoticTextSlider)
+#ifndef SLIDER_PARTICLES_H
+#define SLIDER_PARTICLES_H
+#include "textslider.qc"
+CLASS(XonoticParticlesSlider, XonoticTextSlider)
        METHOD(XonoticParticlesSlider, configureXonoticParticlesSlider, void(entity))
        METHOD(XonoticParticlesSlider, loadCvars, void(entity))
        METHOD(XonoticParticlesSlider, saveCvars, void(entity))
@@ -11,7 +13,7 @@ entity makeXonoticParticlesSlider();
 entity makeXonoticParticlesSlider()
 {
        entity me;
-       me = spawnXonoticParticlesSlider();
+       me = NEW(XonoticParticlesSlider);
        me.configureXonoticParticlesSlider(me);
        return me;
 }
index ddedc4bab2901e2cd077a60c475aef525f223e80..f663f7dd6d3be0f91f7a5cbffb87e9b3ec1af526 100644 (file)
@@ -1,5 +1,7 @@
-#ifdef INTERFACE
-CLASS(XonoticPicmipSlider) EXTENDS(XonoticTextSlider)
+#ifndef SLIDER_PICMIP_H
+#define SLIDER_PICMIP_H
+#include "textslider.qc"
+CLASS(XonoticPicmipSlider, XonoticTextSlider)
        METHOD(XonoticPicmipSlider, configureXonoticPicmipSlider, void(entity))
        METHOD(XonoticPicmipSlider, draw, void(entity))
        METHOD(XonoticPicmipSlider, autofix, void(entity))
@@ -12,7 +14,7 @@ entity makeXonoticPicmipSlider(); // note: you still need to call addValue and c
 entity makeXonoticPicmipSlider()
 {
        entity me;
-       me = spawnXonoticPicmipSlider();
+       me = NEW(XonoticPicmipSlider);
        me.configureXonoticPicmipSlider(me);
        return me;
 }
index c1443628106e7b4b2947d8a86c669d6c2a2a5e88..3d1f8302f18695c902d61d3ae93987ea6dadd680 100644 (file)
@@ -1,5 +1,7 @@
-#ifdef INTERFACE
-CLASS(XonoticResolutionSlider) EXTENDS(XonoticTextSlider)
+#ifndef SLIDER_RESOLUTION_H
+#define SLIDER_RESOLUTION_H
+#include "textslider.qc"
+CLASS(XonoticResolutionSlider, XonoticTextSlider)
        METHOD(XonoticResolutionSlider, configureXonoticResolutionSlider, void(entity))
        METHOD(XonoticResolutionSlider, loadResolutions, void(entity, float))
        METHOD(XonoticResolutionSlider, addResolution, void(entity, float, float, float))
@@ -83,7 +85,7 @@ float updateConwidths(float width, float height, float pixelheight)
 entity makeXonoticResolutionSlider()
 {
        entity me;
-       me = spawnXonoticResolutionSlider();
+       me = NEW(XonoticResolutionSlider);
        me.configureXonoticResolutionSlider(me);
        return me;
 }
index 39f91f933cf734ccdbee07587f8f9757e94c1f19..4d30c64f008a195502f1cbb12d0508ec7ddc017d 100644 (file)
@@ -1,5 +1,7 @@
-#ifdef INTERFACE
-CLASS(XonoticScoreboardFadeTimeSlider) EXTENDS(XonoticTextSlider)
+#ifndef SLIDER_SBFADETIME_H
+#define SLIDER_SBFADETIME_H
+#include "textslider.qc"
+CLASS(XonoticScoreboardFadeTimeSlider, XonoticTextSlider)
        METHOD(XonoticScoreboardFadeTimeSlider, configureXonoticScoreboardFadeTimeSlider, void(entity))
        METHOD(XonoticScoreboardFadeTimeSlider, loadCvars, void(entity))
        METHOD(XonoticScoreboardFadeTimeSlider, saveCvars, void(entity))
@@ -11,7 +13,7 @@ entity makeXonoticScoreboardFadeTimeSlider();
 entity makeXonoticScoreboardFadeTimeSlider()
 {
        entity me;
-       me = spawnXonoticScoreboardFadeTimeSlider();
+       me = NEW(XonoticScoreboardFadeTimeSlider);
        me.configureXonoticScoreboardFadeTimeSlider(me);
        return me;
 }
index e443a53efb42ddcab91cd3d1df8804df0d8b0777..2b98c5fe52296a8f287c4294a3766019487262ea 100644 (file)
@@ -1,9 +1,11 @@
-#ifdef INTERFACE
-CLASS(XonoticSoundList) EXTENDS(XonoticListBox)
+#ifndef SOUNDLIST_H
+#define SOUNDLIST_H
+#include "listbox.qc"
+CLASS(XonoticSoundList, XonoticListBox)
        METHOD(XonoticSoundList, configureXonoticSoundList, void(entity))
        ATTRIB(XonoticSoundList, rowsPerItem, float, 1)
        METHOD(XonoticSoundList, resizeNotify, void(entity, vector, vector, vector, vector))
-       METHOD(XonoticSoundList, drawListBoxItem, void(entity, float, vector, float))
+       METHOD(XonoticSoundList, drawListBoxItem, void(entity, int, vector, bool, bool))
        METHOD(XonoticSoundList, getSounds, void(entity))
        METHOD(XonoticSoundList, soundName, string(entity, float))
        METHOD(XonoticSoundList, doubleClickListBoxItem, void(entity, float, vector))
@@ -38,7 +40,7 @@ void SoundList_Menu_Track_Reset(entity box, entity me);
 entity makeXonoticSoundList()
 {
        entity me;
-       me = spawnXonoticSoundList();
+       me = NEW(XonoticSoundList);
        me.configureXonoticSoundList(me);
        return me;
 }
@@ -101,11 +103,16 @@ void XonoticSoundList_resizeNotify(entity me, vector relOrigin, vector relSize,
        me.columnNameSize = 1 - me.columnNameOrigin - me.realFontSize.x;
 }
 
-void XonoticSoundList_drawListBoxItem(entity me, float i, vector absSize, float isSelected)
+void XonoticSoundList_drawListBoxItem(entity me, int i, vector absSize, bool isSelected, bool isFocused)
 {
        string s;
        if(isSelected)
                draw_Fill('0 0 0', '1 1 0', SKINCOLOR_LISTBOX_SELECTED, SKINALPHA_LISTBOX_SELECTED);
+       else if(isFocused)
+       {
+               me.focusedItemAlpha = getFadedAlpha(me.focusedItemAlpha, SKINALPHA_LISTBOX_FOCUSED, SKINFADEALPHA_LISTBOX_FOCUSED);
+               draw_Fill('0 0 0', '1 1 0', SKINCOLOR_LISTBOX_FOCUSED, me.focusedItemAlpha);
+       }
 
        s = me.soundName(me,i);
        if(s == cvar_string("menu_cdtrack")) // current menu track
index 99c850f13558e456d599b2ba333816748431dcba..d9a22ec6e78f1a8e71aeadf9d3824f44069664c1 100644 (file)
@@ -1,12 +1,14 @@
 #include "../../common/counting.qh"
 #include "../../common/playerstats.qh"
 
-#ifdef INTERFACE
-CLASS(XonoticStatsList) EXTENDS(XonoticListBox)
+#ifndef STATSLIST_H
+#define STATSLIST_H
+#include "listbox.qc"
+CLASS(XonoticStatsList, XonoticListBox)
        METHOD(XonoticStatsList, configureXonoticStatsList, void(entity))
        ATTRIB(XonoticStatsList, rowsPerItem, float, 1.4)
        METHOD(XonoticStatsList, resizeNotify, void(entity, vector, vector, vector, vector))
-       METHOD(XonoticStatsList, drawListBoxItem, void(entity, float, vector, float))
+       METHOD(XonoticStatsList, drawListBoxItem, void(entity, int, vector, bool, bool))
        METHOD(XonoticStatsList, getStats, void(entity))
        METHOD(XonoticStatsList, doubleClickListBoxItem, void(entity, float, vector))
        METHOD(XonoticStatsList, keyDown, float(entity, float, float, float))
@@ -32,7 +34,7 @@ entity makeXonoticStatsList();
 entity makeXonoticStatsList()
 {
        entity me;
-       me = spawnXonoticStatsList();
+       me = NEW(XonoticStatsList);
        me.configureXonoticStatsList(me);
        return me;
 }
@@ -313,10 +315,15 @@ void XonoticStatsList_resizeNotify(entity me, vector relOrigin, vector relSize,
 #endif
 }
 
-void XonoticStatsList_drawListBoxItem(entity me, float i, vector absSize, float isSelected)
+void XonoticStatsList_drawListBoxItem(entity me, int i, vector absSize, bool isSelected, bool isFocused)
 {
        if(isSelected)
                draw_Fill('0 0 0', '1 1 0', SKINCOLOR_LISTBOX_SELECTED, SKINALPHA_LISTBOX_SELECTED);
+       else if(isFocused)
+       {
+               me.focusedItemAlpha = getFadedAlpha(me.focusedItemAlpha, SKINALPHA_LISTBOX_FOCUSED, SKINFADEALPHA_LISTBOX_FOCUSED);
+               draw_Fill('0 0 0', '1 1 0', SKINCOLOR_LISTBOX_FOCUSED, me.focusedItemAlpha);
+       }
 
        string data = bufstr_get(me.listStats, i);
        string s = car(data);
index d1a867a2f88817253b5285838a772c444caf9994..0383c7aae6fd53483ebb677486efceab44584b6f 100644 (file)
@@ -1,5 +1,7 @@
-#ifdef INTERFACE
-CLASS(XonoticTab) EXTENDS(Tab)
+#ifndef TAB_H
+#define TAB_H
+#include "../item/tab.qc"
+CLASS(XonoticTab, Tab)
        // still to be customized by user
        /*
        ATTRIB(XonoticTab, intendedWidth, float, 0)
@@ -15,7 +17,6 @@ CLASS(XonoticTab) EXTENDS(Tab)
        ATTRIB(XonoticTab, columnSpacing, float, SKINMARGIN_COLUMNS) // pixels
        ATTRIB(XonoticTab, rowSpacing, float, SKINMARGIN_ROWS) // pixels
        ATTRIB(XonoticTab, rowHeight, float, SKINFONTSIZE_NORMAL * SKINHEIGHT_NORMAL) // pixels
-       ATTRIB(XonoticTab, titleHeight, float, SKINFONTSIZE_TITLE * SKINHEIGHT_TITLE) // pixels
 
        ATTRIB(XonoticTab, backgroundImage, string, string_null)
 ENDCLASS(XonoticTab)
index 1faa625aee83c607a4af8eab55117a0ddde091ea..c95424b177018ff2ac5ed1375531c0dac7e453de 100644 (file)
@@ -1,5 +1,7 @@
-#ifdef INTERFACE
-CLASS(XonoticTabController) EXTENDS(ModalController)
+#ifndef TABCONTROLLER_H
+#define TABCONTROLLER_H
+#include "../item/modalcontroller.qc"
+CLASS(XonoticTabController, ModalController)
        METHOD(XonoticTabController, configureXonoticTabController, void(entity, float))
        METHOD(XonoticTabController, makeTabButton, entity(entity, string, entity))
        ATTRIB(XonoticTabController, rows, float, 0)
@@ -13,7 +15,7 @@ entity makeXonoticTabController(float theRows);
 entity makeXonoticTabController(float theRows)
 {
        entity me;
-       me = spawnXonoticTabController();
+       me = NEW(XonoticTabController);
        me.configureXonoticTabController(me, theRows);
        return me;
 }
index cb54da19e21b81f901cea7d1e5c697ecfdbfe5d1..e33182f2dadf584316cf97dc5839d01fc171c515 100644 (file)
@@ -1,5 +1,7 @@
-#ifdef INTERFACE
-CLASS(XonoticTextLabel) EXTENDS(Label)
+#ifndef TEXTLABEL_H
+#define TEXTLABEL_H
+#include "../item/label.qc"
+CLASS(XonoticTextLabel, Label)
        METHOD(XonoticTextLabel, configureXonoticTextLabel, void(entity, float, string))
        METHOD(XonoticTextLabel, draw, void(entity))
        ATTRIB(XonoticTextLabel, fontSize, float, SKINFONTSIZE_NORMAL)
@@ -7,13 +9,14 @@ CLASS(XonoticTextLabel) EXTENDS(Label)
        ATTRIB(XonoticTextLabel, disabledAlpha, float, SKINALPHA_DISABLED)
 ENDCLASS(XonoticTextLabel)
 entity makeXonoticTextLabel(float theAlign, string theText);
+entity makeXonoticHeaderLabel(string theText);
 #endif
 
 #ifdef IMPLEMENTATION
 entity makeXonoticTextLabel(float theAlign, string theText)
 {
        entity me;
-       me = spawnXonoticTextLabel();
+       me = NEW(XonoticTextLabel);
        me.configureXonoticTextLabel(me, theAlign, theText);
        return me;
 }
index dabd1b1a6bacba2fd479e2d2b6fba021661147b1..47d9eb44dc7fbaffa0fd310b868534f204cc2b90 100644 (file)
@@ -1,5 +1,7 @@
-#ifdef INTERFACE
-CLASS(XonoticTextSlider) EXTENDS(TextSlider)
+#ifndef TEXTSLIDER_H
+#define TEXTSLIDER_H
+#include "../item/textslider.qc"
+CLASS(XonoticTextSlider, TextSlider)
        METHOD(XonoticTextSlider, configureXonoticTextSlider, void(entity, string))
        METHOD(XonoticTextSlider, setValue, void(entity, float))
        METHOD(XonoticTextSlider, configureXonoticTextSliderValues, void(entity))
@@ -29,7 +31,7 @@ entity makeXonoticTextSlider(string); // note: you still need to call addValue a
 entity makeXonoticTextSlider(string theCvar)
 {
        entity me;
-       me = spawnXonoticTextSlider();
+       me = NEW(XonoticTextSlider);
        me.configureXonoticTextSlider(me, theCvar);
        return me;
 }
index 330b2bb726a0e89ccc19822ee8c8af0182b82e0e..a50fb4cb193b89ebd755b8f3ea7315003b7b5de4 100644 (file)
@@ -1,4 +1,12 @@
+#include "util.qh"
+#include "../menu.qh"
+#include "../oo/base.qh"
+#include "../../common/campaign_common.qh"
+#include "../../common/constants.qh"
+#include "../../common/mapinfo.qh"
 #include "../../common/urllib.qh"
+#include "../../common/util.qh"
+#include "../../common/command/generic.qh"
 
 float GL_CheckExtension(string ext)
 {
@@ -43,6 +51,7 @@ string getZonedTooltipForIdentifier(string s)
        return string_null;
 }
 
+.entity parent, firstChild, nextSibling;
 void forAllDescendants(entity root, void(entity, entity) funcPre, void(entity, entity) funcPost, entity pass)
 {
        depthfirst(root, parent, firstChild, nextSibling, funcPre, funcPost, pass);
@@ -52,11 +61,15 @@ void forAllDescendants(entity root, void(entity, entity) funcPre, void(entity, e
 void SUB_Null_ee(entity e1, entity e2)
 {
 }
+
+.void(entity) saveCvars;
 void saveCvarsOf(entity ignore, entity e)
 {
        if(e.saveCvars)
                e.saveCvars(e);
 }
+
+.void(entity) loadCvars;
 void loadCvarsOf(entity ignore, entity e)
 {
        if(e.loadCvars)
@@ -135,6 +148,7 @@ void makeCallback(entity e, entity cbent, void(entity, entity) cbfunc)
 .string cvarString_setDependent;
 .string cvarValue_setDependent;
 .float(entity) func_setDependent;
+.bool disabled;
 void setDependent_Check(entity e)
 {
        float f;
@@ -181,6 +195,7 @@ void setDependent_Draw(entity e)
        setDependent_Check(e);
        e.draw_setDependent(e);
 }
+.void(entity) draw;
 void setDependent(entity e, string theCvarName, float theCvarMin, float theCvarMax)
 {
        e.draw_setDependent = e.draw;
@@ -529,6 +544,8 @@ void postMenuDraw()
                draw_CenterText('0.5 0.1 0', sprintf(_("^1%s TEST BUILD"), autocvar_menu_watermark), globalToBoxSize('32 32 0', draw_scale), '1 1 1', 0.05, 1);
        }
 }
+void DialogOpenButton_Click_withCoords(entity button, entity tab, vector theOrigin, vector theSize);
+.entity winnerDialog;
 void preMenuDraw()
 {
        vector fs, sz = '0 0 0', line, mid;
@@ -648,20 +665,20 @@ float updateCompression()
 
 // note: include only those that should be in the menu!
 #define GAMETYPES \
-       GAMETYPE(MAPINFO_TYPE_ASSAULT) \
+       GAMETYPE(MAPINFO_TYPE_DEATHMATCH) \
+       GAMETYPE(MAPINFO_TYPE_TEAM_DEATHMATCH) \
        GAMETYPE(MAPINFO_TYPE_CTF) \
        GAMETYPE(MAPINFO_TYPE_CA) \
-       GAMETYPE(MAPINFO_TYPE_DEATHMATCH) \
-       GAMETYPE(MAPINFO_TYPE_DOMINATION) \
        GAMETYPE(MAPINFO_TYPE_FREEZETAG) \
        GAMETYPE(MAPINFO_TYPE_KEEPAWAY) \
        GAMETYPE(MAPINFO_TYPE_KEYHUNT) \
        GAMETYPE(MAPINFO_TYPE_LMS) \
+       GAMETYPE(MAPINFO_TYPE_DOMINATION) \
        GAMETYPE(MAPINFO_TYPE_NEXBALL) \
        GAMETYPE(MAPINFO_TYPE_ONSLAUGHT) \
+       GAMETYPE(MAPINFO_TYPE_ASSAULT) \
        if (cvar("developer")) GAMETYPE(MAPINFO_TYPE_RACE) \
        GAMETYPE(MAPINFO_TYPE_CTS) \
-       GAMETYPE(MAPINFO_TYPE_TEAM_DEATHMATCH) \
        //GAMETYPE(MAPINFO_TYPE_INVASION) \
        /* nothing */
 
@@ -709,6 +726,18 @@ string GameType_GetIcon(int cnt)
        return "";
 }
 
+.void(entity) TR;
+.void(entity, float, float, entity) TD;
+.void(entity, float) TDempty;
+entity makeXonoticTextLabel(float theAlign, string theText);
+entity makeXonoticTextSlider(string);
+.void(entity, string, string) addValue;
+.void(entity) configureXonoticTextSliderValues;
+entity makeXonoticColorpickerString(string theCvar, string theDefaultCvar);
+entity makeXonoticCheckBoxString(string, string, string, string);
+entity makeXonoticCheckBox(float, string, string);
+.bool sendCvars;
+
 void dialog_hudpanel_common_notoggle(entity me, string panelname)
 {
        float i;
@@ -768,6 +797,15 @@ void dialog_hudpanel_common_notoggle(entity me, string panelname)
                                e.configureXonoticTextSliderValues(e);
 }
 
+float getFadedAlpha(float currentAlpha, float startAlpha, float targetAlpha)
+{
+       if(startAlpha < targetAlpha)
+               currentAlpha = min(currentAlpha + frametime * 0.5, targetAlpha);
+       else
+               currentAlpha = max(currentAlpha - frametime * 0.5, targetAlpha);
+       return currentAlpha;
+}
+
 void CheckSendCvars(entity me, string cvarnamestring)
 {
        if(me.sendCvars)
index 80803f8544df735f4363112b466441da3ad34f35..2564a86ed4b724f69640797542b083109d1fd4c5 100644 (file)
@@ -48,6 +48,8 @@ void dialog_hudpanel_common_notoggle(entity me, string panelname);
                me.TD(me, 1, 4, e = makeXonoticCheckBox(0, strzone(strcat("hud_panel_", panelname)), _("Enable panel"))); \
        DIALOG_HUDPANEL_COMMON_NOTOGGLE()
 
+float getFadedAlpha(float currentAlpha, float startAlpha, float targetAlpha);
+
 string _Nex_ExtResponseSystem_BannedServers;
 float _Nex_ExtResponseSystem_BannedServersNeedsRefresh;
 string _Nex_ExtResponseSystem_PromotedServers;
index a7d71f0d2cf5db902dd9106f9e7985477ecd7453..2a8f3aa0332a2da23f409fe14a6217f989d2e19c 100644 (file)
@@ -1,5 +1,7 @@
-#ifdef INTERFACE
-CLASS(XonoticWeaponarenaCheckBox) EXTENDS(CheckBox)
+#ifndef WEAPONARENACHECKBOX_H
+#define WEAPONARENACHECKBOX_H
+#include "../item/checkbox.qc"
+CLASS(XonoticWeaponarenaCheckBox, CheckBox)
        METHOD(XonoticWeaponarenaCheckBox, configureXonoticWeaponarenaCheckBox, void(entity, string, string))
        METHOD(XonoticWeaponarenaCheckBox, setChecked, void(entity, float))
        ATTRIB(XonoticWeaponarenaCheckBox, fontSize, float, SKINFONTSIZE_NORMAL)
@@ -16,7 +18,7 @@ entity makeXonoticWeaponarenaCheckBox(string, string);
 entity makeXonoticWeaponarenaCheckBox(string theWeapon, string theText)
 {
        entity me;
-       me = spawnXonoticWeaponarenaCheckBox();
+       me = NEW(XonoticWeaponarenaCheckBox);
        me.configureXonoticWeaponarenaCheckBox(me, theWeapon, theText);
        return me;
 }
index 1d3b897fc055664f9ed1a3cf98765ed8ae9ad4ee..adc7fc2115bb4634dbae79b6fab9236d286fa05b 100644 (file)
@@ -1,10 +1,12 @@
-#ifdef INTERFACE
-CLASS(XonoticWeaponsList) EXTENDS(XonoticListBox)
+#ifndef WEAPONSLIST_H
+#define WEAPONSLIST_H
+#include "listbox.qc"
+CLASS(XonoticWeaponsList, XonoticListBox)
        METHOD(XonoticWeaponsList, configureXonoticWeaponsList, void(entity))
        METHOD(XonoticWeaponsList, toString, string(entity))
        ATTRIB(XonoticWeaponsList, rowsPerItem, float, 1)
        METHOD(XonoticWeaponsList, draw, void(entity))
-       METHOD(XonoticWeaponsList, drawListBoxItem, void(entity, float, vector, float))
+       METHOD(XonoticWeaponsList, drawListBoxItem, void(entity, int, vector, bool, bool))
        METHOD(XonoticWeaponsList, resizeNotify, void(entity, vector, vector, vector, vector))
        METHOD(XonoticWeaponsList, keyDown, float(entity, float, float, float))
        ATTRIB(XonoticWeaponsList, realFontSize, vector, '0 0 0')
@@ -20,7 +22,7 @@ void WeaponsList_MoveDown_Click(entity box, entity me);
 entity makeXonoticWeaponsList()
 {
        entity me;
-       me = spawnXonoticWeaponsList();
+       me = NEW(XonoticWeaponsList);
        me.configureXonoticWeaponsList(me);
        return me;
 }
@@ -65,9 +67,8 @@ void XonoticWeaponsList_resizeNotify(entity me, vector relOrigin, vector relSize
 }
 float XonoticWeaponsList_mouseDrag(entity me, vector pos)
 {
-       float f, i;
-       i = me.selectedItem;
-       f = SUPER(XonoticWeaponsList).mouseDrag(me, pos);
+       int i = me.selectedItem;
+       float f = SUPER(XonoticWeaponsList).mouseDrag(me, pos);
 
        if(me.pressed != 1) // don't change priority if the person is just scrolling
        {
@@ -91,11 +92,16 @@ string XonoticWeaponsList_toString(entity me)
        }
        return substring(s, 0, strlen(s) - 2);
 }
-void XonoticWeaponsList_drawListBoxItem(entity me, float i, vector absSize, float isSelected)
+void XonoticWeaponsList_drawListBoxItem(entity me, int i, vector absSize, bool isSelected, bool isFocused)
 {
        entity e;
        if(isSelected)
                draw_Fill('0 0 0', '1 1 0', SKINCOLOR_LISTBOX_SELECTED, SKINALPHA_LISTBOX_SELECTED);
+       else if(isFocused)
+       {
+               me.focusedItemAlpha = getFadedAlpha(me.focusedItemAlpha, SKINALPHA_LISTBOX_FOCUSED, SKINFADEALPHA_LISTBOX_FOCUSED);
+               draw_Fill('0 0 0', '1 1 0', SKINCOLOR_LISTBOX_FOCUSED, me.focusedItemAlpha);
+       }
        e = get_weaponinfo(stof(argv(i)));
        string msg = e.message;
        if(e.spawnflags & WEP_FLAG_MUTATORBLOCKED)
diff --git a/qcsrc/server/_all.qh b/qcsrc/server/_all.qh
new file mode 100644 (file)
index 0000000..a331362
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef SERVER_ALL_H
+#define SERVER_ALL_H
+
+#include "autocvars.qh"
+#include "constants.qh"
+#include "defs.qh"
+#include "miscfunctions.qh"
+
+#include "../dpdefs/progsdefs.qh"
+#include "../dpdefs/dpextensions.qh"
+
+#endif
index dab5fa30087248413d00907f4fea25b483bfffd7..1e6759684a593df5fea8690173ee76946d2b4fbe 100644 (file)
 
 void mean_accumulate(entity e, .float a, .float c, float mean, float value, float weight)
 {
-       if(weight == 0)
+       if (weight == 0)
                return;
-       if(mean == 0)
-               e.a *= pow(value, weight);
+       if (mean == 0)
+               e.(a) *= pow(value, weight);
        else
-               e.a += pow(value, mean) * weight;
-       e.c += weight;
+               e.(a) += pow(value, mean) * weight;
+       e.(c) += weight;
 }
 
 float mean_evaluate(entity e, .float a, .float c, float mean)
 {
-       if(e.c == 0)
+       if (e.(c) == 0)
                return 0;
-       if(mean == 0)
-               return pow(e.a, 1.0 / e.c);
+       if (mean == 0)
+               return pow(e.(a), 1.0 / e.(c));
        else
-               return pow(e.a / e.c, 1.0 / mean);
+               return pow(e.(a) / e.(c), 1.0 / mean);
 }
 
 #define MEAN_ACCUMULATE(prefix,v,w) mean_accumulate(self,prefix##_accumulator,prefix##_count,prefix##_mean,v,w)
index 6f8f0f487e0c7e811cd425d7ceb9da8dcc93ec63..f4fe2058b9790db8bba4c311597bb8940b6bb421 100644 (file)
@@ -3,7 +3,7 @@
 #elif defined(SVQC)
        #include "../dpdefs/progsdefs.qh"
     #include "../dpdefs/dpextensions.qh"
-    #include "vehicles/vehicles_def.qh"
+    #include "vehicles/vehicle.qh"
     #include "antilag.qh"
 #endif
 
@@ -65,10 +65,8 @@ vector lerpv(float t0, vector v0, float t1, vector v1, float t)
 
 vector antilag_takebackorigin(entity e, float t)
 {
-       float i0, i1;
-
-       i0 = antilag_find(e, t);
-       if(i0 < 0)
+       int i0 = antilag_find(e, t);
+       if (i0 < 0)
        {
                // IN THE PRESENT
                if(e.antilag_takenback)
@@ -76,8 +74,8 @@ vector antilag_takebackorigin(entity e, float t)
                else
                        return e.origin;
        }
-       i1 = i0 + 1;
-       if(i1 >= ANTILAG_MAX_ORIGINS)
+       int i1 = i0 + 1;
+       if (i1 >= ANTILAG_MAX_ORIGINS)
                i1 = 0;
 
        return lerpv(e.(antilag_times[i0]), e.(antilag_origins[i0]), e.(antilag_times[i1]), e.(antilag_origins[i1]), t);
@@ -127,10 +125,8 @@ void antilag_restore(entity e)
 
 void antilag_clear(entity e)
 {
-       float i;
-
        antilag_restore(e);
-       for(i = 0; i < ANTILAG_MAX_ORIGINS; ++i)
+       for (int i = 0; i < ANTILAG_MAX_ORIGINS; ++i)
        {
                e.(antilag_times[i]) = -2342;
                e.(antilag_origins[i]) = e.origin;
index e4f02cd90eab5d7dbe1e4e772ccc31e6814d3ff9..fdb014710b16d6f513f2c09d57a39c899dfca735 100644 (file)
@@ -128,12 +128,12 @@ float autocvar_g_balance_keyhunt_delay_tracking;
 float autocvar_g_balance_keyhunt_dropvelocity;
 float autocvar_g_balance_keyhunt_maxdist;
 float autocvar_g_balance_keyhunt_protecttime;
-float autocvar_g_balance_keyhunt_score_capture;
-float autocvar_g_balance_keyhunt_score_carrierfrag;
-float autocvar_g_balance_keyhunt_score_collect;
-float autocvar_g_balance_keyhunt_score_destroyed;
-float autocvar_g_balance_keyhunt_score_destroyed_ownfactor;
-float autocvar_g_balance_keyhunt_score_push;
+int autocvar_g_balance_keyhunt_score_capture;
+int autocvar_g_balance_keyhunt_score_carrierfrag;
+int autocvar_g_balance_keyhunt_score_collect;
+int autocvar_g_balance_keyhunt_score_destroyed;
+int autocvar_g_balance_keyhunt_score_destroyed_ownfactor;
+int autocvar_g_balance_keyhunt_score_push;
 float autocvar_g_balance_keyhunt_throwvelocity;
 float autocvar_g_balance_kill_delay;
 float autocvar_g_balance_kill_antispam;
@@ -145,18 +145,18 @@ float autocvar_g_balance_nexball_secondary_force;
 float autocvar_g_balance_nexball_secondary_lifetime;
 float autocvar_g_balance_nexball_secondary_refire;
 float autocvar_g_balance_nexball_secondary_speed;
-float autocvar_g_balance_nix_ammo_cells;
-float autocvar_g_balance_nix_ammo_plasma;
-float autocvar_g_balance_nix_ammo_fuel;
-float autocvar_g_balance_nix_ammo_nails;
-float autocvar_g_balance_nix_ammo_rockets;
-float autocvar_g_balance_nix_ammo_shells;
-float autocvar_g_balance_nix_ammoincr_cells;
-float autocvar_g_balance_nix_ammoincr_plasma;
-float autocvar_g_balance_nix_ammoincr_fuel;
-float autocvar_g_balance_nix_ammoincr_nails;
-float autocvar_g_balance_nix_ammoincr_rockets;
-float autocvar_g_balance_nix_ammoincr_shells;
+int autocvar_g_balance_nix_ammo_cells;
+int autocvar_g_balance_nix_ammo_plasma;
+int autocvar_g_balance_nix_ammo_fuel;
+int autocvar_g_balance_nix_ammo_nails;
+int autocvar_g_balance_nix_ammo_rockets;
+int autocvar_g_balance_nix_ammo_shells;
+int autocvar_g_balance_nix_ammoincr_cells;
+int autocvar_g_balance_nix_ammoincr_plasma;
+int autocvar_g_balance_nix_ammoincr_fuel;
+int autocvar_g_balance_nix_ammoincr_nails;
+int autocvar_g_balance_nix_ammoincr_rockets;
+int autocvar_g_balance_nix_ammoincr_shells;
 float autocvar_g_balance_nix_incrtime;
 float autocvar_g_balance_nix_roundtime;
 float autocvar_g_balance_pause_armor_rot;
@@ -179,8 +179,8 @@ float autocvar_g_balance_powerup_strength_selfforce;
 float autocvar_g_balance_powerup_strength_time;
 float autocvar_g_balance_superweapons_time;
 float autocvar_g_balance_selfdamagepercent;
-float autocvar_g_balance_teams;
-float autocvar_g_balance_teams_prevent_imbalance;
+bool autocvar_g_balance_teams;
+bool autocvar_g_balance_teams_prevent_imbalance;
 float autocvar_g_balance_teams_scorefactor;
 float autocvar_g_ballistics_density_corpse;
 float autocvar_g_ballistics_density_player;
@@ -190,47 +190,47 @@ float autocvar_g_ban_default_masksize;
 float autocvar_g_ban_sync_interval;
 float autocvar_g_ban_sync_timeout;
 string autocvar_g_ban_sync_trusted_servers;
-float autocvar_g_ban_sync_trusted_servers_verify;
+bool autocvar_g_ban_sync_trusted_servers_verify;
 string autocvar_g_ban_sync_uri;
 string autocvar_g_banned_list;
-float autocvar_g_banned_list_idmode;
-float autocvar_g_bastet;
-float autocvar_g_botclip_collisions;
-float autocvar_g_bugrigs;
+bool autocvar_g_banned_list_idmode;
+bool autocvar_g_bastet;
+bool autocvar_g_botclip_collisions;
+bool autocvar_g_bugrigs;
 float autocvar_g_ca_damage2score_multiplier;
-float autocvar_g_ca_point_leadlimit;
-float autocvar_g_ca_point_limit;
+int autocvar_g_ca_point_leadlimit;
+int autocvar_g_ca_point_limit;
 float autocvar_g_ca_round_timelimit;
-float autocvar_g_ca_spectate_enemies;
-float autocvar_g_ca_teams;
-float autocvar_g_ca_teams_override;
-float autocvar_g_ca_team_spawns;
+bool autocvar_g_ca_spectate_enemies;
+int autocvar_g_ca_teams;
+int autocvar_g_ca_teams_override;
+bool autocvar_g_ca_team_spawns;
 float autocvar_g_ca_warmup;
-float autocvar_g_campaign;
+bool autocvar_g_campaign;
 #define autocvar_g_campaign_forceteam cvar("g_campaign_forceteam")
-float autocvar_g_campaign_skill;
-float autocvar_g_casings;
-float autocvar_g_changeteam_banned;
+int autocvar_g_campaign_skill;
+int autocvar_g_casings;
+bool autocvar_g_changeteam_banned;
 float autocvar_g_chat_flood_burst;
 float autocvar_g_chat_flood_burst_team;
 float autocvar_g_chat_flood_burst_tell;
 float autocvar_g_chat_flood_lmax;
 float autocvar_g_chat_flood_lmax_team;
 float autocvar_g_chat_flood_lmax_tell;
-float autocvar_g_chat_flood_notify_flooder;
+bool autocvar_g_chat_flood_notify_flooder;
 float autocvar_g_chat_flood_spl;
 float autocvar_g_chat_flood_spl_team;
 float autocvar_g_chat_flood_spl_tell;
-float autocvar_g_chat_nospectators;
-float autocvar_g_chat_teamcolors;
-float autocvar_g_chat_tellprivacy;
-float autocvar_g_ctf_allow_vehicle_carry;
-float autocvar_g_ctf_allow_vehicle_touch;
-float autocvar_g_ctf_allow_monster_touch;
-float autocvar_g_ctf_throw;
+int autocvar_g_chat_nospectators;
+bool autocvar_g_chat_teamcolors;
+bool autocvar_g_chat_tellprivacy;
+bool autocvar_g_ctf_allow_vehicle_carry;
+bool autocvar_g_ctf_allow_vehicle_touch;
+bool autocvar_g_ctf_allow_monster_touch;
+bool autocvar_g_ctf_throw;
 float autocvar_g_ctf_throw_angle_max;
 float autocvar_g_ctf_throw_angle_min;
-float autocvar_g_ctf_throw_punish_count;
+int autocvar_g_ctf_throw_punish_count;
 float autocvar_g_ctf_throw_punish_delay;
 float autocvar_g_ctf_throw_punish_time;
 float autocvar_g_ctf_throw_strengthmultiplier;
@@ -238,31 +238,31 @@ float autocvar_g_ctf_throw_velocity_forward;
 float autocvar_g_ctf_throw_velocity_up;
 float autocvar_g_ctf_drop_velocity_up;
 float autocvar_g_ctf_drop_velocity_side;
-float autocvar_g_ctf_portalteleport;
-float autocvar_g_ctf_pass;
+bool autocvar_g_ctf_portalteleport;
+bool autocvar_g_ctf_pass;
 float autocvar_g_ctf_pass_arc;
 float autocvar_g_ctf_pass_arc_max;
 float autocvar_g_ctf_pass_directional_max;
 float autocvar_g_ctf_pass_directional_min;
 float autocvar_g_ctf_pass_radius;
 float autocvar_g_ctf_pass_wait;
-float autocvar_g_ctf_pass_request;
+bool autocvar_g_ctf_pass_request;
 float autocvar_g_ctf_pass_turnrate;
 float autocvar_g_ctf_pass_timelimit;
 float autocvar_g_ctf_pass_velocity;
-float autocvar_g_ctf_dynamiclights;
+bool autocvar_g_ctf_dynamiclights;
 string autocvar_g_ctf_flag_blue_model;
-float autocvar_g_ctf_flag_blue_skin;
+int autocvar_g_ctf_flag_blue_skin;
 float autocvar_g_ctf_flag_collect_delay;
 float autocvar_g_ctf_flag_damageforcescale;
-float autocvar_g_ctf_flag_dropped_waypoint;
+int autocvar_g_ctf_flag_dropped_waypoint;
 float autocvar_g_ctf_flag_dropped_floatinwater;
-float autocvar_g_ctf_flag_glowtrails;
+bool autocvar_g_ctf_flag_glowtrails;
 float autocvar_g_ctf_flag_health;
 string autocvar_g_ctf_flag_red_model;
-float autocvar_g_ctf_flag_red_skin;
+int autocvar_g_ctf_flag_red_skin;
 float autocvar_g_ctf_flag_return_time;
-float autocvar_g_ctf_flag_return_when_unreachable;
+bool autocvar_g_ctf_flag_return_when_unreachable;
 float autocvar_g_ctf_flag_return_damage;
 float autocvar_g_ctf_flag_return_dropped;
 float autocvar_g_ctf_flagcarrier_auto_helpme_damage;
@@ -272,82 +272,82 @@ float autocvar_g_ctf_flagcarrier_selfforcefactor;
 float autocvar_g_ctf_flagcarrier_damagefactor;
 float autocvar_g_ctf_flagcarrier_forcefactor;
 //float autocvar_g_ctf_flagcarrier_waypointforenemy_spotting;
-float autocvar_g_ctf_fullbrightflags;
-float autocvar_g_ctf_ignore_frags;
-float autocvar_g_ctf_score_capture;
-float autocvar_g_ctf_score_capture_assist;
-float autocvar_g_ctf_score_kill;
-float autocvar_g_ctf_score_penalty_drop;
-//float autocvar_g_ctf_score_penalty_suicidedrop;
-float autocvar_g_ctf_score_penalty_returned;
-float autocvar_g_ctf_score_pickup_base;
-float autocvar_g_ctf_score_pickup_dropped_early;
-float autocvar_g_ctf_score_pickup_dropped_late;
-float autocvar_g_ctf_score_return;
+bool autocvar_g_ctf_fullbrightflags;
+bool autocvar_g_ctf_ignore_frags;
+int autocvar_g_ctf_score_capture;
+int autocvar_g_ctf_score_capture_assist;
+int autocvar_g_ctf_score_kill;
+int autocvar_g_ctf_score_penalty_drop;
+//int autocvar_g_ctf_score_penalty_suicidedrop;
+int autocvar_g_ctf_score_penalty_returned;
+int autocvar_g_ctf_score_pickup_base;
+int autocvar_g_ctf_score_pickup_dropped_early;
+int autocvar_g_ctf_score_pickup_dropped_late;
+int autocvar_g_ctf_score_return;
 float autocvar_g_ctf_shield_force;
 float autocvar_g_ctf_shield_max_ratio;
-float autocvar_g_ctf_shield_min_negscore;
-float autocvar_g_ctf_stalemate;
-float autocvar_g_ctf_stalemate_endcondition;
+int autocvar_g_ctf_shield_min_negscore;
+bool autocvar_g_ctf_stalemate;
+int autocvar_g_ctf_stalemate_endcondition;
 float autocvar_g_ctf_stalemate_time;
-float autocvar_g_ctf_reverse;
+bool autocvar_g_ctf_reverse;
 float autocvar_g_ctf_dropped_capture_delay;
 float autocvar_g_ctf_dropped_capture_radius;
 float autocvar_g_cts_finish_kill_delay;
-float autocvar_g_cts_selfdamage;
-float autocvar_g_debug_bot_commands;
-float autocvar_g_domination_default_teams;
-float autocvar_g_domination_disable_frags;
-float autocvar_g_domination_point_amt;
-float autocvar_g_domination_point_fullbright;
-float autocvar_g_domination_point_leadlimit;
-float autocvar_g_domination_roundbased;
-float autocvar_g_domination_roundbased_point_limit;
+bool autocvar_g_cts_selfdamage;
+bool autocvar_g_debug_bot_commands;
+int autocvar_g_domination_default_teams;
+bool autocvar_g_domination_disable_frags;
+int autocvar_g_domination_point_amt;
+bool autocvar_g_domination_point_fullbright;
+int autocvar_g_domination_point_leadlimit;
+bool autocvar_g_domination_roundbased;
+int autocvar_g_domination_roundbased_point_limit;
 float autocvar_g_domination_round_timelimit;
 float autocvar_g_domination_warmup;
 #define autocvar_g_domination_point_limit cvar("g_domination_point_limit")
 float autocvar_g_domination_point_rate;
-float autocvar_g_domination_teams_override;
-float autocvar_g_forced_respawn;
+int autocvar_g_domination_teams_override;
+bool autocvar_g_forced_respawn;
 string autocvar_g_forced_team_blue;
 string autocvar_g_forced_team_otherwise;
 string autocvar_g_forced_team_pink;
 string autocvar_g_forced_team_red;
 string autocvar_g_forced_team_yellow;
-float autocvar_g_freezetag_frozen_damage_trigger;
+bool autocvar_g_freezetag_frozen_damage_trigger;
 float autocvar_g_freezetag_frozen_force;
 float autocvar_g_freezetag_frozen_maxtime;
 float autocvar_g_freezetag_revive_falldamage;
 float autocvar_g_freezetag_revive_falldamage_health;
-float autocvar_g_freezetag_revive_nade;
+bool autocvar_g_freezetag_revive_nade;
 float autocvar_g_freezetag_revive_nade_health;
-float autocvar_g_freezetag_point_leadlimit;
-float autocvar_g_freezetag_point_limit;
+int autocvar_g_freezetag_point_leadlimit;
+int autocvar_g_freezetag_point_limit;
 float autocvar_g_freezetag_revive_extra_size;
 float autocvar_g_freezetag_revive_speed;
 float autocvar_g_freezetag_revive_clearspeed;
 float autocvar_g_freezetag_round_timelimit;
-float autocvar_g_freezetag_teams;
-float autocvar_g_freezetag_teams_override;
-float autocvar_g_freezetag_team_spawns;
+int autocvar_g_freezetag_teams;
+int autocvar_g_freezetag_teams_override;
+bool autocvar_g_freezetag_team_spawns;
 float autocvar_g_freezetag_warmup;
 #define autocvar_g_friendlyfire cvar("g_friendlyfire")
 #define autocvar_g_friendlyfire_virtual cvar("g_friendlyfire_virtual")
 #define autocvar_g_friendlyfire_virtual_force cvar("g_friendlyfire_virtual_force")
-float autocvar_g_full_getstatus_responses;
-float autocvar_g_fullbrightitems;
-float autocvar_g_fullbrightplayers;
+bool autocvar_g_full_getstatus_responses;
+bool autocvar_g_fullbrightitems;
+bool autocvar_g_fullbrightplayers;
 #define autocvar_g_grappling_hook cvar("g_grappling_hook")
-float autocvar_g_grappling_hook_tarzan;
-float autocvar_g_hitplots;
+int autocvar_g_grappling_hook_tarzan;
+bool autocvar_g_hitplots;
 string autocvar_g_hitplots_individuals;
 float autocvar_g_jetpack_acceleration_side;
 float autocvar_g_jetpack_acceleration_up;
 float autocvar_g_jetpack_antigravity;
-float autocvar_g_jetpack_fuel;
+int autocvar_g_jetpack_fuel;
 float autocvar_g_jetpack_maxspeed_side;
 float autocvar_g_jetpack_maxspeed_up;
-float autocvar_g_keepaway_ballcarrier_effects;
+int autocvar_g_keepaway_ballcarrier_effects;
 float autocvar_g_keepaway_ballcarrier_damage;
 float autocvar_g_keepaway_ballcarrier_force;
 float autocvar_g_keepaway_ballcarrier_highspeed;
@@ -357,61 +357,61 @@ float autocvar_g_keepaway_noncarrier_damage;
 float autocvar_g_keepaway_noncarrier_force;
 float autocvar_g_keepaway_noncarrier_selfdamage;
 float autocvar_g_keepaway_noncarrier_selfforce;
-float autocvar_g_keepaway_noncarrier_warn;
-float autocvar_g_keepaway_score_bckill;
-float autocvar_g_keepaway_score_killac;
-float autocvar_g_keepaway_score_timepoints;
+bool autocvar_g_keepaway_noncarrier_warn;
+int autocvar_g_keepaway_score_bckill;
+int autocvar_g_keepaway_score_killac;
+int autocvar_g_keepaway_score_timepoints;
 float autocvar_g_keepaway_score_timeinterval;
 float autocvar_g_keepawayball_damageforcescale;
-float autocvar_g_keepawayball_effects;
+int autocvar_g_keepawayball_effects;
 float autocvar_g_keepawayball_respawntime;
-float autocvar_g_keepawayball_trail_color;
-float autocvar_g_keyhunt_point_leadlimit;
+int autocvar_g_keepawayball_trail_color;
+int autocvar_g_keyhunt_point_leadlimit;
 #define autocvar_g_keyhunt_point_limit cvar("g_keyhunt_point_limit")
-float autocvar_g_keyhunt_teams;
-float autocvar_g_keyhunt_teams_override;
-float autocvar_g_lms_extra_lives;
-float autocvar_g_lms_join_anytime;
-float autocvar_g_lms_last_join;
+int autocvar_g_keyhunt_teams;
+int autocvar_g_keyhunt_teams_override;
+int autocvar_g_lms_extra_lives;
+bool autocvar_g_lms_join_anytime;
+int autocvar_g_lms_last_join;
 #define autocvar_g_lms_lives_override cvar("g_lms_lives_override")
-float autocvar_g_lms_regenerate;
+bool autocvar_g_lms_regenerate;
 #define autocvar_g_maplist cvar_string("g_maplist")
-float autocvar_g_maplist_check_waypoints;
-float autocvar_g_maplist_index;
+bool autocvar_g_maplist_check_waypoints;
+int autocvar_g_maplist_index;
 string autocvar_g_maplist_mostrecent;
-float autocvar_g_maplist_mostrecent_count;
-float autocvar_g_maplist_selectrandom;
+int autocvar_g_maplist_mostrecent_count;
+bool autocvar_g_maplist_selectrandom;
 float autocvar_g_maplist_shuffle;
 #define autocvar_g_maplist_votable cvar("g_maplist_votable")
-float autocvar_g_maplist_votable_abstain;
+bool autocvar_g_maplist_votable_abstain;
 float autocvar_g_maplist_votable_keeptwotime;
-float autocvar_g_maplist_votable_nodetail;
+bool autocvar_g_maplist_votable_nodetail;
 string autocvar_g_maplist_votable_screenshot_dir;
-float autocvar_g_maplist_votable_suggestions;
-float autocvar_g_maplist_votable_suggestions_override_mostrecent;
+bool autocvar_g_maplist_votable_suggestions;
+bool autocvar_g_maplist_votable_suggestions_override_mostrecent;
 float autocvar_g_maplist_votable_timeout;
-float autocvar_g_maxplayers;
+int autocvar_g_maxplayers;
 float autocvar_g_maxplayers_spectator_blocktime;
 float autocvar_g_maxpushtime;
 float autocvar_g_maxspeed;
 float autocvar_g_midair_shieldtime;
 #define autocvar_g_instagib cvar("g_instagib")
-float autocvar_g_instagib_ammo_drop;
-float autocvar_g_instagib_extralives;
+int autocvar_g_instagib_ammo_drop;
+int autocvar_g_instagib_extralives;
 float autocvar_g_instagib_speed_highspeed;
 float autocvar_g_instagib_invis_alpha;
 #define autocvar_g_mirrordamage cvar("g_mirrordamage")
 #define autocvar_g_mirrordamage_virtual cvar("g_mirrordamage_virtual")
 
 float autocvar_g_movement_highspeed = 1;
-float autocvar_g_multijump;
+int autocvar_g_multijump;
 float autocvar_g_multijump_add;
 float autocvar_g_multijump_speed;
 string autocvar_g_mutatormsg;
 float autocvar_g_nexball_basketball_bouncefactor;
 float autocvar_g_nexball_basketball_bouncestop;
 float autocvar_g_nexball_basketball_carrier_highspeed;
-float autocvar_g_nexball_basketball_meter;
+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;
@@ -419,79 +419,79 @@ float autocvar_g_nexball_delay_goal;
 float autocvar_g_nexball_delay_start;
 float autocvar_g_nexball_football_bouncefactor;
 float autocvar_g_nexball_football_bouncestop;
-float autocvar_g_nexball_goalleadlimit;
+int autocvar_g_nexball_goalleadlimit;
 #define autocvar_g_nexball_goallimit cvar("g_nexball_goallimit")
-float autocvar_g_nexball_radar_showallplayers;
-float autocvar_g_nexball_sound_bounce;
-float autocvar_g_nexball_trail_color;
+bool autocvar_g_nexball_radar_showallplayers;
+bool autocvar_g_nexball_sound_bounce;
+int autocvar_g_nexball_trail_color;
 //float autocvar_g_nick_flood_penalty;
-float autocvar_g_nick_flood_penalty_red;
-float autocvar_g_nick_flood_penalty_yellow;
+int autocvar_g_nick_flood_penalty_red;
+int autocvar_g_nick_flood_penalty_yellow;
 //float autocvar_g_nick_flood_timeout;
-float autocvar_g_nix_with_healtharmor;
-float autocvar_g_nix_with_blaster;
-float autocvar_g_nix_with_powerups;
-float autocvar_g_nodepthtestitems;
-float autocvar_g_nodepthtestplayers;
-float autocvar_g_norecoil;
+bool autocvar_g_nix_with_healtharmor;
+bool autocvar_g_nix_with_blaster;
+bool autocvar_g_nix_with_powerups;
+bool autocvar_g_nodepthtestitems;
+bool autocvar_g_nodepthtestplayers;
+bool autocvar_g_norecoil;
 float autocvar_g_onslaught_cp_buildhealth;
 float autocvar_g_onslaught_cp_buildtime;
 float autocvar_g_onslaught_cp_health;
 float autocvar_g_onslaught_cp_regen;
 float autocvar_g_onslaught_gen_health;
-float autocvar_g_pickup_cells_max;
-float autocvar_g_pickup_plasma_max;
-float autocvar_g_pickup_fuel_max;
-float autocvar_g_pickup_items;
-float autocvar_g_pickup_nails_max;
-float autocvar_g_pickup_rockets_max;
-float autocvar_g_pickup_shells_max;
+int autocvar_g_pickup_cells_max;
+int autocvar_g_pickup_plasma_max;
+int autocvar_g_pickup_fuel_max;
+int autocvar_g_pickup_items;
+int autocvar_g_pickup_nails_max;
+int autocvar_g_pickup_rockets_max;
+int autocvar_g_pickup_shells_max;
 float autocvar_g_player_alpha;
 float autocvar_g_player_brightness;
-float autocvar_g_playerclip_collisions;
-float autocvar_g_powerups;
-float autocvar_g_projectiles_damage;
-float autocvar_g_projectiles_keep_owner;
-float autocvar_g_projectiles_newton_style;
+bool autocvar_g_playerclip_collisions;
+int autocvar_g_powerups;
+int autocvar_g_projectiles_damage;
+bool autocvar_g_projectiles_keep_owner;
+int autocvar_g_projectiles_newton_style;
 float autocvar_g_projectiles_newton_style_2_maxfactor;
 float autocvar_g_projectiles_newton_style_2_minfactor;
-float autocvar_g_projectiles_spread_style;
+int autocvar_g_projectiles_spread_style;
 #define autocvar_g_race_laps_limit cvar("g_race_laps_limit")
 float autocvar_g_race_qualifying_timelimit;
 float autocvar_g_race_qualifying_timelimit_override;
-float autocvar_g_race_teams;
+int autocvar_g_race_teams;
 float autocvar_g_respawn_delay_small;
-float autocvar_g_respawn_delay_small_count;
+int autocvar_g_respawn_delay_small_count;
 float autocvar_g_respawn_delay_large;
-float autocvar_g_respawn_delay_large_count;
+int autocvar_g_respawn_delay_large_count;
 float autocvar_g_respawn_delay_max;
-float autocvar_g_respawn_ghosts;
+bool autocvar_g_respawn_ghosts;
 float autocvar_g_respawn_ghosts_maxtime;
 float autocvar_g_respawn_ghosts_speed;
-float autocvar_g_respawn_waves;
-float autocvar_g_running_guns;
-float autocvar_g_shootfromcenter;
-float autocvar_g_shootfromclient;
-float autocvar_g_shootfromeye;
+int autocvar_g_respawn_waves;
+bool autocvar_g_running_guns;
+bool autocvar_g_shootfromcenter;
+int autocvar_g_shootfromclient;
+bool autocvar_g_shootfromeye;
 string autocvar_g_shootfromfixedorigin;
-float autocvar_g_showweaponspawns;
-float autocvar_g_spawn_alloweffects;
+int autocvar_g_showweaponspawns;
+bool autocvar_g_spawn_alloweffects;
 float autocvar_g_spawn_furthest;
-float autocvar_g_spawn_useallspawns;
-float autocvar_g_spawnpoints_auto_move_out_of_solid;
+bool autocvar_g_spawn_useallspawns;
+bool autocvar_g_spawnpoints_auto_move_out_of_solid;
 #define autocvar_g_spawnshieldtime cvar("g_spawnshieldtime")
-float autocvar_g_tdm_team_spawns;
-float autocvar_g_tdm_point_limit;
-float autocvar_g_tdm_point_leadlimit;
-float autocvar_g_tdm_teams;
-float autocvar_g_tdm_teams_override;
+bool autocvar_g_tdm_team_spawns;
+int autocvar_g_tdm_point_limit;
+int autocvar_g_tdm_point_leadlimit;
+int autocvar_g_tdm_teams;
+int autocvar_g_tdm_teams_override;
 float autocvar_g_teamdamage_resetspeed;
 float autocvar_g_teamdamage_threshold;
-float autocvar_g_telefrags;
-float autocvar_g_telefrags_avoid;
-float autocvar_g_telefrags_teamplay;
+bool autocvar_g_telefrags;
+bool autocvar_g_telefrags_avoid;
+bool autocvar_g_telefrags_teamplay;
 float autocvar_g_teleport_maxspeed;
-float autocvar_g_throughfloor_debug;
+bool autocvar_g_throughfloor_debug;
 float autocvar_g_throughfloor_damage;
 float autocvar_g_throughfloor_force;
 float autocvar_g_throughfloor_damage_max_stddev;
@@ -504,10 +504,10 @@ float autocvar_g_triggerimpulse_accel_multiplier;
 float autocvar_g_triggerimpulse_accel_power;
 float autocvar_g_triggerimpulse_directional_multiplier;
 float autocvar_g_triggerimpulse_radial_multiplier;
-float autocvar_g_turrets;
+bool autocvar_g_turrets;
 float autocvar_g_turrets_aimidle_delay;
-float autocvar_g_turrets_nofire;
-float autocvar_g_turrets_reloadcvars;
+bool autocvar_g_turrets_nofire;
+bool autocvar_g_turrets_reloadcvars;
 float autocvar_g_turrets_targetscan_maxdelay;
 float autocvar_g_turrets_targetscan_mindelay;
 float autocvar_g_turrets_unit_ewheel_speed_fast;
@@ -545,10 +545,10 @@ float autocvar_g_turrets_unit_walker_turn_walk;
 float autocvar_g_turrets_unit_walker_turn_run;
 float autocvar_g_turrets_unit_walker_turn_strafe;
 float autocvar_g_turrets_unit_walker_turn_swim;
-float autocvar_g_use_ammunition;
-float autocvar_g_waypointeditor;
-float autocvar_g_waypointeditor_auto;
-float autocvar_g_waypoints_for_items;
+bool autocvar_g_use_ammunition;
+bool autocvar_g_waypointeditor;
+int autocvar_g_waypointeditor_auto;
+int autocvar_g_waypoints_for_items;
 float autocvar_g_weapon_charge_colormod_blue_full;
 float autocvar_g_weapon_charge_colormod_blue_half;
 float autocvar_g_weapon_charge_colormod_green_full;
@@ -557,158 +557,139 @@ float autocvar_g_weapon_charge_colormod_hdrmultiplier;
 float autocvar_g_weapon_charge_colormod_red_full;
 float autocvar_g_weapon_charge_colormod_red_half;
 #define autocvar_g_weapon_stay cvar("g_weapon_stay")
-float autocvar_g_weapon_throwable;
+bool autocvar_g_weapon_throwable;
 #define autocvar_g_weaponarena cvar_string("g_weaponarena")
 string autocvar_g_xonoticversion;
 float autocvar_gameversion;
 float autocvar_gameversion_min;
 float autocvar_gameversion_max;
 string autocvar_hostname;
-float autocvar_lastlevel;
-float autocvar_leadlimit;
-float autocvar_leadlimit_and_fraglimit;
-float autocvar_leadlimit_override;
-float autocvar_loddebug;
-float autocvar_minplayers;
+bool autocvar_lastlevel;
+int autocvar_leadlimit;
+int autocvar_leadlimit_and_fraglimit;
+int autocvar_leadlimit_override;
+int autocvar_loddebug;
+int autocvar_minplayers;
 string autocvar_nextmap;
-float autocvar_prvm_backtraceforwarnings;
+bool autocvar_prvm_backtraceforwarnings;
 string autocvar_quit_and_redirect;
 float autocvar_quit_and_redirect_timer;
-float autocvar_quit_when_empty;
+bool autocvar_quit_when_empty;
 float autocvar_r_showbboxes;
-float autocvar_rescan_pending;
-float autocvar_samelevel;
+int autocvar_rescan_pending;
+bool autocvar_samelevel;
 string autocvar_sessionid;
 #define autocvar_skill cvar("skill")
 float autocvar_skill_auto;
 #define autocvar_slowmo cvar("slowmo")
 float autocvar_snd_soundradius;
-float autocvar_spawn_debug;
-float autocvar_speedmeter;
-float autocvar_sv_accelerate;
+int autocvar_spawn_debug;
+bool autocvar_speedmeter;
 float autocvar_sv_accuracy_data_share = 1;
 string autocvar_sv_adminnick;
-float autocvar_sv_airaccel_qw;
-float autocvar_sv_airaccel_qw_stretchfactor;
-float autocvar_sv_airaccel_sideways_friction;
-float autocvar_sv_airaccelerate;
-float autocvar_sv_aircontrol;
-float autocvar_sv_aircontrol_penalty;
-float autocvar_sv_aircontrol_power;
-float autocvar_sv_airspeedlimit_nonqw;
-float autocvar_sv_airstopaccelerate;
-float autocvar_sv_airstrafeaccel_qw;
-float autocvar_sv_airstrafeaccelerate;
-float autocvar_sv_autoscreenshot;
-float autocvar_sv_cheats;
+bool autocvar_sv_autoscreenshot;
+int autocvar_sv_cheats;
 float autocvar_sv_clientcommand_antispam_time;
-float autocvar_sv_clientcommand_antispam_count;
-float autocvar_sv_curl_serverpackages_auto;
-float autocvar_sv_db_saveasdump;
-float autocvar_sv_defaultcharacter;
+int autocvar_sv_clientcommand_antispam_count;
+bool autocvar_sv_curl_serverpackages_auto;
+bool autocvar_sv_db_saveasdump;
+bool autocvar_sv_defaultcharacter;
 string autocvar_sv_defaultplayercolors;
 string autocvar_sv_defaultplayermodel;
 string autocvar_sv_defaultplayermodel_blue;
 string autocvar_sv_defaultplayermodel_pink;
 string autocvar_sv_defaultplayermodel_red;
 string autocvar_sv_defaultplayermodel_yellow;
-float autocvar_sv_defaultplayerskin;
+int autocvar_sv_defaultplayerskin;
 float autocvar_sv_dodging_delay;
 float autocvar_sv_dodging_height_threshold;
 float autocvar_sv_dodging_horiz_speed;
 float autocvar_sv_dodging_horiz_speed_frozen;
 float autocvar_sv_dodging_ramp_time;
-float autocvar_sv_dodging_sound;
+bool autocvar_sv_dodging_sound;
 float autocvar_sv_dodging_up_speed;
 float autocvar_sv_dodging_wall_distance_threshold;
-float autocvar_sv_dodging_wall_dodging;
-float autocvar_sv_dodging_frozen;
-float autocvar_sv_dodging_frozen_doubletap;
-float autocvar_sv_doublejump;
-float autocvar_sv_eventlog;
-float autocvar_sv_eventlog_console;
-float autocvar_sv_eventlog_files;
-float autocvar_sv_eventlog_files_counter;
+bool autocvar_sv_dodging_wall_dodging;
+bool autocvar_sv_dodging_frozen;
+bool autocvar_sv_dodging_frozen_doubletap;
+bool autocvar_sv_doublejump;
+bool autocvar_sv_eventlog;
+bool autocvar_sv_eventlog_console;
+bool autocvar_sv_eventlog_files;
+int autocvar_sv_eventlog_files_counter;
 string autocvar_sv_eventlog_files_nameprefix;
 string autocvar_sv_eventlog_files_namesuffix;
-float autocvar_sv_eventlog_files_timestamps;
-float autocvar_sv_friction;
+bool autocvar_sv_eventlog_files_timestamps;
 float autocvar_sv_friction_on_land;
+var float autocvar_sv_friction_slick = 0.5;
 float autocvar_sv_gameplayfix_q2airaccelerate;
-float autocvar_sv_gentle;
+int autocvar_sv_gentle;
 #define autocvar_sv_gravity cvar("sv_gravity")
 string autocvar_sv_intermission_cdtrack;
-string autocvar_sv_jumpspeedcap_max;
+float autocvar_sv_jumpspeedcap_max;
 float autocvar_sv_jumpspeedcap_max_disable_on_ramps;
-string autocvar_sv_jumpspeedcap_min;
+float autocvar_sv_jumpspeedcap_min;
 float autocvar_sv_jumpvelocity;
-float autocvar_sv_logscores_bots;
-float autocvar_sv_logscores_console;
-float autocvar_sv_logscores_file;
+bool autocvar_sv_logscores_bots;
+bool autocvar_sv_logscores_console;
+bool autocvar_sv_logscores_file;
 string autocvar_sv_logscores_filename;
 float autocvar_sv_mapchange_delay;
 float autocvar_sv_maxairspeed;
-float autocvar_sv_maxairstrafespeed;
 float autocvar_sv_maxspeed;
 string autocvar_sv_motd;
-float autocvar_sv_precacheplayermodels;
+bool autocvar_sv_precacheplayermodels;
 //float autocvar_sv_precacheweapons; // WEAPONTODO?
-float autocvar_sv_q3acompat_machineshotgunswap;
-float autocvar_sv_ready_restart;
-float autocvar_sv_ready_restart_after_countdown;
-float autocvar_sv_ready_restart_repeatable;
-float autocvar_sv_servermodelsonly;
-float autocvar_sv_spectate;
+bool autocvar_sv_q3acompat_machineshotgunswap;
+bool autocvar_sv_ready_restart;
+bool autocvar_sv_ready_restart_after_countdown;
+bool autocvar_sv_ready_restart_repeatable;
+bool autocvar_sv_servermodelsonly;
+int autocvar_sv_spectate;
 float autocvar_sv_spectator_speed_multiplier;
-float autocvar_sv_status_privacy;
+bool autocvar_sv_status_privacy;
 float autocvar_sv_stepheight;
-float autocvar_sv_stopspeed;
 float autocvar_sv_strengthsound_antispam_refire_threshold;
 float autocvar_sv_strengthsound_antispam_time;
-float autocvar_sv_teamnagger;
-float autocvar_sv_timeout;
+bool autocvar_sv_teamnagger;
+bool autocvar_sv_timeout;
 float autocvar_sv_timeout_leadtime;
 float autocvar_sv_timeout_length;
-float autocvar_sv_timeout_number;
+int autocvar_sv_timeout_number;
 float autocvar_sv_timeout_resumetime;
-float autocvar_sv_vote_call;
-float autocvar_sv_vote_change;
+bool autocvar_sv_vote_call;
+bool autocvar_sv_vote_change;
 string autocvar_sv_vote_commands;
-float autocvar_sv_vote_gametype;
+bool autocvar_sv_vote_gametype;
 float autocvar_sv_vote_gametype_timeout;
 string autocvar_sv_vote_gametype_options;
 float autocvar_sv_vote_gametype_keeptwotime;
-float autocvar_sv_vote_gametype_default_current;
-float autocvar_sv_vote_limit;
+bool autocvar_sv_vote_gametype_default_current;
+int autocvar_sv_vote_limit;
 float autocvar_sv_vote_majority_factor;
 float autocvar_sv_vote_majority_factor_of_voted;
-float autocvar_sv_vote_master;
-float autocvar_sv_vote_master_callable;
+bool autocvar_sv_vote_master;
+bool autocvar_sv_vote_master_callable;
 string autocvar_sv_vote_master_commands;
 string autocvar_sv_vote_master_password;
-float autocvar_sv_vote_master_playerlimit;
-float autocvar_sv_vote_no_stops_vote;
-float autocvar_sv_vote_nospectators;
+int autocvar_sv_vote_master_playerlimit;
+bool autocvar_sv_vote_no_stops_vote;
+int autocvar_sv_vote_nospectators;
 //string autocvar_sv_vote_only_commands;
-float autocvar_sv_vote_override_mostrecent;
-float autocvar_sv_vote_singlecount;
+bool autocvar_sv_vote_override_mostrecent;
+bool autocvar_sv_vote_singlecount;
 float autocvar_sv_vote_stop;
 float autocvar_sv_vote_timeout;
 float autocvar_sv_vote_wait;
-float autocvar_sv_vote_gamestart;
-float autocvar_sv_warsowbunny_accel;
-float autocvar_sv_warsowbunny_airforwardaccel;
-float autocvar_sv_warsowbunny_backtosideratio;
-float autocvar_sv_warsowbunny_topspeed;
-float autocvar_sv_warsowbunny_turnaccel;
+bool autocvar_sv_vote_gamestart;
 float autocvar_sv_waypointsprite_deadlifetime;
 float autocvar_sv_waypointsprite_deployed_lifetime;
 float autocvar_sv_waypointsprite_limitedrange;
 string autocvar_sv_weaponstats_file;
 float autocvar_sv_gibhealth;
 float autocvar_sys_ticrate;
-float autocvar_teamplay_lockonrestart;
-float autocvar_teamplay_mode;
+bool autocvar_teamplay_lockonrestart;
+int autocvar_teamplay_mode;
 #define autocvar_timelimit cvar("timelimit")
 #define autocvar_timelimit_override cvar("timelimit_override")
 float autocvar_timelimit_increment;
@@ -716,66 +697,67 @@ float autocvar_timelimit_decrement;
 float autocvar_timelimit_min;
 float autocvar_timelimit_max;
 float autocvar_timelimit_overtime;
-float autocvar_timelimit_overtimes;
+int autocvar_timelimit_overtimes;
 float autocvar_timelimit_suddendeath;
 #define autocvar_utf8_enable cvar("utf8_enable")
-float autocvar_waypoint_benchmark;
+bool autocvar_waypoint_benchmark;
 float autocvar_sv_gameplayfix_gravityunaffectedbyticrate;
+bool autocvar_sv_gameplayfix_upwardvelocityclearsongroundflag;
 float autocvar_g_trueaim_minrange;
-float autocvar_g_debug_defaultsounds;
+bool autocvar_g_debug_defaultsounds;
 float autocvar_g_grab_range;
-float autocvar_g_sandbox_info;
-float autocvar_g_sandbox_readonly;
+int autocvar_g_sandbox_info;
+bool autocvar_g_sandbox_readonly;
 string autocvar_g_sandbox_storage_name;
 float autocvar_g_sandbox_storage_autosave;
-float autocvar_g_sandbox_storage_autoload;
+bool autocvar_g_sandbox_storage_autoload;
 float autocvar_g_sandbox_editor_flood;
-float autocvar_g_sandbox_editor_maxobjects;
-float autocvar_g_sandbox_editor_free;
+int autocvar_g_sandbox_editor_maxobjects;
+int autocvar_g_sandbox_editor_free;
 float autocvar_g_sandbox_editor_distance_spawn;
 float autocvar_g_sandbox_editor_distance_edit;
 float autocvar_g_sandbox_object_scale_min;
 float autocvar_g_sandbox_object_scale_max;
 float autocvar_g_sandbox_object_material_velocity_min;
 float autocvar_g_sandbox_object_material_velocity_factor;
-float autocvar_g_max_info_autoscreenshot;
-float autocvar_physics_ode;
-float autocvar_g_physical_items;
+int autocvar_g_max_info_autoscreenshot;
+bool autocvar_physics_ode;
+int autocvar_g_physical_items;
 float autocvar_g_physical_items_damageforcescale;
 float autocvar_g_physical_items_reset;
 float autocvar_g_monsters;
-float autocvar_g_monsters_edit;
-float autocvar_g_monsters_sounds;
+bool autocvar_g_monsters_edit;
+bool autocvar_g_monsters_sounds;
 float autocvar_g_monsters_think_delay;
-float autocvar_g_monsters_max;
-float autocvar_g_monsters_max_perplayer;
+int autocvar_g_monsters_max;
+int autocvar_g_monsters_max_perplayer;
 float autocvar_g_monsters_target_range;
-float autocvar_g_monsters_target_infront;
+bool autocvar_g_monsters_target_infront;
 float autocvar_g_monsters_attack_range;
-float autocvar_g_monsters_score_kill;
-float autocvar_g_monsters_score_spawned;
-float autocvar_g_monsters_typefrag;
-float autocvar_g_monsters_owners;
+int autocvar_g_monsters_score_kill;
+int autocvar_g_monsters_score_spawned;
+bool autocvar_g_monsters_typefrag;
+bool autocvar_g_monsters_owners;
 float autocvar_g_monsters_miniboss_chance;
 float autocvar_g_monsters_miniboss_healthboost;
 float autocvar_g_monsters_drop_time;
 float autocvar_g_monsters_spawnshieldtime;
-float autocvar_g_monsters_teams;
+bool autocvar_g_monsters_teams;
 float autocvar_g_monsters_respawn_delay;
-float autocvar_g_monsters_respawn;
+bool autocvar_g_monsters_respawn;
 float autocvar_g_monsters_armor_blockpercent;
 float autocvar_g_touchexplode_radius;
 float autocvar_g_touchexplode_damage;
 float autocvar_g_touchexplode_edgedamage;
 float autocvar_g_touchexplode_force;
 float autocvar_g_invasion_round_timelimit;
-float autocvar_g_invasion_teams;
-float autocvar_g_invasion_team_spawns;
+int autocvar_g_invasion_teams;
+bool autocvar_g_invasion_team_spawns;
 float autocvar_g_invasion_spawnpoint_spawn_delay;
 #define autocvar_g_invasion_point_limit cvar("g_invasion_point_limit")
 float autocvar_g_invasion_warmup;
-float autocvar_g_invasion_monster_count;
-float autocvar_g_invasion_zombies_only;
+int autocvar_g_invasion_monster_count;
+bool autocvar_g_invasion_zombies_only;
 float autocvar_g_invasion_spawn_delay;
 #define autocvar_g_bloodloss cvar("g_bloodloss")
 float autocvar_g_random_gravity_negative_chance;
@@ -784,11 +766,11 @@ float autocvar_g_random_gravity_max;
 float autocvar_g_random_gravity_positive;
 float autocvar_g_random_gravity_negative;
 float autocvar_g_random_gravity_delay;
-float autocvar_g_nades;
+bool autocvar_g_nades;
 vector autocvar_g_nades_throw_offset;
-float autocvar_g_nades_spawn;
-float autocvar_g_nades_spawn_count;
-float autocvar_g_nades_client_select;
+bool autocvar_g_nades_spawn;
+int autocvar_g_nades_spawn_count;
+bool autocvar_g_nades_client_select;
 float autocvar_g_nades_nade_lifetime;
 float autocvar_g_nades_nade_minforce;
 float autocvar_g_nades_nade_maxforce;
@@ -798,39 +780,39 @@ float autocvar_g_nades_nade_damage;
 float autocvar_g_nades_nade_edgedamage;
 float autocvar_g_nades_nade_radius;
 float autocvar_g_nades_nade_force;
-float autocvar_g_nades_nade_newton_style;
+int autocvar_g_nades_nade_newton_style;
 int autocvar_g_nades_napalm_ball_count;
 float autocvar_g_nades_napalm_ball_spread;
 float autocvar_g_nades_napalm_ball_damage;
 float autocvar_g_nades_napalm_ball_damageforcescale;
 float autocvar_g_nades_napalm_ball_lifetime;
 float autocvar_g_nades_napalm_ball_radius;
-float autocvar_g_nades_napalm_blast;
+bool autocvar_g_nades_napalm_blast;
 float autocvar_g_nades_napalm_fountain_lifetime;
 float autocvar_g_nades_napalm_fountain_delay;
 float autocvar_g_nades_napalm_fountain_radius;
 float autocvar_g_nades_napalm_fountain_damage;
 float autocvar_g_nades_napalm_fountain_edgedamage;
 float autocvar_g_nades_napalm_burntime;
-float autocvar_g_nades_napalm_selfdamage;
-float autocvar_g_nades_nade_type;
-float autocvar_g_nades_bonus_type;
-float autocvar_g_nades_bonus;
-float autocvar_g_nades_bonus_onstrength;
-float autocvar_g_nades_bonus_client_select;
-float autocvar_g_nades_bonus_max;
-float autocvar_g_nades_bonus_score_max;
-float autocvar_g_nades_bonus_score_time;
-float autocvar_g_nades_bonus_score_time_flagcarrier;
-float autocvar_g_nades_bonus_score_minor;
-float autocvar_g_nades_bonus_score_low;
-float autocvar_g_nades_bonus_score_high;
-float autocvar_g_nades_bonus_score_medium;
-float autocvar_g_nades_bonus_score_spree;
+bool autocvar_g_nades_napalm_selfdamage;
+int autocvar_g_nades_nade_type;
+int autocvar_g_nades_bonus_type;
+bool autocvar_g_nades_bonus;
+bool autocvar_g_nades_bonus_onstrength;
+bool autocvar_g_nades_bonus_client_select;
+int autocvar_g_nades_bonus_max;
+int autocvar_g_nades_bonus_score_max;
+int autocvar_g_nades_bonus_score_time;
+int autocvar_g_nades_bonus_score_time_flagcarrier;
+int autocvar_g_nades_bonus_score_minor;
+int autocvar_g_nades_bonus_score_low;
+int autocvar_g_nades_bonus_score_high;
+int autocvar_g_nades_bonus_score_medium;
+int autocvar_g_nades_bonus_score_spree;
 float autocvar_g_nades_ice_freeze_time;
 float autocvar_g_nades_ice_health;
-float autocvar_g_nades_ice_explode;
-float autocvar_g_nades_ice_teamcheck;
+bool autocvar_g_nades_ice_explode;
+bool autocvar_g_nades_ice_teamcheck;
 float autocvar_g_nades_heal_time;
 float autocvar_g_nades_heal_rate;
 float autocvar_g_nades_heal_friend;
@@ -840,28 +822,31 @@ float autocvar_g_nades_pokenade_monster_lifetime;
 float autocvar_g_campcheck_damage;
 float autocvar_g_campcheck_distance;
 float autocvar_g_campcheck_interval;
-float autocvar_g_jump_grunt;
-float autocvar_g_overkill_powerups_replace;
+bool autocvar_g_jump_grunt;
+bool autocvar_g_overkill_powerups_replace;
 float autocvar_g_overkill_superguns_respawn_time;
-float autocvar_g_overkill_100h_anyway;
-float autocvar_g_overkill_100a_anyway;
-float autocvar_g_overkill_ammo_charge;
+bool autocvar_g_overkill_100h_anyway;
+bool autocvar_g_overkill_100a_anyway;
+bool autocvar_g_overkill_ammo_charge;
 float autocvar_g_overkill_ammo_charge_notice;
 float autocvar_g_overkill_ammo_charge_limit;
 float autocvar_g_spawn_near_teammate_distance;
-float autocvar_g_spawn_near_teammate_ignore_spawnpoint;
+bool autocvar_g_spawn_near_teammate_ignore_spawnpoint;
 float autocvar_g_spawn_near_teammate_ignore_spawnpoint_delay;
 float autocvar_g_spawn_near_teammate_ignore_spawnpoint_delay_death;
-float autocvar_g_spawn_near_teammate_ignore_spawnpoint_check_health;
-float autocvar_g_spawn_near_teammate_ignore_spawnpoint_closetodeath;
+int autocvar_g_spawn_near_teammate_ignore_spawnpoint_check_health;
+bool autocvar_g_spawn_near_teammate_ignore_spawnpoint_closetodeath;
+bool autocvar_g_physics_clientselect;
+string autocvar_g_physics_clientselect_options;
+string autocvar_g_physics_clientselect_default;
 bool  autocvar_g_buffs_effects;
 float autocvar_g_buffs_waypoint_distance;
-float autocvar_g_buffs_randomize;
+bool autocvar_g_buffs_randomize;
 float autocvar_g_buffs_random_lifetime;
-float autocvar_g_buffs_random_location;
-float autocvar_g_buffs_random_location_attempts;
-float autocvar_g_buffs_spawn_count;
-float autocvar_g_buffs_replace_powerups;
+bool autocvar_g_buffs_random_location;
+int autocvar_g_buffs_random_location_attempts;
+int autocvar_g_buffs_spawn_count;
+bool autocvar_g_buffs_replace_powerups;
 float autocvar_g_buffs_cooldown_activate;
 float autocvar_g_buffs_cooldown_respawn;
 float autocvar_g_buffs_resistance_blockpercent;
@@ -893,4 +878,5 @@ float autocvar_g_buffs_inferno_burntime_target_time;
 float autocvar_g_buffs_inferno_damagemultiplier;
 float autocvar_g_buffs_swapper_range;
 float autocvar_g_buffs_magnet_range_item;
+float autocvar_sv_player_scale;
 #endif
index 581c59ca2630ffa7318f7e8c659c8e12c891d448..c889a2f9aaf8a540af01cacd2ee588f83c9ae99a 100644 (file)
@@ -1,3 +1,9 @@
+#include "aim.qh"
+#include "../_all.qh"
+
+#include "bot.qh"
+
+#include "../mutators/mutators_include.qh"
 
 // traces multiple trajectories to find one that will impact the target
 // 'end' vector is the place it aims for,
index fb191a91cce7e61f9f0c930d78c85a988bfd979b..d1cbd0d629a71368ed5b8ea74fe26b4a73ea245d 100644 (file)
@@ -86,6 +86,7 @@ vector shotdir;
  * Functions
  */
 
+float lag_additem(float t, float f1, float f2, entity e1, vector v1, vector v2, vector v3, vector v4);
 void lag_update();
 void bot_lagfunc(float t, float f1, float f2, entity e1, vector v1, vector v2, vector v3, vector v4);
 
index 0acd32993595139f9a777ba74b527a1c574ee7a2..e42a50f6d4a9ccb8abad44d3b3db2511a13a06a6 100644 (file)
@@ -1,37 +1,41 @@
-#if defined(CSQC)
-#elif defined(MENUQC)
-#elif defined(SVQC)
-       #include "../../dpdefs/progsdefs.qh"
-    #include "../../dpdefs/dpextensions.qh"
-    #include "../../warpzonelib/common.qh"
-    #include "../../warpzonelib/util_server.qh"
-    #include "../../common/constants.qh"
-    #include "../../common/teams.qh"
-    #include "../../common/util.qh"
-    #include "../../common/weapons/weapons.qh"
-    #include "../weapons/accuracy.qh"
-    #include "../t_items.qh"
-    #include "../autocvars.qh"
-    #include "../constants.qh"
-    #include "../defs.qh"
-    #include "../mutators/mutators_include.qh"
-    #include "../campaign.qh"
-    #include "../../common/mapinfo.qh"
-    #include "../../csqcmodellib/sv_model.qh"
-    #include "../antilag.qh"
-#endif
-
 #include "bot.qh"
+#include "../_all.qh"
+
 #include "aim.qh"
 #include "navigation.qh"
+#include "scripting.qh"
 #include "waypoints.qh"
 
-#include "aim.qc"
-#include "navigation.qc"
-#include "waypoints.qc"
-#include "scripting.qc"
+#include "havocbot/havocbot.qh"
+#include "havocbot/scripting.qh"
+
+#include "../antilag.qh"
+#include "../autocvars.qh"
+#include "../campaign.qh"
+#include "../cl_client.qh"
+#include "../constants.qh"
+#include "../defs.qh"
+#include "../race.qh"
+#include "../t_items.qh"
+
+#include "../mutators/mutators_include.qh"
+
+#include "../weapons/accuracy.qh"
+
+#include "../../common/constants.qh"
+#include "../../common/mapinfo.qh"
+#include "../../common/teams.qh"
+#include "../../common/util.qh"
+
+#include "../../common/weapons/all.qh"
+
+#include "../../csqcmodellib/sv_model.qh"
+
+#include "../../dpdefs/dpextensions.qh"
+#include "../../dpdefs/progsdefs.qh"
 
-#include "havocbot/havocbot.qc"
+#include "../../warpzonelib/common.qh"
+#include "../../warpzonelib/util_server.qh"
 
 entity bot_spawn()
 {
index bcae58dc181e0c89b9db7ef02e729d2660516e04..ac89f06a7382dc91aec1d68427af2b4b0a6269c1 100644 (file)
@@ -91,6 +91,7 @@ float bot_ignore_bots; // let bots not attack other bots (only works in non-team
  */
 
 entity bot_spawn();
+float bot_fixcount();
 
 void bot_think();
 void bot_setnameandstuff();
index 0ecafaf1e87c7aa62fda4892d2c38ef300e05683..9fa1667099b4b3ac017cde9987004d58dd082192 100644 (file)
@@ -1,7 +1,17 @@
 #include "havocbot.qh"
-#include "role_onslaught.qc"
-#include "role_keyhunt.qc"
-#include "roles.qc"
+#include "../../_all.qh"
+
+#include "../aim.qh"
+#include "../bot.qh"
+#include "../navigation.qh"
+#include "../scripting.qh"
+#include "../waypoints.qh"
+
+#include "../../../common/constants.qh"
+
+#include "../../../common/triggers/trigger/jumppads.qh"
+
+#include "../../../warpzonelib/common.qh"
 
 void havocbot_ai()
 {
@@ -148,9 +158,6 @@ void havocbot_ai()
        // if the bot is not attacking, consider reloading weapons
        if (!(self.aistatus & AI_STATUS_ATTACKING))
        {
-               float i;
-               entity e;
-
                // we are currently holding a weapon that's not fully loaded, reload it
                if(skill >= 2) // bots can only reload the held weapon on purpose past this skill
                if(self.clip_load < self.clip_size)
@@ -161,9 +168,9 @@ void havocbot_ai()
                if(skill >= 5) // bots can only look for unloaded weapons past this skill
                if(self.clip_load >= 0) // only if we're not reloading a weapon already
                {
-                       for(i = WEP_FIRST; i <= WEP_LAST; ++i)
+                       for (int i = WEP_FIRST; i <= WEP_LAST; ++i)
                        {
-                               e = get_weaponinfo(i);
+                               entity e = get_weaponinfo(i);
                                if ((self.weapons & WepSet_FromWeapon(i)) && (e.spawnflags & WEP_FLAG_RELOADABLE) && (self.weapon_load[i] < e.reloading_ammo))
                                        self.switchweapon = i;
                        }
@@ -470,7 +477,7 @@ void havocbot_movetogoal()
 
                // Flying
                self.BUTTON_HOOK = true;
-               if(self.navigation_jetpack_point.z - PL_MAX_z + PL_MIN_z < self.origin.z)
+               if(self.navigation_jetpack_point.z - PL_MAX.z + PL_MIN.z < self.origin.z)
                {
                        self.movement_x = dir * v_forward * maxspeed;
                        self.movement_y = dir * v_right * maxspeed;
index 3b641d9ce757762c430d03be58e9b4e948dc90ea..ea163f4efb56cdd0f9e67b339206573fbe48cedf 100644 (file)
@@ -1,10 +1,18 @@
+#include "role_keyhunt.qh"
+#include "../../_all.qh"
+
+#include "havocbot.qh"
+
+#include "../bot.qh"
+#include "../navigation.qh"
+
+#include "../../mutators/mutators_include.qh"
+
 void() havocbot_role_kh_carrier;
 void() havocbot_role_kh_defense;
 void() havocbot_role_kh_offense;
 void() havocbot_role_kh_freelancer;
 
-entity kh_worldkeylist;
-.entity kh_worldkeynext;
 
 void havocbot_goalrating_kh(float ratingscale_team, float ratingscale_dropped, float ratingscale_enemy)
 {
diff --git a/qcsrc/server/bot/havocbot/role_keyhunt.qh b/qcsrc/server/bot/havocbot/role_keyhunt.qh
new file mode 100644 (file)
index 0000000..f3136c6
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef ROLE_KEYHUNT_H
+#define ROLE_KEYHUNT_H
+
+entity kh_worldkeylist;
+.entity kh_worldkeynext;
+
+void havocbot_chooserole_kh();
+#endif
index 119ea83c81b77c90b659518bf03a601d49f2f360..6924f5122949e8edf715cded97d9c9ea6e98f159 100644 (file)
@@ -1,3 +1,15 @@
+#include "../../_all.qh"
+
+#include "havocbot.qh"
+
+#include "../bot.qh"
+#include "../navigation.qh"
+#include "../waypoints.qh"
+
+#include "../../mutators/mutators_include.qh"
+
+#include "../../../common/teams.qh"
+
 const int HAVOCBOT_ONS_ROLE_NONE               = 0;
 const int HAVOCBOT_ONS_ROLE_DEFENSE    = 2;
 const int HAVOCBOT_ONS_ROLE_ASSISTANT  = 4;
diff --git a/qcsrc/server/bot/havocbot/role_onslaught.qh b/qcsrc/server/bot/havocbot/role_onslaught.qh
new file mode 100644 (file)
index 0000000..3fca678
--- /dev/null
@@ -0,0 +1,4 @@
+#ifndef ROLE_ONSLAUGHT_H
+#define ROLE_ONSLAUGHT_H
+void havocbot_chooserole_ons();
+#endif
index af219b8ec730272f85f334402ea9c8cc4dc229f4..65ea2a809b6be9d105d88ab5d1bd272952bf9028 100644 (file)
@@ -1,3 +1,11 @@
+#include "../../_all.qh"
+
+#include "havocbot.qh"
+#include "role_keyhunt.qh"
+#include "role_onslaught.qh"
+
+#include "../bot.qh"
+#include "../navigation.qh"
 
 .float max_armorvalue;
 .float havocbot_role_timeout;
diff --git a/qcsrc/server/bot/havocbot/roles.qh b/qcsrc/server/bot/havocbot/roles.qh
new file mode 100644 (file)
index 0000000..cfabf05
--- /dev/null
@@ -0,0 +1,4 @@
+#ifndef ROLES_H
+#define ROLES_H
+void havocbot_goalrating_controlpoints(float ratingscale, vector org, float sradius);
+#endif
diff --git a/qcsrc/server/bot/havocbot/scripting.qh b/qcsrc/server/bot/havocbot/scripting.qh
new file mode 100644 (file)
index 0000000..c09dbde
--- /dev/null
@@ -0,0 +1,5 @@
+#ifndef HAVOCBOT_SCRIPTING_H
+#define HAVOCBOT_SCRIPTING_H
+
+void bot_clearqueue(entity bot);
+#endif
index d80f8336c8ba179bd52e862bc2807181d92efebc..ad0a8d761d4bdfff7a8aca640ebc8c6ddf8b8d51 100644 (file)
@@ -1,3 +1,14 @@
+#include "navigation.qh"
+#include "../_all.qh"
+
+#include "bot.qh"
+#include "waypoints.qh"
+
+#include "../t_items.qh"
+
+#include "../../common/constants.qh"
+#include "../../common/triggers/trigger/jumppads.qh"
+
 void bot_debug(string input)
 {
        switch(autocvar_bot_debug)
@@ -387,7 +398,7 @@ entity navigation_findnearestwaypoint_withdist_except(entity ent, float walkfrom
        }
 
        org = ent.origin + 0.5 * (ent.mins + ent.maxs);
-       org.z = ent.origin.z + ent.mins.z - PL_MIN_z; // player height
+       org.z = ent.origin.z + ent.mins.z - PL_MIN.z; // player height
        // TODO possibly make other code have the same support for bboxes
        if(ent.tag_entity)
                org = org + ent.tag_entity.origin;
@@ -710,7 +721,7 @@ void navigation_routerating(entity e, float f, float rangebias)
                        float zdistance, xydistance, cost, t, fuel;
                        vector down, npa, npb;
 
-                       down = '0 0 -1' * (PL_MAX_z - PL_MIN_z) * 10;
+                       down = '0 0 -1' * (PL_MAX.z - PL_MIN.z) * 10;
 
                        do{
                                npa = pointa + down;
index 08e1c53ac88d4fb8304076157bd4a95e88ea8f9b..cf4a5ce5b261dcf6c4e154bef405c480d85a2afb 100644 (file)
@@ -76,4 +76,5 @@ void navigation_unstuck();
 void botframe_updatedangerousobjects(float maxupdate);
 
 entity navigation_findnearestwaypoint(entity ent, float walkfromwp);
+float navigation_waypoint_will_link(vector v, vector org, entity ent, float walkfromwp, float bestdist);
 #endif
index ead8ceac9ec5c3adba637e35df67207f6abc6391..b1425c1a821dadaf447b5d291c539079e3fc83bb 100644 (file)
@@ -1,3 +1,8 @@
+#include "scripting.qh"
+#include "../_all.qh"
+
+#include "bot.qh"
+
 .float bot_cmdqueuebuf_allocated;
 .float bot_cmdqueuebuf;
 .float bot_cmdqueuebuf_start;
@@ -137,68 +142,6 @@ entity bot_getplace(string placename)
 }
 
 
-// NOTE: New commands should be added here. Do not forget to update BOT_CMD_COUNTER
-const int BOT_CMD_NULL                         = 0;
-const int BOT_CMD_PAUSE                = 1;
-const int BOT_CMD_CONTINUE             = 2;
-const int BOT_CMD_WAIT                         = 3;
-const int BOT_CMD_TURN                         = 4;
-const int BOT_CMD_MOVETO               = 5;
-const int BOT_CMD_RESETGOAL    = 6;    // Not implemented yet
-const int BOT_CMD_CC                   = 7;
-const int BOT_CMD_IF                   = 8;
-const int BOT_CMD_ELSE                         = 9;
-const int BOT_CMD_FI                   = 10;
-const int BOT_CMD_RESETAIM             = 11;
-const int BOT_CMD_AIM                  = 12;
-const int BOT_CMD_PRESSKEY             = 13;
-const int BOT_CMD_RELEASEKEY   = 14;
-const int BOT_CMD_SELECTWEAPON         = 15;
-const int BOT_CMD_IMPULSE              = 16;
-const int BOT_CMD_WAIT_UNTIL   = 17;
-const int BOT_CMD_MOVETOTARGET         = 18;
-const int BOT_CMD_AIMTARGET    = 19;
-const int BOT_CMD_BARRIER              = 20;
-const int BOT_CMD_CONSOLE              = 21;
-const int BOT_CMD_SOUND                = 22;
-const int BOT_CMD_DEBUG_ASSERT_CANFIRE = 23;
-const int BOT_CMD_WHILE                = 24;   // TODO: Not implemented yet
-const int BOT_CMD_WEND                         = 25;   // TODO: Not implemented yet
-const int BOT_CMD_CHASE                = 26;   // TODO: Not implemented yet
-
-const int BOT_CMD_COUNTER              = 24;   // Update this value if you add/remove a command
-
-// NOTE: Following commands should be implemented on the bot ai
-//              If a new command should be handled by the target ai(s) please declare it here
-.float(vector) cmd_moveto;
-.float() cmd_resetgoal;
-
-//
-const int BOT_CMD_PARAMETER_NONE = 0;
-const int BOT_CMD_PARAMETER_FLOAT = 1;
-const int BOT_CMD_PARAMETER_STRING = 2;
-const int BOT_CMD_PARAMETER_VECTOR = 3;
-
-float bot_cmds_initialized;
-int bot_cmd_parm_type[BOT_CMD_COUNTER];
-string bot_cmd_string[BOT_CMD_COUNTER];
-
-// Bots command queue
-entity bot_cmd;        // global current command
-.entity bot_cmd_current; // current command of this bot
-
-.float is_bot_cmd;                     // Tells if the entity is a bot command
-.float bot_cmd_index;                  // Position of the command in the queue
-.int bot_cmd_type;                     // If of command (see the BOT_CMD_* defines)
-.float bot_cmd_parm_float;             // Field to store a float parameter
-.string bot_cmd_parm_string;           // Field to store a string parameter
-.vector bot_cmd_parm_vector;           // Field to store a vector parameter
-
-float bot_barriertime;
-.float bot_barrier;
-
-.float bot_cmd_execution_index;                // Position in the queue of the command to be executed
-
 // Initialize global commands list
 // NOTE: New commands should be initialized here
 void bot_commands_init()
@@ -529,14 +472,6 @@ void bot_list_commands()
 // Commands code
 .int bot_exec_status;
 
-#define BOT_EXEC_STATUS_IDLE   0
-#define BOT_EXEC_STATUS_PAUSED 1
-#define BOT_EXEC_STATUS_WAITING        2
-
-#define CMD_STATUS_EXECUTING   0
-#define CMD_STATUS_FINISHED    1
-#define CMD_STATUS_ERROR       2
-
 void SV_ParseClientCommand(string s);
 float bot_cmd_cc()
 {
@@ -1215,7 +1150,6 @@ void bot_setcurrentcommand()
 void bot_resetqueues()
 {
        entity cl;
-       float i;
 
        FOR_EACH_CLIENT(cl) if(cl.isbot)
        {
@@ -1223,7 +1157,7 @@ void bot_resetqueues()
                bot_clearqueue(cl);
                // also, cancel all barriers
                cl.bot_barrier = 0;
-               for(i = 0; i < cl.bot_places_count; ++i)
+               for(int i = 0; i < cl.bot_places_count; ++i)
                {
                        strunzone(cl.(bot_placenames[i]));
                        cl.(bot_placenames[i]) = string_null;
diff --git a/qcsrc/server/bot/scripting.qh b/qcsrc/server/bot/scripting.qh
new file mode 100644 (file)
index 0000000..d5cdda9
--- /dev/null
@@ -0,0 +1,83 @@
+#ifndef BOT_SCRIPTING_H
+#define BOT_SCRIPTING_H
+
+#define BOT_EXEC_STATUS_IDLE 0
+#define BOT_EXEC_STATUS_PAUSED 1
+#define BOT_EXEC_STATUS_WAITING 2
+
+#define CMD_STATUS_EXECUTING 0
+#define CMD_STATUS_FINISHED 1
+#define CMD_STATUS_ERROR 2
+
+
+// NOTE: New commands should be added here. Do not forget to update BOT_CMD_COUNTER
+const int BOT_CMD_NULL                         = 0;
+const int BOT_CMD_PAUSE                = 1;
+const int BOT_CMD_CONTINUE             = 2;
+const int BOT_CMD_WAIT                         = 3;
+const int BOT_CMD_TURN                         = 4;
+const int BOT_CMD_MOVETO               = 5;
+const int BOT_CMD_RESETGOAL    = 6;    // Not implemented yet
+const int BOT_CMD_CC                   = 7;
+const int BOT_CMD_IF                   = 8;
+const int BOT_CMD_ELSE                         = 9;
+const int BOT_CMD_FI                   = 10;
+const int BOT_CMD_RESETAIM             = 11;
+const int BOT_CMD_AIM                  = 12;
+const int BOT_CMD_PRESSKEY             = 13;
+const int BOT_CMD_RELEASEKEY   = 14;
+const int BOT_CMD_SELECTWEAPON         = 15;
+const int BOT_CMD_IMPULSE              = 16;
+const int BOT_CMD_WAIT_UNTIL   = 17;
+const int BOT_CMD_MOVETOTARGET         = 18;
+const int BOT_CMD_AIMTARGET    = 19;
+const int BOT_CMD_BARRIER              = 20;
+const int BOT_CMD_CONSOLE              = 21;
+const int BOT_CMD_SOUND                = 22;
+const int BOT_CMD_DEBUG_ASSERT_CANFIRE = 23;
+const int BOT_CMD_WHILE                = 24;   // TODO: Not implemented yet
+const int BOT_CMD_WEND                         = 25;   // TODO: Not implemented yet
+const int BOT_CMD_CHASE                = 26;   // TODO: Not implemented yet
+
+const int BOT_CMD_COUNTER              = 24;   // Update this value if you add/remove a command
+
+// NOTE: Following commands should be implemented on the bot ai
+//              If a new command should be handled by the target ai(s) please declare it here
+.float(vector) cmd_moveto;
+.float() cmd_resetgoal;
+
+//
+const int BOT_CMD_PARAMETER_NONE = 0;
+const int BOT_CMD_PARAMETER_FLOAT = 1;
+const int BOT_CMD_PARAMETER_STRING = 2;
+const int BOT_CMD_PARAMETER_VECTOR = 3;
+
+float bot_cmds_initialized;
+int bot_cmd_parm_type[BOT_CMD_COUNTER];
+string bot_cmd_string[BOT_CMD_COUNTER];
+
+// Bots command queue
+entity bot_cmd;        // global current command
+.entity bot_cmd_current; // current command of this bot
+
+.float is_bot_cmd;                     // Tells if the entity is a bot command
+.float bot_cmd_index;                  // Position of the command in the queue
+.int bot_cmd_type;                     // If of command (see the BOT_CMD_* defines)
+.float bot_cmd_parm_float;             // Field to store a float parameter
+.string bot_cmd_parm_string;           // Field to store a string parameter
+.vector bot_cmd_parm_vector;           // Field to store a vector parameter
+
+float bot_barriertime;
+.float bot_barrier;
+
+.float bot_cmd_execution_index;                // Position in the queue of the command to be executed
+
+
+void bot_resetqueues();
+void bot_queuecommand(entity bot, string cmdstring);
+void bot_cmdhelp(string scmd);
+void bot_list_commands();
+float bot_execute_commands();
+entity find_bot_by_name(string name);
+entity find_bot_by_number(float number);
+#endif
index 23e7af3f9242061e5ffeadd5a0d0d924c569052d..627c622d2554de6f9b3a6015f5d8ffaebb2e7066 100644 (file)
@@ -1,3 +1,15 @@
+#include "waypoints.qh"
+#include "../_all.qh"
+
+#include "bot.qh"
+#include "navigation.qh"
+
+#include "../antilag.qh"
+
+#include "../../common/constants.qh"
+
+#include "../../warpzonelib/util_server.qh"
+
 // create a new spawnfunc_waypoint and automatically link it to other waypoints, and link
 // them back to it as well
 // (suitable for spawnfunc_waypoint editor)
@@ -196,7 +208,7 @@ void waypoint_think()
                        navigation_testtracewalk = 0;
                        if (!self.wpisbox)
                        {
-                               tracebox(sv - PL_MIN_z * '0 0 1', PL_MIN, PL_MAX, sv, false, self);
+                               tracebox(sv - PL_MIN.z * '0 0 1', PL_MIN, PL_MAX, sv, false, self);
                                if (!trace_startsolid)
                                {
                                        //dprint("sv deviation", vtos(trace_endpos - sv), "\n");
@@ -205,7 +217,7 @@ void waypoint_think()
                        }
                        if (!e.wpisbox)
                        {
-                               tracebox(ev - PL_MIN_z * '0 0 1', PL_MIN, PL_MAX, ev, false, e);
+                               tracebox(ev - PL_MIN.z * '0 0 1', PL_MIN, PL_MAX, ev, false, e);
                                if (!trace_startsolid)
                                {
                                        //dprint("ev deviation", vtos(trace_endpos - ev), "\n");
@@ -719,7 +731,7 @@ float waypoint_loadall()
 
 vector waypoint_fixorigin(vector position)
 {
-       tracebox(position + '0 0 1' * (1 - PL_MIN_z), PL_MIN, PL_MAX, position + '0 0 -512', MOVE_NOMONSTERS, world);
+       tracebox(position + '0 0 1' * (1 - PL_MIN.z), PL_MIN, PL_MAX, position + '0 0 -512', MOVE_NOMONSTERS, world);
        if(trace_fraction < 1)
                position = trace_endpos;
        //traceline(position, position + '0 0 -512', MOVE_NOMONSTERS, world);
@@ -893,7 +905,7 @@ float botframe_autowaypoints_createwp(vector v, entity p, .entity fld, float f)
                w = find(w, classname, "waypoint");
        }
 
-       waypoint_schedulerelink(p.fld = waypoint_spawn(v, v, f));
+       waypoint_schedulerelink(p.(fld) = waypoint_spawn(v, v, f));
        return 1;
 }
 
@@ -948,14 +960,14 @@ float botframe_autowaypoints_fix_from(entity p, float walkfromwp, entity wp, .en
                                                if(navigation_waypoint_will_link(w.origin, porg, p, walkfromwp, 1050))
                                                {
                                                        bestdist = d;
-                                                       p.fld = w;
+                                                       p.(fld) = w;
                                                }
                        }
                        w = find(w, classname, "waypoint");
                }
                if(bestdist < maxdist)
                {
-                       print("update chain to new nearest WP ", etos(p.fld), "\n");
+                       print("update chain to new nearest WP ", etos(p.(fld)), "\n");
                        return 0;
                }
 
@@ -964,7 +976,7 @@ float botframe_autowaypoints_fix_from(entity p, float walkfromwp, entity wp, .en
                        // we know maxdist < 2100
                        // so wp -> porg is still valid
                        // all is good
-                       p.fld = wp;
+                       p.(fld) = wp;
                        return 0;
                }
 
@@ -978,7 +990,7 @@ float botframe_autowaypoints_fix_from(entity p, float walkfromwp, entity wp, .en
                setorigin(p, save);
                if(w)
                {
-                       p.fld = w;
+                       p.(fld) = w;
                        return 0;
                }
        }
@@ -1043,8 +1055,7 @@ float botframe_autowaypoints_fix_from(entity p, float walkfromwp, entity wp, .en
 .entity botframe_autowaypoints_lastwp0, botframe_autowaypoints_lastwp1;
 void botframe_autowaypoints_fix(entity p, float walkfromwp, .entity fld)
 {
-       float r;
-       r = botframe_autowaypoints_fix_from(p, walkfromwp, p.fld, fld);
+       float r = botframe_autowaypoints_fix_from(p, walkfromwp, p.(fld), fld);
        if(r != -1)
                return;
        r = botframe_autowaypoints_fix_from(p, walkfromwp, world, fld);
index 2c091d56e15f19bed4cda5890861ef29fae33db2..650855989edebccc0ee31cf1aba8984b6a634b2f 100644 (file)
@@ -121,7 +121,6 @@ void CampaignPreInit()
        strunzone(title);
 }
 
-string GetMapname();
 void CampaignPostInit()
 {
        // now some sanity checks
index 657ec4d7fd3c0e15f6477c5a56c766b5a5effcb1..0c6fc7f39d483e7b0b931e18f25360fbc4730392 100644 (file)
@@ -1,26 +1,30 @@
 #include "cheats.qh"
+#include "_all.qh"
+
 #include "g_damage.qh"
 #include "race.qh"
-#include "t_teleporters.qh"
-
-#if defined(CSQC)
-#elif defined(MENUQC)
-#elif defined(SVQC)
-       #include "../dpdefs/progsdefs.qh"
-    #include "../dpdefs/dpextensions.qh"
-    #include "../warpzonelib/anglestransform.qh"
-    #include "../warpzonelib/util_server.qh"
-    #include "../common/constants.qh"
-    #include "../common/util.qh"
-    #include "../common/monsters/monsters.qh"
-    #include "../common/weapons/weapons.qh"
-    #include "weapons/tracing.qh"
-    #include "autocvars.qh"
-    #include "defs.qh"
-    #include "../common/deathtypes.qh"
-    #include "mutators/mutators_include.qh"
-    #include "../csqcmodellib/sv_model.qh"
-#endif
+#include "../common/triggers/teleporters.qh"
+
+#include "mutators/mutators_include.qh"
+
+#include "weapons/tracing.qh"
+
+#include "../common/constants.qh"
+#include "../common/deathtypes.qh"
+#include "../common/util.qh"
+
+#include "../common/monsters/all.qh"
+
+#include "../common/weapons/all.qh"
+
+#include "../common/triggers/subs.qh"
+
+#include "../common/triggers/func/breakable.qh"
+
+#include "../csqcmodellib/sv_model.qh"
+
+#include "../warpzonelib/anglestransform.qh"
+#include "../warpzonelib/util_server.qh"
 
 void CopyBody(float keepvelocity);
 
@@ -40,15 +44,7 @@ void Drag_MoveDrag(entity from, entity to) { }
 .float maycheat;
 float gamestart_sv_cheats;
 
-const float CHIMPULSE_SPEEDRUN_INIT = 30;
-const float CHIMPULSE_GIVE_ALL = 99;
-const float CHIMPULSE_CLONE_MOVING = 140;
-const float CHIMPULSE_SPEEDRUN = 141;
-const float CHIMPULSE_CLONE_STANDING = 142;
-const float CHIMPULSE_TELEPORT = 143;
-const float CHIMPULSE_R00T = 148;
 
-const float CHRAME_DRAG = 8;
 
 void CheatInit()
 {
index 625a304bd51f99ce3539942cd58d5a47f3c4aff3..f200c4c867bc5afc73e7c3eb86483a38e7f621ed 100644 (file)
@@ -13,5 +13,15 @@ float CheatImpulse(float i);
 float CheatCommand(float argc);
 float CheatFrame();
 
+const float CHIMPULSE_SPEEDRUN_INIT = 30;
+const float CHIMPULSE_GIVE_ALL = 99;
+const float CHIMPULSE_CLONE_MOVING = 140;
+const float CHIMPULSE_SPEEDRUN = 141;
+const float CHIMPULSE_CLONE_STANDING = 142;
+const float CHIMPULSE_TELEPORT = 143;
+const float CHIMPULSE_R00T = 148;
+
+const float CHRAME_DRAG = 8;
+
 void Drag_MoveDrag(entity from, entity to); // call this from CopyBody
 #endif
index 3bc5cc762f231b2e92f8df7dfdfe4b05e9d55bb1..33491ff0e7bfa49cbbaae33e434094f83c11c084 100644 (file)
@@ -1,29 +1,48 @@
+#include "cl_client.qh"
+
 #include "waypointsprites.qh"
 
+#include "anticheat.qh"
 #include "cl_impulse.qh"
 #include "cl_player.qh"
 #include "ent_cs.qh"
-#include "g_subs.qh"
 #include "ipban.qh"
 #include "miscfunctions.qh"
 #include "portals.qh"
 #include "teamplay.qh"
 #include "playerdemo.qh"
-#include "secret.qh"
+#include "spawnpoints.qh"
+#include "g_damage.qh"
+#include "g_hook.qh"
+#include "command/common.qh"
+#include "cheats.qh"
+#include "g_world.qh"
+#include "race.qh"
+#include "antilag.qh"
+#include "campaign.qh"
+#include "command/common.qh"
 
 #include "bot/bot.qh"
 #include "bot/navigation.qh"
 
+#include "vehicles/vehicle.qh"
+
 #include "weapons/hitplot.qh"
 #include "weapons/weaponsystem.qh"
 
 #include "../common/net_notice.qh"
+#include "../common/physics.qh"
+
+#include "../common/triggers/subs.qh"
+#include "../common/triggers/triggers.qh"
+#include "../common/triggers/trigger/secret.qh"
+
+#include "../common/items/inventory.qh"
 
 #include "../common/monsters/sv_monsters.qh"
 
 #include "../warpzonelib/server.qh"
 
-float c1, c2, c3, c4;
 
 void send_CSQC_teamnagger() {
        WriteByte(MSG_BROADCAST, SVC_TEMPENTITY);
@@ -301,7 +320,7 @@ void FixPlayermodel()
        defaultskin = 0;
        chmdl = false;
 
-       if(autocvar_sv_defaultcharacter == 1)
+       if(autocvar_sv_defaultcharacter)
        {
                if(teamplay)
                {
@@ -409,7 +428,6 @@ void PutClientInServer (void)
        if(IS_PLAYER(self))
        {
                entity spot, oldself;
-               float j;
 
                accuracy_resend(self);
 
@@ -516,7 +534,7 @@ void PutClientInServer (void)
                self.respawn_flags = 0;
                self.respawn_time = 0;
                self.stat_respawn_time = 0;
-               self.scale = 0;
+               self.scale = autocvar_sv_player_scale;
                self.fade_time = 0;
                self.pain_frame = 0;
                self.pain_finished = 0;
@@ -598,13 +616,13 @@ void PutClientInServer (void)
                target_voicescript_clear(self);
 
                // reset fields the weapons may use
-               for (j = WEP_FIRST; j <= WEP_LAST; ++j)
+               for (int j = WEP_FIRST; j <= WEP_LAST; ++j)
                {
                        WEP_ACTION(j, WR_RESETPLAYER);
 
                        // all weapons must be fully loaded when we spawn
                        entity e = get_weaponinfo(j);
-                       if(e.spawnflags & WEP_FLAG_RELOADABLE) // prevent accessing undefined cvars
+                       if (e.spawnflags & WEP_FLAG_RELOADABLE) // prevent accessing undefined cvars
                                self.(weapon_load[j]) = e.reloading_ammo;
                }
 
@@ -651,7 +669,7 @@ void PutClientInServer (void)
 .float ebouncefactor, ebouncestop; // electro's values
 // TODO do we need all these fields, or should we stop autodetecting runtime
 // changes and just have a console command to update this?
-float ClientInit_SendEntity(entity to, float sf)
+float ClientInit_SendEntity(entity to, int sf)
 {
        WriteByte(MSG_ENTITY, ENT_CLIENT_INIT);
        WriteByte(MSG_ENTITY, g_nexball_meter_period * 32);
@@ -1082,6 +1100,7 @@ void ClientConnect (void)
        PlayerScore_Attach(self);
        ClientData_Attach();
        accuracy_init(self);
+       Inventory_new(self);
 
        bot_clientconnect();
 
@@ -1324,6 +1343,7 @@ void ClientDisconnect (void)
        bot_relinkplayerlist();
 
        accuracy_free(self);
+       Inventory_delete(self);
        ClientData_Detach();
        PlayerScore_Detach(self);
 
@@ -1661,55 +1681,17 @@ void SetZoomState(float z)
 
 void GetPressedKeys(void) {
        MUTATOR_CALLHOOK(GetPressedKeys);
-       if (self.movement.x > 0) // get if movement keys are pressed
-       {       // forward key pressed
-               self.pressedkeys |= KEY_FORWARD;
-               self.pressedkeys &= ~KEY_BACKWARD;
-       }
-       else if (self.movement.x < 0)
-       {       // backward key pressed
-               self.pressedkeys |= KEY_BACKWARD;
-               self.pressedkeys &= ~KEY_FORWARD;
-       }
-       else
-       {       // no x input
-               self.pressedkeys &= ~KEY_FORWARD;
-               self.pressedkeys &= ~KEY_BACKWARD;
-       }
-
-       if (self.movement.y > 0)
-       {       // right key pressed
-               self.pressedkeys |= KEY_RIGHT;
-               self.pressedkeys &= ~KEY_LEFT;
-       }
-       else if (self.movement.y < 0)
-       {       // left key pressed
-               self.pressedkeys |= KEY_LEFT;
-               self.pressedkeys &= ~KEY_RIGHT;
-       }
-       else
-       {       // no y input
-               self.pressedkeys &= ~KEY_RIGHT;
-               self.pressedkeys &= ~KEY_LEFT;
-       }
-
-       if (self.BUTTON_JUMP) // get if jump and crouch keys are pressed
-               self.pressedkeys |= KEY_JUMP;
-       else
-               self.pressedkeys &= ~KEY_JUMP;
-       if (self.BUTTON_CROUCH)
-               self.pressedkeys |= KEY_CROUCH;
-       else
-               self.pressedkeys &= ~KEY_CROUCH;
-
-       if (self.BUTTON_ATCK)
-               self.pressedkeys |= KEY_ATCK;
-       else
-               self.pressedkeys &= ~KEY_ATCK;
-       if (self.BUTTON_ATCK2)
-               self.pressedkeys |= KEY_ATCK2;
-       else
-               self.pressedkeys &= ~KEY_ATCK2;
+       #define X(var,bit,flag) (flag ? var |= bit : var &= ~bit)
+       X(self.pressedkeys, KEY_FORWARD,        self.movement_x > 0);
+       X(self.pressedkeys, KEY_BACKWARD,       self.movement_x < 0);
+       X(self.pressedkeys, KEY_RIGHT,          self.movement_y > 0);
+       X(self.pressedkeys, KEY_LEFT,           self.movement_y < 0);
+
+       X(self.pressedkeys, KEY_JUMP,           PHYS_INPUT_BUTTON_JUMP(self));
+       X(self.pressedkeys, KEY_CROUCH,         PHYS_INPUT_BUTTON_CROUCH(self));
+       X(self.pressedkeys, KEY_ATCK,           PHYS_INPUT_BUTTON_ATCK(self));
+       X(self.pressedkeys, KEY_ATCK2,          PHYS_INPUT_BUTTON_ATCK2(self));
+       #undef X
 }
 
 /*
@@ -2482,8 +2464,8 @@ void PlayerPreThink (void)
                        if (!self.crouch)
                        {
                                self.crouch = true;
-                               self.view_ofs = PL_CROUCH_VIEW_OFS;
-                               setsize (self, PL_CROUCH_MIN, PL_CROUCH_MAX);
+                               self.view_ofs = self.stat_pl_crouch_view_ofs;
+                               setsize (self, self.stat_pl_crouch_min, self.stat_pl_crouch_max);
                                // setanim(self, self.anim_duck, false, true, true); // this anim is BROKEN anyway
                        }
                }
@@ -2491,12 +2473,12 @@ void PlayerPreThink (void)
                {
                        if (self.crouch)
                        {
-                               tracebox(self.origin, PL_MIN, PL_MAX, self.origin, false, self);
+                               tracebox(self.origin, self.stat_pl_min, self.stat_pl_max, self.origin, false, self);
                                if (!trace_startsolid)
                                {
                                        self.crouch = false;
-                                       self.view_ofs = PL_VIEW_OFS;
-                                       setsize (self, PL_MIN, PL_MAX);
+                                       self.view_ofs = self.stat_pl_view_ofs;
+                                       setsize (self, self.stat_pl_min, self.stat_pl_max);
                                }
                        }
                }
diff --git a/qcsrc/server/cl_client.qh b/qcsrc/server/cl_client.qh
new file mode 100644 (file)
index 0000000..213a029
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef CL_CLIENT_H
+#define CL_CLIENT_H
+float c1, c2, c3, c4;
+
+void play_countdown(float finished, string samp);
+
+float CalcRotRegen(float current, float regenstable, float regenfactor, float regenlinear, float regenframetime, float rotstable, float rotfactor, float rotlinear, float rotframetime, float limit);
+
+float Spectate(entity pl);
+
+void CTS_ClientKill (entity e);
+
+#endif
index 2cc8e0215bb8c1b1f0be9620c2b484326f4acde0..bb4c171c87272a7ce10cba28b78a3654b17e01fc 100644 (file)
@@ -1,10 +1,19 @@
+#include "_all.qh"
 #include "round_handler.qh"
 
 #include "bot/waypoints.qh"
 
 #include "weapons/throwing.qh"
+#include "command/common.qh"
+#include "cheats.qh"
+#include "bot/navigation.qh"
+#include "weapons/selection.qh"
+#include "weapons/tracing.qh"
+#include "weapons/weaponsystem.qh"
+#include "vehicles/vehicle.qh"
+#include "waypointsprites.qh"
 
-#include "../common/weapons/weapons.qh"
+#include "../common/weapons/all.qh"
 
 /*
  * Impulse map:
@@ -132,7 +141,7 @@ void ImpulseCommands (void)
                if(self.deadflag == DEAD_NO)
                {
                        // custom order weapon cycling
-                       i = imp % 10;
+                       int i = imp % 10;
                        m = (imp - (210 + i)); // <0 for prev, =0 for best, >0 for next
                        W_CycleWeapon(self.(cvar_cl_weaponpriorities[i]), m);
                }
diff --git a/qcsrc/server/cl_physics.qc b/qcsrc/server/cl_physics.qc
deleted file mode 100644 (file)
index 3373423..0000000
+++ /dev/null
@@ -1,1366 +0,0 @@
-#if defined(CSQC)
-#elif defined(MENUQC)
-#elif defined(SVQC)
-       #include "../dpdefs/progsdefs.qh"
-    #include "../dpdefs/dpextensions.qh"
-    #include "../warpzonelib/mathlib.qh"
-    #include "../warpzonelib/server.qh"
-    #include "../common/constants.qh"
-    #include "../common/util.qh"
-    #include "../common/animdecide.qh"
-    #include "../common/monsters/sv_monsters.qh"
-    #include "../common/weapons/weapons.qh"
-    #include "t_items.qh"
-    #include "autocvars.qh"
-    #include "defs.qh"
-    #include "../common/notifications.qh"
-    #include "mutators/mutators_include.qh"
-    #include "../common/mapinfo.qh"
-    #include "../csqcmodellib/sv_model.qh"
-    #include "anticheat.qh"
-    #include "cheats.qh"
-    #include "g_hook.qh"
-    #include "race.qh"
-    #include "playerdemo.qh"
-#endif
-
-.float race_penalty;
-.float restart_jump;
-
-.float ladder_time;
-.entity ladder_entity;
-.float gravity;
-.float swamp_slowdown;
-.int lastflags;
-.float lastground;
-.float wasFlying;
-.float spectatorspeed;
-
-/*
-=============
-PlayerJump
-
-When you press the jump key
-returns true if handled
-=============
-*/
-float PlayerJump (void)
-{
-       if(self.frozen)
-               return true; // no jumping in freezetag when frozen
-
-       if(self.player_blocked)
-               return true; // no jumping while blocked
-
-       float doublejump = false;
-       float mjumpheight = autocvar_sv_jumpvelocity;
-
-       player_multijump = doublejump;
-       player_jumpheight = mjumpheight;
-       if(MUTATOR_CALLHOOK(PlayerJump))
-               return true;
-
-       doublejump = player_multijump;
-       mjumpheight = player_jumpheight;
-
-       if (autocvar_sv_doublejump)
-       {
-               tracebox(self.origin + '0 0 0.01', self.mins, self.maxs, self.origin - '0 0 0.01', MOVE_NORMAL, self);
-               if (trace_fraction < 1 && trace_plane_normal.z > 0.7)
-               {
-                       doublejump = true;
-
-                       // we MUST clip velocity here!
-                       float f;
-                       f = self.velocity * trace_plane_normal;
-                       if(f < 0)
-                               self.velocity -= f * trace_plane_normal;
-               }
-       }
-
-       if (self.waterlevel >= WATERLEVEL_SWIMMING)
-       {
-               self.velocity_z = self.stat_sv_maxspeed * 0.7;
-               return true;
-       }
-
-       if (!doublejump)
-               if (!(self.flags & FL_ONGROUND))
-                       return !(self.flags & FL_JUMPRELEASED);
-
-       if(self.cvar_cl_movement_track_canjump)
-               if (!(self.flags & FL_JUMPRELEASED))
-                       return true;
-
-       // sv_jumpspeedcap_min/sv_jumpspeedcap_max act as baseline
-       // velocity bounds.  Final velocity is bound between (jumpheight *
-       // min + jumpheight) and (jumpheight * max + jumpheight);
-
-       if(autocvar_sv_jumpspeedcap_min != "")
-       {
-               float minjumpspeed;
-
-               minjumpspeed = mjumpheight * stof(autocvar_sv_jumpspeedcap_min);
-
-               if (self.velocity.z < minjumpspeed)
-                       mjumpheight += minjumpspeed - self.velocity.z;
-       }
-
-       if(autocvar_sv_jumpspeedcap_max != "")
-       {
-               // don't do jump speedcaps on ramps to preserve old xonotic ramjump style
-               tracebox(self.origin + '0 0 0.01', self.mins, self.maxs, self.origin - '0 0 0.01', MOVE_NORMAL, self);
-
-               if(!(trace_fraction < 1 && trace_plane_normal.z < 0.98 && autocvar_sv_jumpspeedcap_max_disable_on_ramps))
-               {
-                       float maxjumpspeed;
-
-                       maxjumpspeed = mjumpheight * stof(autocvar_sv_jumpspeedcap_max);
-
-                       if (self.velocity.z > maxjumpspeed)
-                               mjumpheight -= self.velocity.z - maxjumpspeed;
-               }
-       }
-
-       if(!(self.lastflags & FL_ONGROUND))
-       {
-               if(autocvar_speedmeter)
-                       dprint(strcat("landing velocity: ", vtos(self.velocity), " (abs: ", ftos(vlen(self.velocity)), ")\n"));
-               if(self.lastground < time - 0.3)
-               {
-                       self.velocity_x *= (1 - autocvar_sv_friction_on_land);
-                       self.velocity_y *= (1 - autocvar_sv_friction_on_land);
-               }
-               if(self.jumppadcount > 1)
-                       dprint(strcat(ftos(self.jumppadcount), "x jumppad combo\n"));
-               self.jumppadcount = 0;
-       }
-
-       self.velocity_z = self.velocity.z + mjumpheight;
-       self.oldvelocity_z = self.velocity.z;
-
-       self.flags &= ~FL_ONGROUND;
-       self.flags &= ~FL_JUMPRELEASED;
-
-       animdecide_setaction(self, ANIMACTION_JUMP, true);
-
-       if(autocvar_g_jump_grunt)
-               PlayerSound(playersound_jump, CH_PLAYER, VOICETYPE_PLAYERSOUND);
-
-       self.restart_jump = -1; // restart jump anim next time
-       // value -1 is used to not use the teleport bit (workaround for tiny hitch when re-jumping)
-       return true;
-}
-void CheckWaterJump()
-{
-       vector start, end;
-
-// check for a jump-out-of-water
-       makevectors (self.angles);
-       start = self.origin;
-       start.z = start.z + 8;
-       v_forward.z = 0;
-       normalize(v_forward);
-       end = start + v_forward*24;
-       traceline (start, end, true, self);
-       if (trace_fraction < 1)
-       {       // solid at waist
-               start.z = start.z + self.maxs.z - 8;
-               end = start + v_forward*24;
-               self.movedir = trace_plane_normal * -50;
-               traceline (start, end, true, self);
-               if (trace_fraction == 1)
-               {       // open at eye level
-                       self.flags |= FL_WATERJUMP;
-                       self.velocity_z = 225;
-                       self.flags &= ~FL_JUMPRELEASED;
-                       self.teleport_time = time + 2;  // safety net
-                       return;
-               }
-       }
-}
-
-.float jetpack_stopped;
-// Hack: shouldn't need to know about this
-.float multijump_count;
-void CheckPlayerJump()
-{
-       float was_flying = self.items & IT_USING_JETPACK;
-
-       if (self.cvar_cl_jetpack_jump < 2)
-               self.items &= ~IT_USING_JETPACK;
-
-       if (self.BUTTON_JUMP || self.BUTTON_JETPACK)
-       {
-               float air_jump = !PlayerJump() || self.multijump_count > 0; // PlayerJump() has important side effects
-               float activate = self.cvar_cl_jetpack_jump && air_jump && self.BUTTON_JUMP || self.BUTTON_JETPACK;
-               float has_fuel = !autocvar_g_jetpack_fuel || self.ammo_fuel || self.items & IT_UNLIMITED_WEAPON_AMMO;
-               if (!(self.items & IT_JETPACK)) { }
-               else if (self.jetpack_stopped) { }
-               else if (!has_fuel)
-               {
-                       if (was_flying) // TODO: ran out of fuel message
-                               Send_Notification(NOTIF_ONE, self, MSG_INFO, INFO_JETPACK_NOFUEL);
-                       else if (activate)
-                               Send_Notification(NOTIF_ONE, self, MSG_INFO, INFO_JETPACK_NOFUEL);
-                       self.jetpack_stopped = true;
-                       self.items &= ~IT_USING_JETPACK;
-               }
-               else if (activate && !self.frozen)
-                       self.items |= IT_USING_JETPACK;
-       }
-       else
-       {
-               self.jetpack_stopped = false;
-               self.items &= ~IT_USING_JETPACK;
-       }
-       if (!self.BUTTON_JUMP)
-               self.flags |= FL_JUMPRELEASED;
-
-       if (self.waterlevel == WATERLEVEL_SWIMMING)
-               CheckWaterJump ();
-}
-
-float racecar_angle(float forward, float down)
-{
-       float ret, angle_mult;
-
-       if(forward < 0)
-       {
-               forward = -forward;
-               down = -down;
-       }
-
-       ret = vectoyaw('0 1 0' * down + '1 0 0' * forward);
-
-       angle_mult = forward / (800 + forward);
-
-       if(ret > 180)
-               return ret * angle_mult + 360 * (1 - angle_mult);
-       else
-               return ret * angle_mult;
-}
-
-void RaceCarPhysics()
-{
-       // using this move type for "big rigs"
-       // the engine does not push the entity!
-
-       float accel, steer, f, myspeed, steerfactor;
-       vector angles_save, rigvel;
-
-       angles_save = self.angles;
-       accel = bound(-1, self.movement.x / self.stat_sv_maxspeed, 1);
-       steer = bound(-1, self.movement.y / self.stat_sv_maxspeed, 1);
-
-       if(g_bugrigs_reverse_speeding)
-       {
-               if(accel < 0)
-               {
-                       // back accel is DIGITAL
-                       // to prevent speedhack
-                       if(accel < -0.5)
-                               accel = -1;
-                       else
-                               accel = 0;
-               }
-       }
-
-       self.angles_x = 0;
-       self.angles_z = 0;
-       makevectors(self.angles); // new forward direction!
-
-       if(self.flags & FL_ONGROUND || g_bugrigs_air_steering)
-       {
-               float upspeed, accelfactor;
-
-               myspeed = self.velocity * v_forward;
-               upspeed = self.velocity * v_up;
-
-               // responsiveness factor for steering and acceleration
-               f = 1 / (1 + pow(max(-myspeed, myspeed) / g_bugrigs_speed_ref, g_bugrigs_speed_pow));
-               //MAXIMA: f(v) := 1 / (1 + (v / g_bugrigs_speed_ref) ^ g_bugrigs_speed_pow);
-
-               if(myspeed < 0 && g_bugrigs_reverse_spinning)
-                       steerfactor = -myspeed * g_bugrigs_steer;
-               else
-                       steerfactor = -myspeed * f * g_bugrigs_steer;
-
-               if(myspeed < 0 && g_bugrigs_reverse_speeding)
-                       accelfactor = g_bugrigs_accel;
-               else
-                       accelfactor = f * g_bugrigs_accel;
-               //MAXIMA: accel(v) := f(v) * g_bugrigs_accel;
-
-               if(accel < 0)
-               {
-                       if(myspeed > 0)
-                       {
-                               myspeed = max(0, myspeed - frametime * (g_bugrigs_friction_floor - g_bugrigs_friction_brake * accel));
-                       }
-                       else
-                       {
-                               if(!g_bugrigs_reverse_speeding)
-                                       myspeed = min(0, myspeed + frametime * g_bugrigs_friction_floor);
-                       }
-               }
-               else
-               {
-                       if(myspeed >= 0)
-                       {
-                               myspeed = max(0, myspeed - frametime * g_bugrigs_friction_floor);
-                       }
-                       else
-                       {
-                               if(g_bugrigs_reverse_stopping)
-                                       myspeed = 0;
-                               else
-                                       myspeed = min(0, myspeed + frametime * (g_bugrigs_friction_floor + g_bugrigs_friction_brake * accel));
-                       }
-               }
-               // terminal velocity = velocity at which 50 == accelfactor, that is, 1549 units/sec
-               //MAXIMA: friction(v) := g_bugrigs_friction_floor;
-
-               self.angles_y += steer * frametime * steerfactor; // apply steering
-               makevectors(self.angles); // new forward direction!
-
-               myspeed += accel * accelfactor * frametime;
-
-               rigvel = myspeed * v_forward + '0 0 1' * upspeed;
-       }
-       else
-       {
-               myspeed = vlen(self.velocity);
-
-               // responsiveness factor for steering and acceleration
-               f = 1 / (1 + pow(max(0, myspeed / g_bugrigs_speed_ref), g_bugrigs_speed_pow));
-               steerfactor = -myspeed * f;
-               self.angles_y += steer * frametime * steerfactor; // apply steering
-
-               rigvel = self.velocity;
-               makevectors(self.angles); // new forward direction!
-       }
-
-       rigvel = rigvel * max(0, 1 - vlen(rigvel) * g_bugrigs_friction_air * frametime);
-       //MAXIMA: airfriction(v) := v * v * g_bugrigs_friction_air;
-       //MAXIMA: total_acceleration(v) := accel(v) - friction(v) - airfriction(v);
-       //MAXIMA: solve(total_acceleration(v) = 0, v);
-
-       if(g_bugrigs_planar_movement)
-       {
-               vector rigvel_xy, neworigin, up;
-               float mt;
-
-               rigvel.z -= frametime * autocvar_sv_gravity; // 4x gravity plays better
-               rigvel_xy = vec2(rigvel);
-
-               if(g_bugrigs_planar_movement_car_jumping)
-                       mt = MOVE_NORMAL;
-               else
-                       mt = MOVE_NOMONSTERS;
-
-               tracebox(self.origin, self.mins, self.maxs, self.origin + '0 0 1024', mt, self);
-               up = trace_endpos - self.origin;
-
-               // BUG RIGS: align the move to the surface instead of doing collision testing
-               // can we move?
-               tracebox(trace_endpos, self.mins, self.maxs, trace_endpos + rigvel_xy * frametime, mt, self);
-
-               // align to surface
-               tracebox(trace_endpos, self.mins, self.maxs, trace_endpos - up + '0 0 1' * rigvel.z * frametime, mt, self);
-
-               if(trace_fraction < 0.5)
-               {
-                       trace_fraction = 1;
-                       neworigin = self.origin;
-               }
-               else
-                       neworigin = trace_endpos;
-
-               if(trace_fraction < 1)
-               {
-                       // now set angles_x so that the car points parallel to the surface
-                       self.angles = vectoangles(
-                                       '1 0 0' * v_forward.x * trace_plane_normal.z
-                                       +
-                                       '0 1 0' * v_forward.y * trace_plane_normal.z
-                                       +
-                                       '0 0 1' * -(v_forward.x * trace_plane_normal.x + v_forward.y * trace_plane_normal.y)
-                                       );
-                       self.flags |= FL_ONGROUND;
-               }
-               else
-               {
-                       // now set angles_x so that the car points forward, but is tilted in velocity direction
-                       self.flags &= ~FL_ONGROUND;
-               }
-
-               self.velocity = (neworigin - self.origin) * (1.0 / frametime);
-               self.movetype = MOVETYPE_NOCLIP;
-       }
-       else
-       {
-               rigvel.z -= frametime * autocvar_sv_gravity; // 4x gravity plays better
-               self.velocity = rigvel;
-               self.movetype = MOVETYPE_FLY;
-       }
-
-       trace_fraction = 1;
-       tracebox(self.origin, self.mins, self.maxs, self.origin - '0 0 4', MOVE_NORMAL, self);
-       if(trace_fraction != 1)
-       {
-               self.angles = vectoangles2(
-                               '1 0 0' * v_forward.x * trace_plane_normal.z
-                               +
-                               '0 1 0' * v_forward.y * trace_plane_normal.z
-                               +
-                               '0 0 1' * -(v_forward.x * trace_plane_normal.x + v_forward.y * trace_plane_normal.y),
-                               trace_plane_normal
-                               );
-       }
-       else
-       {
-               vector vel_local;
-
-               vel_local.x = v_forward * self.velocity;
-               vel_local.y = v_right * self.velocity;
-               vel_local.z = v_up * self.velocity;
-
-               self.angles_x = racecar_angle(vel_local.x, vel_local.z);
-               self.angles_z = racecar_angle(-vel_local.y, vel_local.z);
-       }
-
-       // smooth the angles
-       vector vf1, vu1, smoothangles;
-       makevectors(self.angles);
-       f = bound(0, frametime * g_bugrigs_angle_smoothing, 1);
-       if(f == 0)
-               f = 1;
-       vf1 = v_forward * f;
-       vu1 = v_up * f;
-       makevectors(angles_save);
-       vf1 = vf1 + v_forward * (1 - f);
-       vu1 = vu1 + v_up * (1 - f);
-       smoothangles = vectoangles2(vf1, vu1);
-       self.angles_x = -smoothangles.x;
-       self.angles_z =  smoothangles.z;
-}
-
-float IsMoveInDirection(vector mv, float angle) // key mix factor
-{
-       if(mv.x == 0 && mv.y == 0)
-               return 0; // avoid division by zero
-       angle -= RAD2DEG * atan2(mv.y, mv.x);
-       angle = remainder(angle, 360) / 45;
-       if(angle >  1)
-               return 0;
-       if(angle < -1)
-               return 0;
-       return 1 - fabs(angle);
-}
-
-float GeomLerp(float a, float lerp, float b)
-{
-       if(a == 0)
-       {
-               if(lerp < 1)
-                       return 0;
-               else
-                       return b;
-       }
-       if(b == 0)
-       {
-               if(lerp > 0)
-                       return 0;
-               else
-                       return a;
-       }
-       return a * pow(fabs(b / a), lerp);
-}
-
-void CPM_PM_Aircontrol(vector wishdir, float wishspeed)
-{
-       float zspeed, xyspeed, dot, k;
-
-#if 0
-       // this doesn't play well with analog input
-       if(self.movement_x == 0 || self.movement.y != 0)
-               return; // can't control movement if not moving forward or backward
-       k = 32;
-#else
-       k = 32 * (2 * IsMoveInDirection(self.movement, 0) - 1);
-       if(k <= 0)
-               return;
-#endif
-
-       k *= bound(0, wishspeed / autocvar_sv_maxairspeed, 1);
-
-       zspeed = self.velocity.z;
-       self.velocity_z = 0;
-       xyspeed = vlen(self.velocity); self.velocity = normalize(self.velocity);
-
-       dot = self.velocity * wishdir;
-
-       if(dot > 0) // we can't change direction while slowing down
-       {
-               k *= pow(dot, autocvar_sv_aircontrol_power)*frametime;
-               xyspeed = max(0, xyspeed - autocvar_sv_aircontrol_penalty * sqrt(max(0, 1 - dot*dot)) * k/32);
-               k *= autocvar_sv_aircontrol;
-               self.velocity = normalize(self.velocity * xyspeed + wishdir * k);
-       }
-
-       self.velocity = self.velocity * xyspeed;
-       self.velocity_z = zspeed;
-}
-
-float AdjustAirAccelQW(float accelqw, float factor)
-{
-       return copysign(bound(0.000001, 1 - (1 - fabs(accelqw)) * factor, 1), accelqw);
-}
-
-// example config for alternate speed clamping:
-//   sv_airaccel_qw 0.8
-//   sv_airaccel_sideways_friction 0
-//   prvm_globalset server speedclamp_mode 1
-//     (or 2)
-void PM_Accelerate(vector wishdir, float wishspeed, float wishspeed0, float accel, float accelqw, float stretchfactor, float sidefric, float speedlimit)
-{
-       float vel_straight;
-       float velZ;
-       vector vel_perpend;
-       float step;
-
-       vector vel_xy;
-       float vel_xy_current;
-       float vel_xy_backward, vel_xy_forward;
-       float speedclamp;
-
-       if(stretchfactor > 0)
-               speedclamp = stretchfactor;
-       else if(accelqw < 0)
-               speedclamp = 1; // full clamping, no stretch
-       else
-               speedclamp = -1; // no clamping
-
-       if(accelqw < 0)
-               accelqw = -accelqw;
-
-       if(autocvar_sv_gameplayfix_q2airaccelerate)
-               wishspeed0 = wishspeed;
-
-       vel_straight = self.velocity * wishdir;
-       velZ = self.velocity.z;
-       vel_xy = vec2(self.velocity);
-       vel_perpend = vel_xy - vel_straight * wishdir;
-
-       step = accel * frametime * wishspeed0;
-
-       vel_xy_current  = vlen(vel_xy);
-       if(speedlimit)
-               accelqw = AdjustAirAccelQW(accelqw, (speedlimit - bound(wishspeed, vel_xy_current, speedlimit)) / max(1, speedlimit - wishspeed));
-       vel_xy_forward  = vel_xy_current + bound(0, wishspeed - vel_xy_current, step) * accelqw + step * (1 - accelqw);
-       vel_xy_backward = vel_xy_current - bound(0, wishspeed + vel_xy_current, step) * accelqw - step * (1 - accelqw);
-       if(vel_xy_backward < 0)
-               vel_xy_backward = 0; // not that it REALLY occurs that this would cause wrong behaviour afterwards
-
-       vel_straight = vel_straight + bound(0, wishspeed - vel_straight, step) * accelqw + step * (1 - accelqw);
-
-       if(sidefric < 0 && (vel_perpend*vel_perpend))
-               // negative: only apply so much sideways friction to stay below the speed you could get by "braking"
-       {
-               float f, fminimum;
-               f = max(0, 1 + frametime * wishspeed * sidefric);
-               fminimum = (vel_xy_backward*vel_xy_backward - vel_straight*vel_straight) / (vel_perpend*vel_perpend);
-               // this cannot be > 1
-               if(fminimum <= 0)
-                       vel_perpend = vel_perpend * max(0, f);
-               else
-               {
-                       fminimum = sqrt(fminimum);
-                       vel_perpend = vel_perpend * max(fminimum, f);
-               }
-       }
-       else
-               vel_perpend = vel_perpend * max(0, 1 - frametime * wishspeed * sidefric);
-
-       vel_xy = vel_straight * wishdir + vel_perpend;
-
-       if(speedclamp >= 0)
-       {
-               float vel_xy_preclamp;
-               vel_xy_preclamp = vlen(vel_xy);
-               if(vel_xy_preclamp > 0) // prevent division by zero
-               {
-                       vel_xy_current += (vel_xy_forward - vel_xy_current) * speedclamp;
-                       if(vel_xy_current < vel_xy_preclamp)
-                               vel_xy = vel_xy * (vel_xy_current / vel_xy_preclamp);
-               }
-       }
-
-       self.velocity = vel_xy + velZ * '0 0 1';
-}
-
-void PM_AirAccelerate(vector wishdir, float wishspeed)
-{
-       vector curvel, wishvel, acceldir, curdir;
-       float addspeed, accelspeed, curspeed, f;
-       float dot;
-
-       if(wishspeed == 0)
-               return;
-
-       curvel = self.velocity;
-       curvel.z = 0;
-       curspeed = vlen(curvel);
-
-       if(wishspeed > curspeed * 1.01)
-       {
-               wishspeed = min(wishspeed, curspeed + autocvar_sv_warsowbunny_airforwardaccel * self.stat_sv_maxspeed * frametime);
-       }
-       else
-       {
-               f = max(0, (autocvar_sv_warsowbunny_topspeed - curspeed) / (autocvar_sv_warsowbunny_topspeed - self.stat_sv_maxspeed));
-               wishspeed = max(curspeed, self.stat_sv_maxspeed) + autocvar_sv_warsowbunny_accel * f * self.stat_sv_maxspeed * frametime;
-       }
-       wishvel = wishdir * wishspeed;
-       acceldir = wishvel - curvel;
-       addspeed = vlen(acceldir);
-       acceldir = normalize(acceldir);
-
-       accelspeed = min(addspeed, autocvar_sv_warsowbunny_turnaccel * self.stat_sv_maxspeed * frametime);
-
-       if(autocvar_sv_warsowbunny_backtosideratio < 1)
-       {
-               curdir = normalize(curvel);
-               dot = acceldir * curdir;
-               if(dot < 0)
-                       acceldir = acceldir - (1 - autocvar_sv_warsowbunny_backtosideratio) * dot * curdir;
-       }
-
-       self.velocity += accelspeed * acceldir;
-}
-
-.vector movement_old;
-.float buttons_old;
-.vector v_angle_old;
-.string lastclassname;
-
-.float() PlayerPhysplug;
-
-string specialcommand = "xwxwxsxsxaxdxaxdx1x ";
-.float specialcommand_pos;
-void SpecialCommand()
-{
-#ifdef TETRIS
-       TetrisImpulse();
-#else
-       if(!CheatImpulse(99))
-               print("A hollow voice says \"Plugh\".\n");
-#endif
-}
-
-float speedaward_speed;
-string speedaward_holder;
-string speedaward_uid;
-void race_send_speedaward(float msg)
-{
-       // send the best speed of the round
-       WriteByte(msg, SVC_TEMPENTITY);
-       WriteByte(msg, TE_CSQC_RACE);
-       WriteByte(msg, RACE_NET_SPEED_AWARD);
-       WriteInt24_t(msg, floor(speedaward_speed+0.5));
-       WriteString(msg, speedaward_holder);
-}
-
-float speedaward_alltimebest;
-string speedaward_alltimebest_holder;
-string speedaward_alltimebest_uid;
-void race_send_speedaward_alltimebest(float msg)
-{
-       // send the best speed
-       WriteByte(msg, SVC_TEMPENTITY);
-       WriteByte(msg, TE_CSQC_RACE);
-       WriteByte(msg, RACE_NET_SPEED_AWARD_BEST);
-       WriteInt24_t(msg, floor(speedaward_alltimebest+0.5));
-       WriteString(msg, speedaward_alltimebest_holder);
-}
-
-string GetMapname(void);
-float speedaward_lastupdate;
-float speedaward_lastsent;
-void SV_PlayerPhysics()
-{
-       vector wishvel, wishdir, v;
-       float wishspeed, f, maxspd_mod, spd, maxairspd, airaccel, swampspd_mod, buttons;
-       string temps;
-       int buttons_prev;
-       float not_allowed_to_move;
-       string c;
-
-       WarpZone_PlayerPhysics_FixVAngle();
-
-       maxspd_mod = 1;
-       if(self.ballcarried)
-               if(g_keepaway)
-                       maxspd_mod *= autocvar_g_keepaway_ballcarrier_highspeed;
-
-       maxspd_mod *= autocvar_g_movement_highspeed;
-
-       // fix physics stats for g_movement_highspeed
-       // TODO maybe rather use maxairspeed? needs testing
-       self.stat_sv_airaccel_qw = AdjustAirAccelQW(autocvar_sv_airaccel_qw, maxspd_mod);
-       if(autocvar_sv_airstrafeaccel_qw)
-               self.stat_sv_airstrafeaccel_qw = AdjustAirAccelQW(autocvar_sv_airstrafeaccel_qw, maxspd_mod);
-       else
-               self.stat_sv_airstrafeaccel_qw = 0;
-       self.stat_sv_airspeedlimit_nonqw = autocvar_sv_airspeedlimit_nonqw * maxspd_mod;
-       self.stat_sv_maxspeed = autocvar_sv_maxspeed * maxspd_mod; // also slow walking
-
-    if(self.PlayerPhysplug)
-        if(self.PlayerPhysplug())
-            return;
-
-       self.race_movetime_frac += frametime;
-       f = floor(self.race_movetime_frac);
-       self.race_movetime_frac -= f;
-       self.race_movetime_count += f;
-       self.race_movetime = self.race_movetime_frac + self.race_movetime_count;
-
-       anticheat_physics();
-
-       buttons = self.BUTTON_ATCK + 2 * self.BUTTON_JUMP + 4 * self.BUTTON_ATCK2 + 8 * self.BUTTON_ZOOM + 16 * self.BUTTON_CROUCH + 32 * self.BUTTON_HOOK + 64 * self.BUTTON_USE + 128 * (self.movement.x < 0) + 256 * (self.movement.x > 0) + 512 * (self.movement.y < 0) + 1024 * (self.movement.y > 0);
-
-       if(!buttons)
-               c = "x";
-       else if(buttons == 1)
-               c = "1";
-       else if(buttons == 2)
-               c = " ";
-       else if(buttons == 128)
-               c = "s";
-       else if(buttons == 256)
-               c = "w";
-       else if(buttons == 512)
-               c = "a";
-       else if(buttons == 1024)
-               c = "d";
-       else
-               c = "?";
-
-       if(c == substring(specialcommand, self.specialcommand_pos, 1))
-       {
-               self.specialcommand_pos += 1;
-               if(self.specialcommand_pos >= strlen(specialcommand))
-               {
-                       self.specialcommand_pos = 0;
-                       SpecialCommand();
-                       return;
-               }
-       }
-       else if(self.specialcommand_pos && (c != substring(specialcommand, self.specialcommand_pos - 1, 1)))
-               self.specialcommand_pos = 0;
-
-       if(sv_maxidle > 0)
-       {
-               if(buttons != self.buttons_old || self.movement != self.movement_old || self.v_angle != self.v_angle_old)
-                       self.parm_idlesince = time;
-       }
-       buttons_prev = self.buttons_old;
-       self.buttons_old = buttons;
-       self.movement_old = self.movement;
-       self.v_angle_old = self.v_angle;
-
-       if(time < self.nickspamtime)
-       if(self.nickspamcount >= autocvar_g_nick_flood_penalty_yellow)
-       {
-               // slight annoyance for nick change scripts
-               self.movement = -1 * self.movement;
-               self.BUTTON_ATCK = self.BUTTON_JUMP = self.BUTTON_ATCK2 = self.BUTTON_ZOOM = self.BUTTON_CROUCH = self.BUTTON_HOOK = self.BUTTON_USE = 0;
-
-               if(self.nickspamcount >= autocvar_g_nick_flood_penalty_red) // if you are persistent and the slight annoyance above does not stop you, I'll show you!
-               {
-                       self.angles_x = random() * 360;
-                       self.angles_y = random() * 360;
-                       // at least I'm not forcing retardedview by also assigning to angles_z
-                       self.fixangle = true;
-               }
-       }
-
-       if (self.punchangle != '0 0 0')
-       {
-               f = vlen(self.punchangle) - 10 * frametime;
-               if (f > 0)
-                       self.punchangle = normalize(self.punchangle) * f;
-               else
-                       self.punchangle = '0 0 0';
-       }
-
-       if (self.punchvector != '0 0 0')
-       {
-               f = vlen(self.punchvector) - 30 * frametime;
-               if (f > 0)
-                       self.punchvector = normalize(self.punchvector) * f;
-               else
-                       self.punchvector = '0 0 0';
-       }
-
-       if (IS_BOT_CLIENT(self))
-       {
-               if(playerdemo_read())
-                       return;
-               bot_think();
-       }
-
-       if(IS_PLAYER(self))
-       {
-               if(self.race_penalty)
-                       if(time > self.race_penalty)
-                               self.race_penalty = 0;
-
-               not_allowed_to_move = 0;
-               if(self.race_penalty)
-                       not_allowed_to_move = 1;
-               if(time < game_starttime)
-                       not_allowed_to_move = 1;
-
-               if(not_allowed_to_move)
-               {
-                       self.velocity = '0 0 0';
-                       self.movetype = MOVETYPE_NONE;
-                       self.disableclientprediction = 2;
-               }
-               else if(self.disableclientprediction == 2)
-               {
-                       if(self.movetype == MOVETYPE_NONE)
-                               self.movetype = MOVETYPE_WALK;
-                       self.disableclientprediction = 0;
-               }
-       }
-
-       if (self.movetype == MOVETYPE_NONE)
-               return;
-
-       // when we get here, disableclientprediction cannot be 2
-       self.disableclientprediction = 0;
-       if(time < self.ladder_time)
-               self.disableclientprediction = 1;
-
-       if(time < self.spider_slowness)
-       {
-               self.stat_sv_maxspeed *= 0.5; // half speed while slow from spider
-               self.stat_sv_airspeedlimit_nonqw *= 0.5;
-       }
-
-       if(self.frozen)
-       {
-               if(autocvar_sv_dodging_frozen && IS_REAL_CLIENT(self))
-               {
-                       self.movement_x = bound(-5, self.movement.x, 5);
-                       self.movement_y = bound(-5, self.movement.y, 5);
-                       self.movement_z = bound(-5, self.movement.z, 5);
-               }
-               else
-                       self.movement = '0 0 0';
-               self.disableclientprediction = 1;
-
-               vector midpoint = ((self.absmin + self.absmax) * 0.5);
-               if(pointcontents(midpoint) == CONTENT_WATER)
-               {
-                       self.velocity = self.velocity * 0.5;
-
-                       if(pointcontents(midpoint + '0 0 16') == CONTENT_WATER)
-                               { self.velocity_z = 200; }
-               }
-       }
-
-       MUTATOR_CALLHOOK(PlayerPhysics);
-
-       if(self.player_blocked)
-       {
-               self.movement = '0 0 0';
-               self.disableclientprediction = 1;
-       }
-
-       maxspd_mod = 1;
-
-       swampspd_mod = 1;
-       if(self.in_swamp) {
-               swampspd_mod = self.swamp_slowdown; //cvar("g_balance_swamp_moverate");
-       }
-
-       // conveyors: first fix velocity
-       if(self.conveyor.state)
-               self.velocity -= self.conveyor.movedir;
-
-       if (!IS_PLAYER(self))
-       {
-               maxspd_mod = autocvar_sv_spectator_speed_multiplier;
-               if(!self.spectatorspeed)
-                       self.spectatorspeed = maxspd_mod;
-               if(self.impulse && self.impulse <= 19 || (self.impulse >= 200 && self.impulse <= 209) || (self.impulse >= 220 && self.impulse <= 229))
-               {
-                       if(self.lastclassname != "player")
-                       {
-                               if(self.impulse == 10 || self.impulse == 15 || self.impulse == 18 || (self.impulse >= 200 && self.impulse <= 209))
-                                       self.spectatorspeed = bound(1, self.spectatorspeed + 0.5, 5);
-                               else if(self.impulse == 11)
-                                       self.spectatorspeed = maxspd_mod;
-                               else if(self.impulse == 12 || self.impulse == 16  || self.impulse == 19 || (self.impulse >= 220 && self.impulse <= 229))
-                                       self.spectatorspeed = bound(1, self.spectatorspeed - 0.5, 5);
-                               else if(self.impulse >= 1 && self.impulse <= 9)
-                                       self.spectatorspeed = 1 + 0.5 * (self.impulse - 1);
-                       } // otherwise just clear
-                       self.impulse = 0;
-               }
-               maxspd_mod = self.spectatorspeed;
-       }
-
-       spd = max(self.stat_sv_maxspeed, autocvar_sv_maxairspeed) * maxspd_mod * swampspd_mod;
-       if(self.speed != spd)
-       {
-               self.speed = spd;
-               temps = ftos(spd);
-               stuffcmd(self, strcat("cl_forwardspeed ", temps, "\n"));
-               stuffcmd(self, strcat("cl_backspeed ", temps, "\n"));
-               stuffcmd(self, strcat("cl_sidespeed ", temps, "\n"));
-               stuffcmd(self, strcat("cl_upspeed ", temps, "\n"));
-       }
-
-       maxspd_mod *= swampspd_mod; // only one common speed modder please!
-       swampspd_mod = 1;
-
-       // if dead, behave differently
-       if (self.deadflag)
-               goto end;
-
-       if (!self.fixangle && !g_bugrigs)
-       {
-               self.angles_x = 0;
-               self.angles_y = self.v_angle.y;
-               self.angles_z = 0;
-       }
-
-       if(self.flags & FL_ONGROUND)
-       if(IS_PLAYER(self)) // no fall sounds for observers thank you very much
-       if(self.wasFlying)
-       {
-               self.wasFlying = 0;
-
-               if(self.waterlevel < WATERLEVEL_SWIMMING)
-               if(time >= self.ladder_time)
-               if (!self.hook)
-               {
-                       self.nextstep = time + 0.3 + random() * 0.1;
-                       trace_dphitq3surfaceflags = 0;
-                       tracebox(self.origin, self.mins, self.maxs, self.origin - '0 0 1', MOVE_NOMONSTERS, self);
-                       if (!(trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOSTEPS))
-                       {
-                               if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_METALSTEPS)
-                                       GlobalSound(globalsound_metalfall, CH_PLAYER, VOICETYPE_PLAYERSOUND);
-                               else
-                                       GlobalSound(globalsound_fall, CH_PLAYER, VOICETYPE_PLAYERSOUND);
-                       }
-               }
-       }
-
-       if(IsFlying(self))
-               self.wasFlying = 1;
-
-       if(IS_PLAYER(self))
-               CheckPlayerJump();
-
-       if (self.flags & FL_WATERJUMP )
-       {
-               self.velocity_x = self.movedir.x;
-               self.velocity_y = self.movedir.y;
-               if (time > self.teleport_time || self.waterlevel == WATERLEVEL_NONE)
-               {
-                       self.flags &= ~FL_WATERJUMP;
-                       self.teleport_time = 0;
-               }
-       }
-       else if (g_bugrigs && IS_PLAYER(self))
-       {
-               RaceCarPhysics();
-       }
-       else if (self.movetype == MOVETYPE_NOCLIP || self.movetype == MOVETYPE_FLY || self.movetype == MOVETYPE_FLY_WORLDONLY)
-       {
-               // noclipping or flying
-               self.flags &= ~FL_ONGROUND;
-
-               self.velocity = self.velocity * (1 - frametime * autocvar_sv_friction);
-               makevectors(self.v_angle);
-               //wishvel = v_forward * self.movement_x + v_right * self.movement_y + v_up * self.movement_z;
-               wishvel = v_forward * self.movement.x + v_right * self.movement.y + '0 0 1' * self.movement.z;
-               // acceleration
-               wishdir = normalize(wishvel);
-               wishspeed = vlen(wishvel);
-               if (wishspeed > self.stat_sv_maxspeed*maxspd_mod)
-                       wishspeed = self.stat_sv_maxspeed*maxspd_mod;
-               if (time >= self.teleport_time)
-                       PM_Accelerate(wishdir, wishspeed, wishspeed, autocvar_sv_accelerate*maxspd_mod, 1, 0, 0, 0);
-       }
-       else if (self.waterlevel >= WATERLEVEL_SWIMMING)
-       {
-               // swimming
-               self.flags &= ~FL_ONGROUND;
-
-               makevectors(self.v_angle);
-               //wishvel = v_forward * self.movement_x + v_right * self.movement_y + v_up * self.movement_z;
-               wishvel = v_forward * self.movement.x + v_right * self.movement.y + '0 0 1' * self.movement.z;
-               if (wishvel == '0 0 0')
-                       wishvel = '0 0 -60'; // drift towards bottom
-
-               wishdir = normalize(wishvel);
-               wishspeed = vlen(wishvel);
-               if (wishspeed > self.stat_sv_maxspeed*maxspd_mod)
-                       wishspeed = self.stat_sv_maxspeed*maxspd_mod;
-               wishspeed = wishspeed * 0.7;
-
-               // water friction
-               self.velocity = self.velocity * (1 - frametime * autocvar_sv_friction);
-
-               // water acceleration
-               PM_Accelerate(wishdir, wishspeed, wishspeed, autocvar_sv_accelerate*maxspd_mod, 1, 0, 0, 0);
-       }
-       else if (time < self.ladder_time)
-       {
-               // on a spawnfunc_func_ladder or swimming in spawnfunc_func_water
-               self.flags &= ~FL_ONGROUND;
-
-               float g;
-               g = autocvar_sv_gravity * frametime;
-               if(self.gravity)
-                       g *= self.gravity;
-               if(autocvar_sv_gameplayfix_gravityunaffectedbyticrate)
-               {
-                       g *= 0.5;
-                       self.velocity_z += g;
-               }
-
-               self.velocity = self.velocity * (1 - frametime * autocvar_sv_friction);
-               makevectors(self.v_angle);
-               //wishvel = v_forward * self.movement_x + v_right * self.movement_y + v_up * self.movement_z;
-               wishvel = v_forward * self.movement.x + v_right * self.movement.y + '0 0 1' * self.movement.z;
-               self.velocity_z += g;
-               if (self.ladder_entity.classname == "func_water")
-               {
-                       f = vlen(wishvel);
-                       if (f > self.ladder_entity.speed)
-                               wishvel = wishvel * (self.ladder_entity.speed / f);
-
-                       self.watertype = self.ladder_entity.skin;
-                       f = self.ladder_entity.origin.z + self.ladder_entity.maxs.z;
-                       if ((self.origin.z + self.view_ofs.z) < f)
-                               self.waterlevel = WATERLEVEL_SUBMERGED;
-                       else if ((self.origin.z + (self.mins.z + self.maxs.z) * 0.5) < f)
-                               self.waterlevel = WATERLEVEL_SWIMMING;
-                       else if ((self.origin.z + self.mins.z + 1) < f)
-                               self.waterlevel = WATERLEVEL_WETFEET;
-                       else
-                       {
-                               self.waterlevel = WATERLEVEL_NONE;
-                               self.watertype = CONTENT_EMPTY;
-                       }
-               }
-               // acceleration
-               wishdir = normalize(wishvel);
-               wishspeed = vlen(wishvel);
-               if (wishspeed > self.stat_sv_maxspeed*maxspd_mod)
-                       wishspeed = self.stat_sv_maxspeed*maxspd_mod;
-               if (time >= self.teleport_time)
-               {
-                       // water acceleration
-                       PM_Accelerate(wishdir, wishspeed, wishspeed, autocvar_sv_accelerate*maxspd_mod, 1, 0, 0, 0);
-               }
-       }
-       else if (self.items & IT_USING_JETPACK)
-       {
-               //makevectors(self.v_angle_y * '0 1 0');
-               makevectors(self.v_angle);
-               wishvel = v_forward * self.movement.x + v_right * self.movement.y;
-               // add remaining speed as Z component
-               maxairspd = autocvar_sv_maxairspeed*max(1, maxspd_mod);
-               // fix speedhacks :P
-               wishvel = normalize(wishvel) * min(vlen(wishvel) / maxairspd, 1);
-               // add the unused velocity as up component
-               wishvel.z = 0;
-
-               // if(self.BUTTON_JUMP)
-                       wishvel.z = sqrt(max(0, 1 - wishvel * wishvel));
-
-               // it is now normalized, so...
-               float a_side, a_up, a_add, a_diff;
-               a_side = autocvar_g_jetpack_acceleration_side;
-               a_up = autocvar_g_jetpack_acceleration_up;
-               a_add = autocvar_g_jetpack_antigravity * autocvar_sv_gravity;
-
-               wishvel.x *= a_side;
-               wishvel.y *= a_side;
-               wishvel.z *= a_up;
-               wishvel.z += a_add;
-
-               float best;
-               best = 0;
-               //////////////////////////////////////////////////////////////////////////////////////
-               // finding the maximum over all vectors of above form
-               // with wishvel having an absolute value of 1
-               //////////////////////////////////////////////////////////////////////////////////////
-               // we're finding the maximum over
-               //   f(a_side, a_up, a_add, z) := a_side * (1 - z^2) + (a_add + a_up * z)^2;
-               // for z in the range from -1 to 1
-               //////////////////////////////////////////////////////////////////////////////////////
-               // maximum is EITHER attained at the single extreme point:
-               a_diff = a_side * a_side - a_up * a_up;
-               if(a_diff != 0)
-               {
-                       f = a_add * a_up / a_diff; // this is the zero of diff(f(a_side, a_up, a_add, z), z)
-                       if(f > -1 && f < 1) // can it be attained?
-                       {
-                               best = (a_diff + a_add * a_add) * (a_diff + a_up * a_up) / a_diff;
-                               //print("middle\n");
-                       }
-               }
-               // OR attained at z = 1:
-               f = (a_up + a_add) * (a_up + a_add);
-               if(f > best)
-               {
-                       best = f;
-                       //print("top\n");
-               }
-               // OR attained at z = -1:
-               f = (a_up - a_add) * (a_up - a_add);
-               if(f > best)
-               {
-                       best = f;
-                       //print("bottom\n");
-               }
-               best = sqrt(best);
-               //////////////////////////////////////////////////////////////////////////////////////
-
-               //print("best possible acceleration: ", ftos(best), "\n");
-
-               float fxy, fz;
-               fxy = bound(0, 1 - (self.velocity * normalize(wishvel.x * '1 0 0' + wishvel.y * '0 1 0')) / autocvar_g_jetpack_maxspeed_side, 1);
-               if(wishvel.z - autocvar_sv_gravity > 0)
-                       fz = bound(0, 1 - self.velocity.z / autocvar_g_jetpack_maxspeed_up, 1);
-               else
-                       fz = bound(0, 1 + self.velocity.z / autocvar_g_jetpack_maxspeed_up, 1);
-
-               wishvel.x *= fxy;
-               wishvel.y *= fxy;
-               wishvel.z = (wishvel.z - autocvar_sv_gravity) * fz + autocvar_sv_gravity;
-
-               float fvel;
-               fvel = min(1, vlen(wishvel) / best);
-               if(autocvar_g_jetpack_fuel && !(self.items & IT_UNLIMITED_WEAPON_AMMO))
-                       f = min(1, self.ammo_fuel / (autocvar_g_jetpack_fuel * frametime * fvel));
-               else
-                       f = 1;
-
-               //print("this acceleration: ", ftos(vlen(wishvel) * f), "\n");
-
-               if (f > 0 && wishvel != '0 0 0')
-               {
-                       self.velocity = self.velocity + wishvel * f * frametime;
-                       if (!(self.items & IT_UNLIMITED_WEAPON_AMMO))
-                               self.ammo_fuel -= autocvar_g_jetpack_fuel * frametime * fvel * f;
-                       self.flags &= ~FL_ONGROUND;
-                       self.items |= IT_USING_JETPACK;
-
-                       // jetpack also inhibits health regeneration, but only for 1 second
-                       self.pauseregen_finished = max(self.pauseregen_finished, time + autocvar_g_balance_pause_fuel_regen);
-               }
-       }
-       else if (self.flags & FL_ONGROUND)
-       {
-               // we get here if we ran out of ammo
-               if((self.items & IT_JETPACK) && self.BUTTON_HOOK && !(buttons_prev & 32) && self.ammo_fuel < 0.01)
-                       Send_Notification(NOTIF_ONE, self, MSG_INFO, INFO_JETPACK_NOFUEL);
-
-               // walking
-               makevectors(self.v_angle.y * '0 1 0');
-               wishvel = v_forward * self.movement.x + v_right * self.movement.y;
-
-               if(!(self.lastflags & FL_ONGROUND))
-               {
-                       if(autocvar_speedmeter)
-                               dprint(strcat("landing velocity: ", vtos(self.velocity), " (abs: ", ftos(vlen(self.velocity)), ")\n"));
-                       if(self.lastground < time - 0.3)
-                               self.velocity = self.velocity * (1 - autocvar_sv_friction_on_land);
-                       if(self.jumppadcount > 1)
-                               dprint(strcat(ftos(self.jumppadcount), "x jumppad combo\n"));
-                       self.jumppadcount = 0;
-               }
-
-               v = self.velocity;
-               v.z = 0;
-               f = vlen(v);
-               if(f > 0)
-               {
-                       if (f < autocvar_sv_stopspeed)
-                               f = 1 - frametime * (autocvar_sv_stopspeed / f) * autocvar_sv_friction;
-                       else
-                               f = 1 - frametime * autocvar_sv_friction;
-                       if (f > 0)
-                               self.velocity = self.velocity * f;
-                       else
-                               self.velocity = '0 0 0';
-                       /*
-                          Mathematical analysis time!
-
-                          Our goal is to invert this mess.
-
-                          For the two cases we get:
-                               v = v0 * (1 - frametime * (autocvar_sv_stopspeed / v0) * autocvar_sv_friction)
-                                 = v0 - frametime * autocvar_sv_stopspeed * autocvar_sv_friction
-                               v0 = v + frametime * autocvar_sv_stopspeed * autocvar_sv_friction
-                          and
-                               v = v0 * (1 - frametime * autocvar_sv_friction)
-                               v0 = v / (1 - frametime * autocvar_sv_friction)
-
-                          These cases would be chosen ONLY if:
-                               v0 < autocvar_sv_stopspeed
-                               v + frametime * autocvar_sv_stopspeed * autocvar_sv_friction < autocvar_sv_stopspeed
-                               v < autocvar_sv_stopspeed * (1 - frametime * autocvar_sv_friction)
-                          and, respectively:
-                               v0 >= autocvar_sv_stopspeed
-                               v / (1 - frametime * autocvar_sv_friction) >= autocvar_sv_stopspeed
-                               v >= autocvar_sv_stopspeed * (1 - frametime * autocvar_sv_friction)
-                        */
-               }
-
-               // acceleration
-               wishdir = normalize(wishvel);
-               wishspeed = vlen(wishvel);
-               if (wishspeed > self.stat_sv_maxspeed*maxspd_mod)
-                       wishspeed = self.stat_sv_maxspeed*maxspd_mod;
-               if (self.crouch)
-                       wishspeed = wishspeed * 0.5;
-               if (time >= self.teleport_time)
-                       PM_Accelerate(wishdir, wishspeed, wishspeed, autocvar_sv_accelerate*maxspd_mod, 1, 0, 0, 0);
-       }
-       else
-       {
-               float wishspeed0;
-               // we get here if we ran out of ammo
-               if((self.items & IT_JETPACK) && self.BUTTON_HOOK && !(buttons_prev & 32) && self.ammo_fuel < 0.01)
-                       Send_Notification(NOTIF_ONE, self, MSG_INFO, INFO_JETPACK_NOFUEL);
-
-               if(maxspd_mod < 1)
-               {
-                       maxairspd = autocvar_sv_maxairspeed*maxspd_mod;
-                       airaccel = autocvar_sv_airaccelerate*maxspd_mod;
-               }
-               else
-               {
-                       maxairspd = autocvar_sv_maxairspeed;
-                       airaccel = autocvar_sv_airaccelerate;
-               }
-               // airborn
-               makevectors(self.v_angle.y * '0 1 0');
-               wishvel = v_forward * self.movement.x + v_right * self.movement.y;
-               // acceleration
-               wishdir = normalize(wishvel);
-               wishspeed = wishspeed0 = vlen(wishvel);
-               if (wishspeed0 > self.stat_sv_maxspeed*maxspd_mod)
-                       wishspeed0 = self.stat_sv_maxspeed*maxspd_mod;
-               if (wishspeed > maxairspd)
-                       wishspeed = maxairspd;
-               if (self.crouch)
-                       wishspeed = wishspeed * 0.5;
-               if (time >= self.teleport_time)
-               {
-                       float accelerating;
-                       float wishspeed2;
-                       float airaccelqw;
-                       float strafity;
-
-                       airaccelqw = self.stat_sv_airaccel_qw;
-                       accelerating = (self.velocity * wishdir > 0);
-                       wishspeed2 = wishspeed;
-
-                       // CPM
-                       if(autocvar_sv_airstopaccelerate)
-                       {
-                               vector curdir;
-                               curdir = self.velocity;
-                               curdir.z = 0;
-                               curdir = normalize(curdir);
-                               airaccel = airaccel + (autocvar_sv_airstopaccelerate*maxspd_mod - airaccel) * max(0, -(curdir * wishdir));
-                       }
-                       // note that for straight forward jumping:
-                       // step = accel * frametime * wishspeed0;
-                       // accel  = bound(0, wishspeed - vel_xy_current, step) * accelqw + step * (1 - accelqw);
-                       // -->
-                       // dv/dt = accel * maxspeed (when slow)
-                       // dv/dt = accel * maxspeed * (1 - accelqw) (when fast)
-                       // log dv/dt = logaccel + logmaxspeed (when slow)
-                       // log dv/dt = logaccel + logmaxspeed + log(1 - accelqw) (when fast)
-                       strafity = IsMoveInDirection(self.movement, -90) + IsMoveInDirection(self.movement, +90); // if one is nonzero, other is always zero
-                       if(autocvar_sv_maxairstrafespeed)
-                               wishspeed = min(wishspeed, GeomLerp(autocvar_sv_maxairspeed*maxspd_mod, strafity, autocvar_sv_maxairstrafespeed*maxspd_mod));
-                       if(autocvar_sv_airstrafeaccelerate)
-                               airaccel = GeomLerp(airaccel, strafity, autocvar_sv_airstrafeaccelerate*maxspd_mod);
-                       if(self.stat_sv_airstrafeaccel_qw)
-                               airaccelqw = copysign(1-GeomLerp(1-fabs(self.stat_sv_airaccel_qw), strafity, 1-fabs(self.stat_sv_airstrafeaccel_qw)), ((strafity > 0.5) ? self.stat_sv_airstrafeaccel_qw : self.stat_sv_airaccel_qw));
-                       // !CPM
-
-                       if(autocvar_sv_warsowbunny_turnaccel && accelerating && self.movement_y == 0 && self.movement.x != 0)
-                               PM_AirAccelerate(wishdir, wishspeed);
-                       else
-                               PM_Accelerate(wishdir, wishspeed, wishspeed0, airaccel, airaccelqw, autocvar_sv_airaccel_qw_stretchfactor, autocvar_sv_airaccel_sideways_friction / maxairspd, self.stat_sv_airspeedlimit_nonqw);
-
-                       if(autocvar_sv_aircontrol)
-                               CPM_PM_Aircontrol(wishdir, wishspeed2);
-               }
-       }
-
-       if((g_cts || g_race) && !IS_OBSERVER(self))
-       {
-               if(vlen(self.velocity - self.velocity.z * '0 0 1') > speedaward_speed)
-               {
-                       speedaward_speed = vlen(self.velocity - self.velocity.z * '0 0 1');
-                       speedaward_holder = self.netname;
-                       speedaward_uid = self.crypto_idfp;
-                       speedaward_lastupdate = time;
-               }
-               if(speedaward_speed > speedaward_lastsent && time - speedaward_lastupdate > 1)
-               {
-                       string rr = (g_cts) ? CTS_RECORD : RACE_RECORD;
-                       race_send_speedaward(MSG_ALL);
-                       speedaward_lastsent = speedaward_speed;
-                       if (speedaward_speed > speedaward_alltimebest && speedaward_uid != "")
-                       {
-                               speedaward_alltimebest = speedaward_speed;
-                               speedaward_alltimebest_holder = speedaward_holder;
-                               speedaward_alltimebest_uid = speedaward_uid;
-                               db_put(ServerProgsDB, strcat(GetMapname(), rr, "speed/speed"), ftos(speedaward_alltimebest));
-                               db_put(ServerProgsDB, strcat(GetMapname(), rr, "speed/crypto_idfp"), speedaward_alltimebest_uid);
-                               race_send_speedaward_alltimebest(MSG_ALL);
-                       }
-               }
-       }
-
-       // WEAPONTODO
-       float xyspeed;
-       xyspeed = vlen('1 0 0' * self.velocity.x + '0 1 0' * self.velocity.y);
-       if(self.weapon == WEP_VORTEX && WEP_CVAR(vortex, charge) && WEP_CVAR(vortex, charge_velocity_rate) && xyspeed > WEP_CVAR(vortex, charge_minspeed))
-       {
-               // add a maximum of charge_velocity_rate when going fast (f = 1), gradually increasing from minspeed (f = 0) to maxspeed
-               xyspeed = min(xyspeed, WEP_CVAR(vortex, charge_maxspeed));
-               f = (xyspeed - WEP_CVAR(vortex, charge_minspeed)) / (WEP_CVAR(vortex, charge_maxspeed) - WEP_CVAR(vortex, charge_minspeed));
-               // add the extra charge
-               self.vortex_charge = min(1, self.vortex_charge + WEP_CVAR(vortex, charge_velocity_rate) * f * frametime);
-       }
-:end
-       if(self.flags & FL_ONGROUND)
-               self.lastground = time;
-
-       // conveyors: then break velocity again
-       if(self.conveyor.state)
-               self.velocity += self.conveyor.movedir;
-
-       self.lastflags = self.flags;
-       self.lastclassname = self.classname;
-}
index 49d1c1b4691c3136f11c4fd3aa87c27a816c9ea9..aae39ea66eccbc9e9190e1797fedcabee3e366de 100644 (file)
@@ -1,10 +1,28 @@
 #include "cl_player.qh"
-#include "g_triggers.qh"
+#include "_all.qh"
+
+#include "bot/bot.qh"
+#include "cheats.qh"
+#include "g_damage.qh"
+#include "g_subs.qh"
 #include "g_violence.qh"
 #include "miscfunctions.qh"
+#include "portals.qh"
+#include "teamplay.qh"
+#include "waypointsprites.qh"
+#include "weapons/throwing.qh"
+#include "command/common.qh"
+#include "../common/animdecide.qh"
+#include "../common/csqcmodel_settings.qh"
+#include "../common/deathtypes.qh"
+#include "../common/triggers/subs.qh"
+#include "../common/playerstats.qh"
+#include "../csqcmodellib/sv_model.qh"
 
 #include "weapons/weaponstats.qh"
 
+#include "../common/animdecide.qh"
+
 void CopyBody_Think(void)
 {
        if(self.CopyBody_nextthink && time > self.CopyBody_nextthink)
@@ -147,7 +165,7 @@ void player_anim (void)
        }
 }
 
-void PlayerCorpseDamage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
+void PlayerCorpseDamage (entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
 {
        float take, save;
        vector v;
@@ -767,9 +785,9 @@ float Say(entity source, float teamsay, entity privatesay, string msgin, float f
                                flood = 2;
                        }
 
-                       if(time >= source.flood_field)
+                       if (time >= source.(flood_field))
                        {
-                               source.flood_field = max(time - flood_burst * flood_spl, source.flood_field) + lines * flood_spl;
+                               source.(flood_field) = max(time - flood_burst * flood_spl, source.(flood_field)) + lines * flood_spl;
                        }
                        else
                        {
@@ -779,14 +797,14 @@ float Say(entity source, float teamsay, entity privatesay, string msgin, float f
                }
                else
                {
-                       if(time >= source.flood_field)
-                               source.flood_field = max(time - flood_burst * flood_spl, source.flood_field) + flood_spl;
+                       if (time >= source.(flood_field))
+                               source.(flood_field) = max(time - flood_burst * flood_spl, source.(flood_field)) + flood_spl;
                        else
                                flood = 1;
                }
 
                if (timeout_status == TIMEOUT_ACTIVE) // when game is paused, no flood protection
-                       source.flood_field = flood = 0;
+                       source.(flood_field) = flood = 0;
        }
 
        if(flood == 2) // cannot happen for empty msgstr
@@ -831,9 +849,9 @@ float Say(entity source, float teamsay, entity privatesay, string msgin, float f
        }
        else if(flood == 1)
        {
-               if(autocvar_g_chat_flood_notify_flooder)
+               if (autocvar_g_chat_flood_notify_flooder)
                {
-                       sprint(source, strcat("^3FLOOD CONTROL: ^7wait ^1", ftos(source.flood_field - time), "^3 seconds\n"));
+                       sprint(source, strcat("^3FLOOD CONTROL: ^7wait ^1", ftos(source.(flood_field) - time), "^3 seconds\n"));
                        ret = 0;
                }
                else
@@ -1003,9 +1021,9 @@ float LoadPlayerSounds(string f, float first)
                        field = GetVoiceMessageSampleField(argv(0));
                if(GetPlayerSoundSampleField_notFound)
                        continue;
-               if(self.field)
-                       strunzone(self.field);
-               self.field = strzone(strcat(argv(1), " ", argv(2)));
+               if (self.(field))
+                       strunzone(self.(field));
+               self.(field) = strzone(strcat(argv(1), " ", argv(2)));
        }
        fclose(fh);
        return 1;
@@ -1200,7 +1218,7 @@ void GlobalSound(string sample, float chan, float voicetype)
 
 void PlayerSound(.string samplefield, float chan, float voicetype)
 {
-       GlobalSound(self.samplefield, chan, voicetype);
+       GlobalSound(self.(samplefield), chan, voicetype);
 }
 
 void VoiceMessage(string type, string msg)
@@ -1221,10 +1239,10 @@ void VoiceMessage(string type, string msg)
 
        flood = Say(self, ownteam, world, msg, 1);
 
-       if(IS_SPEC(self) || IS_OBSERVER(self) || flood < 0)
-               FakeGlobalSound(self.sample, CH_VOICE, voicetype);
+       if (IS_SPEC(self) || IS_OBSERVER(self) || flood < 0)
+               FakeGlobalSound(self.(sample), CH_VOICE, voicetype);
        else if (flood > 0)
-               GlobalSound(self.sample, CH_VOICE, voicetype);
+               GlobalSound(self.(sample), CH_VOICE, voicetype);
 }
 
 void MoveToTeam(entity client, float team_colour, float type)
index cf5ec0a7d1df502a7297636ed9d51ddcd061c079..cd1ec2e15be6dc19b9ac2fe52507203c4d85bb49 100644 (file)
@@ -16,7 +16,7 @@ void player_setupanimsformodel();
 
 void player_anim (void);
 
-void PlayerCorpseDamage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force);
+void PlayerCorpseDamage (entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force);
 
 // g_<gametype>_str:
 // If 0, default is used.
diff --git a/qcsrc/server/command/all.qc b/qcsrc/server/command/all.qc
new file mode 100644 (file)
index 0000000..ac37b6b
--- /dev/null
@@ -0,0 +1,10 @@
+#include "../../common/command/all.qc"
+
+#include "sv_cmd.qc"
+
+#include "banning.qc"
+#include "cmd.qc"
+#include "common.qc"
+#include "getreplies.qc"
+#include "radarmap.qc"
+#include "vote.qc"
diff --git a/qcsrc/server/command/all.qh b/qcsrc/server/command/all.qh
new file mode 100644 (file)
index 0000000..af87c24
--- /dev/null
@@ -0,0 +1,15 @@
+#ifndef SERVER_COMMANDS_ALL_H
+#define SERVER_COMMANDS_ALL_H
+
+#include "../../common/command/commands.qh"
+
+#include "sv_cmd.qh"
+
+#include "banning.qh"
+#include "cmd.qh"
+#include "common.qh"
+#include "getreplies.qh"
+#include "radarmap.qh"
+#include "vote.qh"
+
+#endif
index 9091ae0b783b65953aa4abef156b4e3203ce8040..e3d3c67591f9888de119f0a3bc1f344156ae689f 100644 (file)
@@ -1,14 +1,14 @@
-#if defined(CSQC)
-#elif defined(MENUQC)
-#elif defined(SVQC)
-       #include "../../dpdefs/dpextensions.qh"
-    #include "../../common/util.qh"
-    #include "../../common/command/shared_defs.qh"
-    #include "../autocvars.qh"
-    #include "common.qh"
-    #include "banning.qh"
-    #include "../ipban.qh"
-#endif
+#include "../../common/command/command.qh"
+#include "banning.qh"
+#include "../_all.qh"
+
+#include "common.qh"
+
+#include "../cl_player.qh"
+#include "../ipban.qh"
+
+#include "../../common/util.qh"
+
 // =====================================================
 //  Banning and kicking command code, written by Samual
 //  Last updated: December 29th, 2011
index 70daacc87ea98d6152b183dc6ea97b6fc0b30ef2..17eca95c738363e4c83c3fbe57d0762fd143111c 100644 (file)
@@ -16,4 +16,8 @@ float Ban_Delete(float i);
 
 // used by common/command/generic.qc:GenericCommand_dumpcommands to list all commands into a .txt file
 void BanCommand_macro_write_aliases(float fh);
+
+void BanCommand_macro_help();
+float BanCommand_macro_usage(float argc);
+
 #endif
index 14e0f201c0f7bb029d4f4363a8ba50e7b7ea39c3..828c86302354c5a53c11ae4e0116f2e04a46ef6c 100644 (file)
@@ -1,32 +1,39 @@
-#if defined(CSQC)
-#elif defined(MENUQC)
-#elif defined(SVQC)
-       #include "../../dpdefs/progsdefs.qh"
-    #include "../../dpdefs/dpextensions.qh"
-    #include "../../warpzonelib/common.qh"
-    #include "../../common/constants.qh"
-    #include "../../common/teams.qh"
-    #include "../../common/util.qh"
-    #include "../../common/command/shared_defs.qh"
-    #include "../../common/monsters/monsters.qh"
-    #include "../../common/monsters/sv_monsters.qh"
-    #include "../../common/monsters/spawn.qh"
-    #include "../autocvars.qh"
-    #include "../defs.qh"
-    #include "../../common/notifications.qh"
-    #include "../../common/deathtypes.qh"
-    #include "../mutators/mutators_include.qh"
-    #include "../vehicles/vehicles_def.qh"
-    #include "../campaign.qh"
-    #include "../../common/mapinfo.qh"
-    #include "common.qh"
-    #include "vote.qh"
-    #include "cmd.qh"
-    #include "../cheats.qh"
-    #include "../scores.qh"
-    #include "../ipban.qh"
+#include "../../common/command/command.qh"
+#include "cmd.qh"
+#include "../_all.qh"
+
+#include "common.qh"
+#include "vote.qh"
+
+#include "../campaign.qh"
+#include "../cheats.qh"
+#include "../cl_player.qh"
+#include "../ipban.qh"
+#include "../mapvoting.qh"
+#include "../scores.qh"
+#include "../teamplay.qh"
+
+#include "../mutators/mutators_include.qh"
+
+#ifdef SVQC
+       #include "../vehicles/vehicle.qh"
 #endif
 
+#include "../../common/constants.qh"
+#include "../../common/deathtypes.qh"
+#include "../../common/mapinfo.qh"
+#include "../../common/notifications.qh"
+#include "../../common/teams.qh"
+#include "../../common/util.qh"
+
+#include "../../common/monsters/all.qh"
+#include "../../common/monsters/spawn.qh"
+#include "../../common/monsters/sv_monsters.qh"
+
+#include "../../warpzonelib/common.qh"
+
+void ClientKill_TeamChange (float targetteam); // 0 = don't change, -1 = auto, -2 = spec
+
 // =========================================================
 //  Server side networked commands code, reworked by Samual
 //  Last updated: December 28th, 2011
@@ -370,6 +377,46 @@ void ClientCommand_mobspawn(float request, float argc)
        }
 }
 
+void ClientCommand_physics(float request, float argc)
+{
+       switch(request)
+       {
+               case CMD_REQUEST_COMMAND:
+               {
+                       string command = strtolower(argv(1));
+                       
+                       if(!autocvar_g_physics_clientselect)
+                       {
+                               sprint(self, "Client physics selection is currently disabled.\n");
+                               return;
+                       }
+
+                       if(command == "list" || command == "help")
+                       {
+                               sprint(self, strcat("Available physics sets: \n\n", autocvar_g_physics_clientselect_options, " default\n"));
+                               return;
+                       }
+                       
+                       if(Physics_Valid(command) || command == "default")
+                       {
+                               stuffcmd(self, strcat("\nseta cl_physics ", command, "\nsendcvar cl_physics\n"));
+                               sprint(self, strcat("^2Physics set successfully changed to ^3", command, "\n"));
+                               return;
+                       }
+               }
+       
+               default:
+                       sprint(self, strcat("Current physics set: ^3", self.cvar_cl_physics, "\n"));
+               case CMD_REQUEST_USAGE:
+               {
+                       sprint(self, "\nUsage:^3 cmd physics <physics>\n");
+                       sprint(self, "  See 'cmd physics list' for available physics sets.\n");
+                       sprint(self, "  Argument 'default' resets to standard physics.\n");
+                       return;
+               }
+       }
+}
+
 void ClientCommand_ready(float request) // todo: anti-spam for toggling readyness
 {
        switch(request)
@@ -762,6 +809,7 @@ void ClientCommand_(float request)
        CLIENT_COMMAND("mobedit", ClientCommand_mobedit(request, arguments), "Edit your monster's properties") \
        CLIENT_COMMAND("mobkill", ClientCommand_mobkill(request), "Kills your monster") \
        CLIENT_COMMAND("mobspawn", ClientCommand_mobspawn(request, arguments), "Spawn monsters infront of yourself") \
+       CLIENT_COMMAND("physics", ClientCommand_physics(request, arguments), "Change physics set") \
        CLIENT_COMMAND("ready", ClientCommand_ready(request), "Qualify as ready to end warmup stage (or restart server if allowed)") \
        CLIENT_COMMAND("say", ClientCommand_say(request, arguments, command), "Print a message to chat to all players") \
        CLIENT_COMMAND("say_team", ClientCommand_say_team(request, arguments, command), "Print a message to chat to all team mates") \
index 5b7e761b7879077a18d841119ca0e0e2e4092c93..0bdc6672fbf550daa7d2d66b54bdb30cf69b99d3 100644 (file)
@@ -1,5 +1,10 @@
+#include "../../common/command/command.qh"
 #include "common.qh"
+#include "../_all.qh"
 
+#include "../scores.qh"
+
+#include "../../common/notifications.qh"
 #include "../../common/counting.qh"
 
 
index ac99e32dc46d2583a677e3d687d6a067dde510ee..0925d7137855c000e51017f720f057e2ded902c3 100644 (file)
@@ -4,7 +4,7 @@
 #include "vote.qh"
 
 #include "../../common/command/generic.qh"
-#include "../../common/command/shared_defs.qh"
+#include "../../common/command/command.qh"
 
 // ============================================================
 //  Shared declarations for server commands, written by Samual
index aa8efd6d69a15934416371d6066b76c419bfc212..543f1db1525a374a501a7e66e7cc50ed4461089c 100644 (file)
@@ -1,17 +1,15 @@
-#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/counting.qh"
-    #include "../../common/monsters/monsters.qh"
-    #include "../defs.qh"
-    #include "../../common/mapinfo.qh"
-    #include "getreplies.qh"
-    #include "../race.qh"
-#endif
+#include "../../common/command/command.qh"
+#include "getreplies.qh"
+#include "../_all.qh"
+
+#include "../race.qh"
+
+#include "../../common/constants.qh"
+#include "../../common/counting.qh"
+#include "../../common/mapinfo.qh"
+#include "../../common/util.qh"
+
+#include "../../common/monsters/all.qh"
 
 // =========================================================
 //  Reply messages for common commands, re-worked by Samual
index 73e5108795525bd072c60cc5bd86bcd58cc25da5..53cab574729d7f524639222433f4fb6c1f4c3529 100644 (file)
@@ -1,13 +1,12 @@
-#if defined(CSQC)
-#elif defined(MENUQC)
-#elif defined(SVQC)
-       #include "../../dpdefs/progsdefs.qh"
-    #include "../../dpdefs/dpextensions.qh"
-    #include "../../common/util.qh"
-    #include "../defs.qh"
-    #include "radarmap.qh"
-    #include "../../csqcmodellib/sv_model.qh"
-#endif
+#include "../../common/command/command.qh"
+#include "radarmap.qh"
+#include "../_all.qh"
+
+#include "../g_world.qh"
+
+#include "../../common/util.qh"
+
+#include "../../csqcmodellib/sv_model.qh"
 
 // ===============================================
 //     Generates radar map images for use in the HUD
@@ -167,7 +166,7 @@ void sharpen_set(int x, float v)
 {
        sharpen_buffer[x + 2 * RADAR_WIDTH_MAX] = v;
 }
-float sharpen_getpixel(float x, float y)
+float sharpen_getpixel(int x, int y)
 {
        if(x < 0)
                return 0;
index c2b068c7d1a9f2a01e86f8dcf9b5531ab2fc702d..fea60ba9e1143238181d3f5a131ea7034edcb3f7 100644 (file)
@@ -14,4 +14,8 @@ float sharpen_buffer[RADAR_WIDTH_MAX * 3];
 string doublehex = "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFFFF";
 // FF is contained twice, to map 256 to FF too
 // removes the need to bound()
+
+float RadarMap_Make(float argc);
+
+
 #endif
index 7166ab7cfd1156b9377724ac6f2586e591f24872..0bf2df320b9475adfddeb9e7ba8c2782b87a5053 100644 (file)
@@ -1,25 +1,39 @@
-#if defined(CSQC)
-#elif defined(MENUQC)
-#elif defined(SVQC)
-       #include "../../dpdefs/progsdefs.qh"
-    #include "../../dpdefs/dpextensions.qh"
-    #include "../../warpzonelib/mathlib.qh"
-    #include "../../common/constants.qh"
-    #include "../../common/teams.qh"
-    #include "../../common/util.qh"
-    #include "../../common/command/shared_defs.qh"
-    #include "../../common/monsters/sv_monsters.qh"
-    #include "../autocvars.qh"
-    #include "../defs.qh"
-    #include "../../common/notifications.qh"
-    #include "../mutators/mutators_include.qh"
-    #include "../../common/mapinfo.qh"
-    #include "common.qh"
-    #include "cmd.qh"
-    #include "sv_cmd.qh"
-    #include "../anticheat.qh"
-    #include "../playerdemo.qh"
-#endif
+#include "../../common/command/command.qh"
+#include "sv_cmd.qh"
+#include "../_all.qh"
+
+#include "banning.qh"
+#include "cmd.qh"
+#include "common.qh"
+#include "getreplies.qh"
+#include "radarmap.qh"
+
+#include "../anticheat.qh"
+#include "../campaign.qh"
+#include "../cl_client.qh"
+#include "../cl_player.qh"
+#include "../g_world.qh"
+#include "../ipban.qh"
+#include "../playerdemo.qh"
+#include "../teamplay.qh"
+
+#include "../bot/bot.qh"
+#include "../bot/navigation.qh"
+#include "../bot/scripting.qh"
+
+#include "../mutators/mutators_include.qh"
+
+#include "../../common/constants.qh"
+#include "../../common/mapinfo.qh"
+#include "../../common/notifications.qh"
+#include "../../common/teams.qh"
+#include "../../common/util.qh"
+
+#include "../../common/monsters/sv_monsters.qh"
+
+#include "../../warpzonelib/mathlib.qh"
+
+void PutObserverInServer (void);
 
 // =====================================================
 //  Server side game commands code, reworked by Samual
@@ -46,7 +60,7 @@ void make_mapinfo_Think()
 void changematchtime(float delta, float mi, float ma)
 {
        float cur;
-       float new;
+       float update;
        float lim;
 
        if(delta == 0)
@@ -67,21 +81,21 @@ void changematchtime(float delta, float mi, float ma)
                if(lim == 0)
                        return; // cannot increase any further
                else if(lim < ma)
-                       new = min(ma, lim + delta);
+                       update = min(ma, lim + delta);
                else // already above maximum: FAIL
                        return;
        }
        else
        {
                if(lim == 0) // infinite: try reducing to max, if we are allowed to
-                       new = max(mi, ma);
+                       update = max(mi, ma);
                else if(lim > mi) // above minimum: decrease
-                       new = max(mi, lim + delta);
+                       update = max(mi, lim + delta);
                else // already below minimum: FAIL
                        return;
        }
 
-       cvar_set("timelimit", ftos(new / 60));
+       cvar_set("timelimit", ftos(update / 60));
 }
 
 
@@ -1380,12 +1394,13 @@ void GameCommand_shuffleteams(float request)
                        {
                                entity tmp_player;
                                int i;
-                               float x, z, t_teams, t_players, team_color;
+                               float x, t_teams, t_players, team_color;
 
                                // count the total amount of players and total amount of teams
                                t_players = 0;
                                t_teams = 0;
-                               FOR_EACH_PLAYER(tmp_player)
+                               FOR_EACH_CLIENT(tmp_player)
+                               if(IS_PLAYER(tmp_player) || tmp_player.caplayer)
                                {
                                        CheckAllowedTeams(tmp_player);
 
@@ -1398,7 +1413,8 @@ void GameCommand_shuffleteams(float request)
                                }
 
                                // build a list of the players in a random order
-                               FOR_EACH_PLAYER(tmp_player)
+                               FOR_EACH_CLIENT(tmp_player)
+                               if(IS_PLAYER(tmp_player) || tmp_player.caplayer)
                                {
                                        for (;;)
                                        {
@@ -1417,7 +1433,7 @@ void GameCommand_shuffleteams(float request)
                                }
 
                                // finally, from the list made earlier, re-join the players in different order.
-                               for(i = 1; i <= t_teams; ++i)
+                               for (int i = 1; i <= t_teams; ++i)
                                {
                                        // find out how many players to assign to this team
                                        x = (t_players / t_teams);
@@ -1426,7 +1442,7 @@ void GameCommand_shuffleteams(float request)
                                        team_color = Team_NumberToTeam(i);
 
                                        // sort through the random list of players made earlier
-                                       for(z = 1; z <= maxclients; ++z)
+                                       for (int z = 1; z <= maxclients; ++z)
                                        {
                                                if (!(shuffleteams_teams[i] >= x))
                                                {
index 61fd2f3a2d44d423b8a2a1792aec5f635a7ae420..4be48e124e82b98d38fb26c41c5df7dfe18efc29 100644 (file)
@@ -1,24 +1,22 @@
-#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/command/shared_defs.qh"
-    #include "../autocvars.qh"
-    #include "../constants.qh"
-    #include "../defs.qh"
-    #include "../../common/notifications.qh"
-    #include "../mutators/mutators_include.qh"
-    #include "../../common/mapinfo.qh"
-    #include "common.qh"
-    #include "vote.qh"
-    #include "../../common/playerstats.qh"
-    #include "../scores.qh"
-    #include "../race.qh"
-    #include "../round_handler.qh"
-#endif
+#include "../../common/command/command.qh"
+#include "vote.qh"
+#include "../_all.qh"
+
+#include "common.qh"
+
+#include "../g_damage.qh"
+#include "../g_world.qh"
+#include "../race.qh"
+#include "../round_handler.qh"
+#include "../scores.qh"
+
+#include "../mutators/mutators_include.qh"
+
+#include "../../common/constants.qh"
+#include "../../common/mapinfo.qh"
+#include "../../common/notifications.qh"
+#include "../../common/playerstats.qh"
+#include "../../common/util.qh"
 
 // =============================================
 //  Server side voting code, reworked by Samual
@@ -117,6 +115,13 @@ void Nagger_ReadyCounted()
                nagger.SendFlags |= 1;
 }
 
+// If the vote_caller is still here, return their name, otherwise vote_caller_name
+string OriginalCallerName()
+{
+       if (IS_REAL_CLIENT(vote_caller))
+               return vote_caller.netname;
+       return vote_caller_name;
+}
 
 // =======================
 //  Game logic for voting
@@ -132,10 +137,12 @@ void VoteReset()
        {
                strunzone(vote_called_command);
                strunzone(vote_called_display);
+               strunzone(vote_caller_name);
        }
 
        vote_called = VOTE_NULL;
        vote_caller = world;
+       vote_caller_name = string_null;
        vote_endtime = 0;
 
        vote_called_command = string_null;
@@ -149,7 +156,7 @@ void VoteReset()
 
 void VoteStop(entity stopper)
 {
-       bprint("\{1}^2* ^3", GetCallerName(stopper), "^2 stopped ^3", GetCallerName(vote_caller), "^2's vote\n");
+       bprint("\{1}^2* ^3", GetCallerName(stopper), "^2 stopped ^3", OriginalCallerName(), "^2's vote\n");
        if(autocvar_sv_eventlog) { GameLogEcho(strcat(":vote:vstop:", ftos(stopper.playerid))); }
 
        // Don't force them to wait for next vote, this way they can e.g. correct their vote.
@@ -160,7 +167,7 @@ void VoteStop(entity stopper)
 
 void VoteAccept()
 {
-       bprint("\{1}^2* ^3", GetCallerName(vote_caller), "^2's vote for ^1", vote_called_display, "^2 was accepted\n");
+       bprint("\{1}^2* ^3", OriginalCallerName(), "^2's vote for ^1", vote_called_display, "^2 was accepted\n");
 
        if((vote_called == VOTE_MASTER) && vote_caller)
                vote_caller.vote_master = 1;
@@ -175,14 +182,14 @@ void VoteAccept()
 
 void VoteReject()
 {
-       bprint("\{1}^2* ^3", GetCallerName(vote_caller), "^2's vote for ", vote_called_display, "^2 was rejected\n");
+       bprint("\{1}^2* ^3", OriginalCallerName(), "^2's vote for ", vote_called_display, "^2 was rejected\n");
        VoteReset();
        Send_Notification(NOTIF_ALL, world, MSG_ANNCE, ANNCE_VOTE_FAIL);
 }
 
 void VoteTimeout()
 {
-       bprint("\{1}^2* ^3", GetCallerName(vote_caller), "^2's vote for ", vote_called_display, "^2 timed out\n");
+       bprint("\{1}^2* ^3", OriginalCallerName(), "^2's vote for ", vote_called_display, "^2 timed out\n");
        VoteReset();
        Send_Notification(NOTIF_ALL, world, MSG_ANNCE, ANNCE_VOTE_FAIL);
 }
@@ -823,6 +830,7 @@ void VoteCommand_call(float request, entity caller, float argc, string vote_comm
                        else // everything went okay, continue with calling the vote
                        {
                                vote_caller = caller; // remember who called the vote
+                               vote_caller_name = strzone(GetCallerName(vote_caller));
                                vote_called = VOTE_NORMAL;
                                vote_called_command = strzone(vote_parsed_command);
                                vote_called_display = strzone(vote_parsed_display);
@@ -838,7 +846,7 @@ void VoteCommand_call(float request, entity caller, float argc, string vote_comm
                                FOR_EACH_REALCLIENT(tmp_player) { ++tmp_playercount; }
                                if(tmp_playercount > 1) { Send_Notification(NOTIF_ALL, world, MSG_ANNCE, ANNCE_VOTE_CALL); } // don't announce a "vote now" sound if player is alone
 
-                               bprint("\{1}^2* ^3", GetCallerName(vote_caller), "^2 calls a vote for ", vote_called_display, "\n");
+                               bprint("\{1}^2* ^3", OriginalCallerName(), "^2 calls a vote for ", vote_called_display, "\n");
                                if(autocvar_sv_eventlog) { GameLogEcho(strcat(":vote:vcall:", ftos(vote_caller.playerid), ":", vote_called_display)); }
                                Nagger_VoteChanged();
                                VoteCount(true); // needed if you are the only one
@@ -919,6 +927,7 @@ void VoteCommand_master(float request, entity caller, float argc, string vote_co
                                                else // everything went okay, continue with creating vote
                                                {
                                                        vote_caller = caller;
+                                                       vote_caller_name = strzone(GetCallerName(vote_caller));
                                                        vote_called = VOTE_MASTER;
                                                        vote_called_command = strzone("XXX");
                                                        vote_called_display = strzone("^3master");
@@ -927,7 +936,7 @@ void VoteCommand_master(float request, entity caller, float argc, string vote_co
                                                        caller.vote_selection = VOTE_SELECT_ACCEPT;
                                                        caller.vote_waittime = time + autocvar_sv_vote_wait;
 
-                                                       bprint("\{1}^2* ^3", GetCallerName(vote_caller), "^2 calls a vote to become ^3master^2.\n");
+                                                       bprint("\{1}^2* ^3", OriginalCallerName(), "^2 calls a vote to become ^3master^2.\n");
                                                        if(autocvar_sv_eventlog) { GameLogEcho(strcat(":vote:vcall:", ftos(vote_caller.playerid), ":", vote_called_display)); }
                                                        Nagger_VoteChanged();
                                                        VoteCount(true); // needed if you are the only one
@@ -991,7 +1000,7 @@ void VoteCommand_status(float request, entity caller) // BOTH
                case CMD_REQUEST_COMMAND:
                {
                        if(vote_called)
-                               print_to(caller, strcat("^7Vote for ", vote_called_display, "^7 called by ^7", GetCallerName(vote_caller), "^7."));
+                               print_to(caller, strcat("^7Vote for ", vote_called_display, "^7 called by ^7", OriginalCallerName(), "^7."));
                        else
                                print_to(caller, "^1No vote called.");
 
index ff33f5668cf635f2f00acf8929d338df7e6d05c7..f80785e2a12f8c4935654a8e1853141fb4c5653a 100644 (file)
@@ -24,6 +24,7 @@ const float VOTE_MASTER = 2;
 
 // global vote information declarations
 entity vote_caller; // original caller of the current vote
+string vote_caller_name; // name of the vote caller
 float vote_called; // stores status of current vote (See VOTE_*)
 float vote_endtime; // time when the vote is finished
 float vote_accept_count; // total amount of players who accept the vote (counted by VoteCount() function)
@@ -52,4 +53,5 @@ float restart_mapalreadyrestarted; // bool, indicates whether reset_map() was al
 .float ready; // flag for if a player is ready
 void reset_map(float dorespawn);
 void ReadyCount();
+void ReadyRestart_force();
 #endif
index 1d4cc55232382a6fcd7f2491325b6364ec5a9736..c1def6b821e469d43d1183f371ff1039e0009d53 100644 (file)
@@ -23,5 +23,4 @@ const int NUM_PLAYERSKINS_TEAMPLAY = 3;
 
 const int ASSAULT_VALUE_INACTIVE = 1000;
 
-const int DOOR_NOSPLASH = 256; // generic anti-splashdamage spawnflag
 #endif
diff --git a/qcsrc/server/csqceffects.qh b/qcsrc/server/csqceffects.qh
new file mode 100644 (file)
index 0000000..9fd0c38
--- /dev/null
@@ -0,0 +1,4 @@
+#ifndef CSQCEFFECTS_H
+#define CSQCEFFECTS_H
+void te_csqc_lightningarc(vector from,vector to);
+#endif
index 822c5163c384c1476656d825ab0a009f549ac406..9637cc67c8496dd02032e99d3b5a864dfd9211e2 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef SERVER_DEFS_H
 #define SERVER_DEFS_H
 
-#include "../common/weapons/weapons.qh"
+#include "../common/weapons/all.qh"
 
 #define INDEPENDENT_ATTACK_FINISHED
 
@@ -46,8 +46,6 @@ float g_jetpack;
 float sv_clones;
 float sv_foginterval;
 
-entity activator;
-
 float player_count;
 float currentbots;
 float bots_would_leave;
@@ -64,27 +62,17 @@ float server_is_dedicated;
 
 // Fields
 
-.void(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force) event_damage;
+.void(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force) event_damage;
 
 //.string      wad;
 //.string      map;
 
 //.float       worldtype;
-.float delay;
-.float wait;
-.float lip;
-//.float       light_lev;
-.float speed;
-//.float       style;
-//.float       skill;
-.float sounds;
-.string  platmovetype;
-.float platmovetype_start, platmovetype_end;
-
-.string killtarget;
-
-.vector        pos1, pos2;
-.vector        mangle;
+// Needed for dynamic clientwalls
+.float inactive; // Clientwall disappears when inactive
+.float alpha_max, alpha_min;
+.float fade_start, fade_end, fade_vertical_offset;
+.float default_solid; // Variable to store default self.solid for clientwalls
 
 .float pain_finished;                  //Added by Supajoe
 .float pain_frame;                     //"
@@ -94,14 +82,7 @@ float server_is_dedicated;
 .float invincible_finished;
 .float superweapons_finished;
 
-.vector                finaldest, finalangle;          //plat.qc stuff
-.void()                think1;
-.float state;
-.float         t_length, t_width;
-
-.vector destvec;               // for rain
-.vector destvec2;              // for train
-.float cnt;            // for rain
+.float cnt; // used in too many places
 .float count;
 //.float cnt2;
 
@@ -113,15 +94,6 @@ float server_is_dedicated;
 .float fade_time;
 .float fade_rate;
 
-// player animation state
-.float animstate_startframe;
-.float animstate_numframes;
-.float animstate_framerate;
-.float animstate_starttime;
-.float animstate_endtime;
-.float animstate_override;
-.float animstate_looping;
-
 // weapon animation vectors:
 .vector anim_fire1;
 .vector anim_fire2;
@@ -210,26 +182,13 @@ const int W_TICSPERFRAME = 2;
 
 void weapon_defaultspawnfunc(float wpn);
 
-.vector dest1, dest2;
-
 float gameover;
 float intermission_running;
 float intermission_exittime;
 float alreadychangedlevel;
 
-// Keys player is holding
-.float itemkeys;
-// message delay for func_door locked by keys and key locks
-// this field is used on player entities
-.float key_door_messagetime;
-
-
 .float version;
 
-//swamp
-.float in_swamp;              // bool
-.entity swampslug;            // Uses this to release from swamp ("untouch" fix)
-
 // footstep interval
 .float nextstep;
 
@@ -250,7 +209,7 @@ float nJoinAllowed(entity ignore);
 
 .entity flagcarried;
 
-.float playerid;
+.int playerid;
 float playerid_last;
 .float noalign;                // if set to 1, the item or spawnpoint won't be dropped to the floor
 
@@ -284,10 +243,6 @@ float default_weapon_alpha;
 
 .float version_nagtime;
 
-const int NUM_JUMPPADSUSED = 3;
-.float jumppadcount;
-.entity jumppadsused[NUM_JUMPPADSUSED];
-
 string gamemode_name;
 
 float startitem_failed;
@@ -333,7 +288,7 @@ float have_team_spawns_forteam[17]; // 0 = this team has no spawns, 1 = this tea
 .entity killindicator;
 .float killindicator_teamchange;
 
-void Damage (entity targ, entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force);
+void Damage (entity targ, entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force);
 
 float lockteams;
 
@@ -347,7 +302,7 @@ float next_pingtime;
 
 .float Version;
 .int SendFlags;
-.float(entity to, float sendflags) SendEntity;
+.bool(entity to, int sendflags) SendEntity;
 
 // player sounds, voice messages
 // TODO implemented fall and falling
@@ -447,11 +402,6 @@ float round_starttime; //point in time when the countdown to round start is over
 .float stat_game_starttime;
 .float stat_round_starttime;
 
-.float stat_sv_airaccel_qw;
-.float stat_sv_airstrafeaccel_qw;
-.float stat_sv_airspeedlimit_nonqw;
-.float stat_sv_maxspeed;
-
 void W_Porto_Remove (entity p);
 
 .int projectiledeathtype;
@@ -464,16 +414,6 @@ void W_Porto_Remove (entity p);
 // may be useful to all weapons
 .float bulletcounter;
 
-void target_voicescript_next(entity pl);
-void target_voicescript_clear(entity pl);
-
-.string target2;
-.string target3;
-.string target4;
-.string curvetarget;
-.float target_random;
-.float trigger_reverse;
-
 // Nexball
 .entity ballcarried; // Also used for keepaway
 .float metertime;
@@ -519,7 +459,7 @@ string matchid;
 
 .float stat_leadlimit;
 
-float radar_showennemies;
+bool radar_showennemies;
 
 #ifdef PROFILING
 float client_cefc_accumulator;
@@ -527,7 +467,7 @@ float client_cefc_accumulatortime;
 #endif
 
 .float weapon_load[WEP_MAXCOUNT];
-.float ammo_none; // used by the reloading system, must always be 0
+.int ammo_none; // used by the reloading system, must always be 0
 .float clip_load;
 .float old_clip_load;
 .float clip_size;
@@ -539,7 +479,7 @@ float client_cefc_accumulatortime;
 .float vortex_chargepool_ammo;
 .float hagar_load;
 
-.float grab; // 0 = can't grab, 1 = owner can grab, 2 = owner and team mates can grab, 3 = anyone can grab
+.int grab; // 0 = can't grab, 1 = owner can grab, 2 = owner and team mates can grab, 3 = anyone can grab
 
 #define PROJECTILE_MAKETRIGGER(e) (e).solid = SOLID_CORPSE; (e).dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_CORPSE
 // when doing this, hagar can go through clones
@@ -594,8 +534,6 @@ void PlayerUseKey();
 typedef vector(entity player, entity spot, vector current) spawn_evalfunc_t;
 .spawn_evalfunc_t spawn_evalfunc;
 
-.entity conveyor;
-
 string modname;
 
 .float missile_flags;
@@ -624,6 +562,8 @@ const int MIF_GUIDED_TAG = 128;
 .float elos;
 .float ranks;
 
+.string cvar_cl_physics;
+
 .float init_for_player_needed;
 .void(entity) init_for_player;
 
index 98ec277683c5477912cc1415f234c284a80754b5..52b15b0953fabc047fcefb668db5c6143bb6221f 100644 (file)
@@ -1,13 +1,7 @@
-#if defined(CSQC)
-#elif defined(MENUQC)
-#elif defined(SVQC)
-       #include "../dpdefs/progsdefs.qh"
-    #include "../dpdefs/dpextensions.qh"
-    #include "../common/constants.qh"
-    #include "constants.qh"
-    #include "defs.qh"
-    #include "mutators/mutators_include.qh"
-#endif
+#include "_all.qh"
+
+#include "defs.qh"
+#include "mutators/mutators_include.qh"
 
 /**
  * The point of these entities is to avoid the problems
diff --git a/qcsrc/server/func_breakable.qc b/qcsrc/server/func_breakable.qc
deleted file mode 100644 (file)
index be6104f..0000000
+++ /dev/null
@@ -1,312 +0,0 @@
-#include "weapons/common.qh"
-
-.entity sprite;
-
-.float dmg;
-.float dmg_edge;
-.float dmg_radius;
-.float dmg_force;
-.float debrismovetype;
-.float debrissolid;
-.vector debrisvelocity;
-.vector debrisvelocityjitter;
-.vector debrisavelocityjitter;
-.float debristime;
-.float debristimejitter;
-.float debrisfadetime;
-.float debrisdamageforcescale;
-.float debrisskin;
-
-.string mdl_dead; // or "" to hide when broken
-.string debris; // space separated list of debris models
-// other fields:
-//   mdl = particle effect name
-//   count = particle effect multiplier
-//   targetname = target to trigger to unbreak the model
-//   target = targets to trigger when broken
-//   health = amount of damage it can take
-//   spawnflags:
-//     1 = start disabled (needs to be triggered to activate)
-//     2 = indicate damage
-// notes:
-//   for mdl_dead to work, origin must be set (using a common/origin brush).
-//   Otherwise mdl_dead will be displayed at the map origin, and nobody would
-//   want that!
-
-void func_breakable_damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force);
-
-//
-// func_breakable
-// - basically func_assault_destructible for general gameplay use
-//
-void LaunchDebris (string debrisname, vector force)
-{
-       entity dbr = spawn();
-       setorigin(dbr, self.absmin
-                  + '1 0 0' * random() * (self.absmax.x - self.absmin.x)
-                  + '0 1 0' * random() * (self.absmax.y - self.absmin.y)
-                  + '0 0 1' * random() * (self.absmax.z - self.absmin.z));
-       setmodel (dbr, debrisname );
-       dbr.skin = self.debrisskin;
-       dbr.colormap = self.colormap; // inherit team colors
-       dbr.owner = self; // do not be affected by our own explosion
-       dbr.movetype = self.debrismovetype;
-       dbr.solid = self.debrissolid;
-       if(dbr.solid != SOLID_BSP) // SOLID_BSP has exact collision, MAYBE this works? TODO check this out
-               setsize(dbr, '0 0 0', '0 0 0'); // needed for performance, until engine can deal better with it
-       dbr.velocity_x = self.debrisvelocity.x + self.debrisvelocityjitter.x * crandom();
-       dbr.velocity_y = self.debrisvelocity.y + self.debrisvelocityjitter.y * crandom();
-       dbr.velocity_z = self.debrisvelocity.z + self.debrisvelocityjitter.z * crandom();
-       self.velocity = self.velocity + force * self.debrisdamageforcescale;
-       dbr.avelocity_x = random()*self.debrisavelocityjitter.x;
-       dbr.avelocity_y = random()*self.debrisavelocityjitter.y;
-       dbr.avelocity_z = random()*self.debrisavelocityjitter.z;
-       dbr.damageforcescale = self.debrisdamageforcescale;
-       if(dbr.damageforcescale)
-               dbr.takedamage = DAMAGE_YES;
-       SUB_SetFade(dbr, time + self.debristime + crandom() * self.debristimejitter, self.debrisfadetime);
-}
-
-void func_breakable_colormod()
-{
-       float h;
-       if (!(self.spawnflags & 2))
-               return;
-       h = self.health / self.max_health;
-       if(h < 0.25)
-               self.colormod = '1 0 0';
-       else if(h <= 0.75)
-               self.colormod = '1 0 0' + '0 1 0' * (2 * h - 0.5);
-       else
-               self.colormod = '1 1 1';
-
-       CSQCMODEL_AUTOUPDATE();
-}
-
-void func_breakable_look_destroyed()
-{
-       float floorZ;
-
-       if(self.solid == SOLID_BSP) // in case a misc_follow moved me, save the current origin first
-               self.dropped_origin = self.origin;
-
-       if(self.mdl_dead == "")
-               self.effects |= EF_NODRAW;
-       else {
-               if (self.origin == '0 0 0')     {       // probably no origin brush, so don't spawn in the middle of the map..
-                       floorZ = self.absmin.z;
-                       setorigin(self,((self.absmax+self.absmin)*.5));
-                       self.origin_z = floorZ;
-               }
-               setmodel(self, self.mdl_dead);
-               self.effects &= ~EF_NODRAW;
-       }
-
-       CSQCMODEL_AUTOUPDATE();
-
-       self.solid = SOLID_NOT;
-}
-
-void func_breakable_look_restore()
-{
-       setmodel(self, self.mdl);
-       self.effects &= ~EF_NODRAW;
-
-       if(self.mdl_dead != "") // only do this if we use mdl_dead, to behave better with misc_follow
-               setorigin(self, self.dropped_origin);
-
-       CSQCMODEL_AUTOUPDATE();
-
-       self.solid = SOLID_BSP;
-}
-
-void func_breakable_behave_destroyed()
-{
-       self.health = self.max_health;
-       self.takedamage = DAMAGE_NO;
-       self.bot_attack = false;
-       self.event_damage = func_null;
-       self.state = 1;
-       func_breakable_colormod();
-       if (self.noise1)
-               stopsound (self, CH_TRIGGER_SINGLE);
-}
-
-void func_breakable_behave_restore()
-{
-       self.health = self.max_health;
-       if(self.sprite)
-       {
-               WaypointSprite_UpdateMaxHealth(self.sprite, self.max_health);
-               WaypointSprite_UpdateHealth(self.sprite, self.health);
-       }
-       self.takedamage = DAMAGE_AIM;
-       self.bot_attack = true;
-       self.event_damage = func_breakable_damage;
-       self.state = 0;
-       self.nextthink = 0; // cancel auto respawn
-       func_breakable_colormod();
-       if (self.noise1)
-               sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTEN_NORM);
-}
-
-void func_breakable_init_for_player(entity player)
-{
-       if (self.noise1 && self.state == 0 && clienttype(player) == CLIENTTYPE_REAL)
-       {
-               msg_entity = player;
-               soundto (MSG_ONE, self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTEN_NORM);
-       }
-}
-
-void func_breakable_destroyed()
-{
-       func_breakable_look_destroyed();
-       func_breakable_behave_destroyed();
-
-       CSQCMODEL_AUTOUPDATE();
-}
-
-void func_breakable_restore()
-{
-       func_breakable_look_restore();
-       func_breakable_behave_restore();
-
-       CSQCMODEL_AUTOUPDATE();
-}
-
-vector debrisforce; // global, set before calling this
-void func_breakable_destroy() {
-       float n, i;
-       string oldmsg;
-
-       activator = self.owner;
-       self.owner = world; // set by W_PrepareExplosionByDamage
-
-       // now throw around the debris
-       n = tokenize_console(self.debris);
-       for(i = 0; i < n; ++i)
-               LaunchDebris(argv(i), debrisforce);
-
-       func_breakable_destroyed();
-
-       if(self.noise)
-               sound (self, CH_TRIGGER, self.noise, VOL_BASE, ATTEN_NORM);
-
-       if(self.dmg)
-               RadiusDamage(self, activator, self.dmg, self.dmg_edge, self.dmg_radius, self, world, self.dmg_force, DEATH_HURTTRIGGER, world);
-
-       if(self.cnt)
-               pointparticles(self.cnt, self.absmin * 0.5 + self.absmax * 0.5, '0 0 0', self.count);
-
-       if(self.respawntime)
-       {
-               self.think = func_breakable_restore;
-               self.nextthink = time + self.respawntime + crandom() * self.respawntimejitter;
-       }
-
-       oldmsg = self.message;
-       self.message = "";
-       SUB_UseTargets();
-       self.message = oldmsg;
-}
-
-void func_breakable_damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
-{
-       if(self.state == 1)
-               return;
-       if(self.spawnflags & DOOR_NOSPLASH)
-               if(!(DEATH_ISSPECIAL(deathtype)) && (deathtype & HITTYPE_SPLASH))
-                       return;
-       if(self.team)
-               if(attacker.team == self.team)
-                       return;
-       self.health = self.health - damage;
-       if(self.sprite)
-       {
-               WaypointSprite_Ping(self.sprite);
-               WaypointSprite_UpdateHealth(self.sprite, self.health);
-       }
-       func_breakable_colormod();
-
-       if(self.health <= 0)
-       {
-               debrisforce = force;
-               W_PrepareExplosionByDamage(attacker, func_breakable_destroy);
-       }
-}
-
-void func_breakable_reset()
-{
-       self.team = self.team_saved;
-       func_breakable_look_restore();
-       if(self.spawnflags & 1)
-               func_breakable_behave_destroyed();
-       else
-               func_breakable_behave_restore();
-
-       CSQCMODEL_AUTOUPDATE();
-}
-
-// destructible walls that can be used to trigger target_objective_decrease
-void spawnfunc_func_breakable() {
-       float n, i;
-       if(!self.health)
-               self.health = 100;
-       self.max_health = self.health;
-
-       // yes, I know, MOVETYPE_NONE is not available here, not that one would want it here anyway
-       if(!self.debrismovetype) self.debrismovetype = MOVETYPE_BOUNCE;
-       if(!self.debrissolid) self.debrissolid = SOLID_NOT;
-       if(self.debrisvelocity == '0 0 0') self.debrisvelocity = '0 0 140';
-       if(self.debrisvelocityjitter == '0 0 0') self.debrisvelocityjitter = '70 70 70';
-       if(self.debrisavelocityjitter == '0 0 0') self.debrisavelocityjitter = '600 600 600';
-       if(!self.debristime) self.debristime = 3.5;
-       if(!self.debristimejitter) self.debristime = 2.5;
-
-       if(self.mdl != "")
-               self.cnt = particleeffectnum(self.mdl);
-       if(self.count == 0)
-               self.count = 1;
-
-       if(self.message == "")
-               self.message = "got too close to an explosion";
-       if(self.message2 == "")
-               self.message2 = "was pushed into an explosion by";
-       if(!self.dmg_radius)
-               self.dmg_radius = 150;
-       if(!self.dmg_force)
-               self.dmg_force = 200;
-
-       self.mdl = self.model;
-       SetBrushEntityModel();
-
-       self.use = func_breakable_restore;
-
-       // precache all the models
-       if (self.mdl_dead)
-               precache_model(self.mdl_dead);
-       n = tokenize_console(self.debris);
-       for(i = 0; i < n; ++i)
-               precache_model(argv(i));
-       if(self.noise)
-               precache_sound(self.noise);
-       if(self.noise1)
-               precache_sound(self.noise1);
-
-       self.team_saved = self.team;
-       self.dropped_origin = self.origin;
-
-       self.reset = func_breakable_reset;
-       func_breakable_reset();
-
-       self.init_for_player_needed = 1;
-       self.init_for_player = func_breakable_init_for_player;
-
-       CSQCMODEL_AUTOINIT();
-}
-
-// for use in maps with a "model" key set
-void spawnfunc_misc_breakablemodel() {
-       spawnfunc_func_breakable();
-}
index 2b78ebe0b2d309b5d33ef93768a3ba6cae4ce699..b9ad94e3f3910ec90f254a9a4ded0b3f2e9646e7 100644 (file)
@@ -1,14 +1,8 @@
-#if defined(CSQC)
-#elif defined(MENUQC)
-#elif defined(SVQC)
-       #include "../dpdefs/progsdefs.qh"
-    #include "../common/constants.qh"
-    #include "../common/util.qh"
-    #include "constants.qh"
-    #include "defs.qh"
-#endif
+#include "_all.qh"
 
-float Casing_SendEntity(entity to, float sf)
+#include "../common/util.qh"
+
+float Casing_SendEntity(entity to, int sf)
 {
        WriteByte(MSG_ENTITY, ENT_CLIENT_CASING);
        WriteByte(MSG_ENTITY, self.state); // actually type
index 18d58f4eb9b374d38c3176f41f331bb5cea858fe..c5bbfcab55ed0f132ece9d8e55d517afac328338 100644 (file)
@@ -1,34 +1,30 @@
 #include "g_damage.qh"
-
-#if defined(CSQC)
-#elif defined(MENUQC)
-#elif defined(SVQC)
-    #include "../warpzonelib/common.qh"
-    #include "../common/constants.qh"
-    #include "../common/buffs.qh"
-    #include "../common/teams.qh"
-    #include "../common/util.qh"
-    #include "../common/weapons/weapons.qh"
-    #include "weapons/accuracy.qh"
-    #include "weapons/csqcprojectile.qh"
-    #include "weapons/selection.qh"
-    #include "t_items.qh"
-    #include "autocvars.qh"
-    #include "constants.qh"
-    #include "defs.qh"
-    #include "../common/notifications.qh"
-    #include "../common/deathtypes.qh"
-    #include "mutators/mutators_include.qh"
-    #include "tturrets/include/turrets_early.qh"
-    #include "vehicles/vehicles_def.qh"
-    #include "../csqcmodellib/sv_model.qh"
-    #include "../common/playerstats.qh"
-    #include "g_hook.qh"
-    #include "scores.qh"
-    #include "spawnpoints.qh"
-#endif
-
-float Damage_DamageInfo_SendEntity(entity to, float sf)
+#include "_all.qh"
+
+#include "g_hook.qh"
+#include "mutators/mutators_include.qh"
+#include "scores.qh"
+#include "waypointsprites.qh"
+#include "spawnpoints.qh"
+#include "tturrets/include/turrets_early.qh"
+#include "t_items.qh"
+#include "vehicles/vehicle.qh"
+#include "weapons/accuracy.qh"
+#include "weapons/csqcprojectile.qh"
+#include "weapons/selection.qh"
+#include "../common/buffs.qh"
+#include "../common/constants.qh"
+#include "../common/deathtypes.qh"
+#include "../common/notifications.qh"
+#include "../common/movetypes/movetypes.qh"
+#include "../common/playerstats.qh"
+#include "../common/teams.qh"
+#include "../common/util.qh"
+#include "../common/weapons/all.qh"
+#include "../csqcmodellib/sv_model.qh"
+#include "../warpzonelib/common.qh"
+
+float Damage_DamageInfo_SendEntity(entity to, int sf)
 {
        WriteByte(MSG_ENTITY, ENT_CLIENT_DAMAGEINFO);
        WriteShort(MSG_ENTITY, self.projectiledeathtype);
@@ -43,7 +39,7 @@ float Damage_DamageInfo_SendEntity(entity to, float sf)
        return true;
 }
 
-void Damage_DamageInfo(vector org, float coredamage, float edgedamage, float rad, vector force, float deathtype, float bloodtype, entity dmgowner)
+void Damage_DamageInfo(vector org, float coredamage, float edgedamage, float rad, vector force, int deathtype, float bloodtype, entity dmgowner)
 {
        // TODO maybe call this from non-edgedamage too?
        // TODO maybe make the client do the particle effects for the weapons and the impact sounds using this info?
@@ -67,24 +63,12 @@ void Damage_DamageInfo(vector org, float coredamage, float edgedamage, float rad
        Net_LinkEntity(e, false, 0.2, Damage_DamageInfo_SendEntity);
 }
 
-float IsFlying(entity a)
-{
-       if(a.flags & FL_ONGROUND)
-               return 0;
-       if(a.waterlevel >= WATERLEVEL_SWIMMING)
-               return 0;
-       traceline(a.origin, a.origin - '0 0 48', MOVE_NORMAL, a);
-       if(trace_fraction < 1)
-               return 0;
-       return 1;
-}
-
 void UpdateFrags(entity player, float f)
 {
        PlayerTeamScore_AddScore(player, f);
 }
 
-void GiveFrags (entity attacker, entity targ, float f, float deathtype)
+void GiveFrags (entity attacker, entity targ, float f, int deathtype)
 {
        // TODO route through PlayerScores instead
        if(gameover) return;
@@ -204,7 +188,7 @@ string AppendItemcodes(string s, entity player)
        return s;
 }
 
-void LogDeath(string mode, float deathtype, entity killer, entity killed)
+void LogDeath(string mode, int deathtype, entity killer, entity killed)
 {
        string s;
        if(!autocvar_sv_eventlog)
@@ -226,7 +210,7 @@ void LogDeath(string mode, float deathtype, entity killer, entity killed)
 void Obituary_SpecialDeath(
        entity notif_target,
        float murder,
-       float deathtype,
+       int deathtype,
        string s1, string s2, string s3,
        float f1, float f2, float f3)
 {
@@ -286,7 +270,7 @@ void Obituary_SpecialDeath(
 float Obituary_WeaponDeath(
        entity notif_target,
        float murder,
-       float deathtype,
+       int deathtype,
        string s1, string s2, string s3,
        float f1, float f2)
 {
@@ -294,10 +278,10 @@ float Obituary_WeaponDeath(
        if(death_weapon)
        {
                w_deathtype = deathtype;
-               float death_message = WEP_ACTION(death_weapon, ((murder) ? WR_KILLMESSAGE : WR_SUICIDEMESSAGE));
+               int death_message = WEP_ACTION(death_weapon, ((murder) ? WR_KILLMESSAGE : WR_SUICIDEMESSAGE));
                w_deathtype = false;
 
-               if(death_message)
+               if (death_message)
                {
                        Send_Notification_WOCOVA(
                                NOTIF_ONE,
@@ -330,7 +314,7 @@ float Obituary_WeaponDeath(
        return false;
 }
 
-void Obituary(entity attacker, entity inflictor, entity targ, float deathtype)
+void Obituary(entity attacker, entity inflictor, entity targ, int deathtype)
 {
        // Sanity check
        if (!IS_PLAYER(targ)) { backtrace("Obituary called on non-player?!\n"); return; }
@@ -640,7 +624,7 @@ void Unfreeze (entity targ)
        targ.iceblock = world;
 }
 
-void Damage (entity targ, entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
+void Damage (entity targ, entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
 {
        float mirrordamage;
        float mirrorforce;
@@ -934,8 +918,12 @@ void Damage (entity targ, entity inflictor, entity attacker, float damage, float
                        farcent.think = SUB_Remove;
                }
                else
+               {
                        self.velocity = self.velocity + farce;
+                       self.move_velocity = self.velocity;
+               }
                self.flags &= ~FL_ONGROUND;
+               self.move_flags &= ~FL_ONGROUND;
                UpdateCSQCProjectile(self);
        }
        // apply damage
@@ -954,7 +942,7 @@ void Damage (entity targ, entity inflictor, entity attacker, float damage, float
        }
 }
 
-float RadiusDamageForSource (entity inflictor, vector inflictororigin, vector inflictorvelocity, entity attacker, float coredamage, float edgedamage, float rad, entity cantbe, entity mustbe, float inflictorselfdamage, float forceintensity, float deathtype, entity directhitentity)
+float RadiusDamageForSource (entity inflictor, vector inflictororigin, vector inflictorvelocity, entity attacker, float coredamage, float edgedamage, float rad, entity cantbe, entity mustbe, float inflictorselfdamage, float forceintensity, int deathtype, entity directhitentity)
        // Returns total damage applies to creatures
 {
        entity  targ;
@@ -1143,7 +1131,7 @@ float RadiusDamageForSource (entity inflictor, vector inflictororigin, vector in
        return total_damage_to_creatures;
 }
 
-float RadiusDamage (entity inflictor, entity attacker, float coredamage, float edgedamage, float rad, entity cantbe, entity mustbe, float forceintensity, float deathtype, entity directhitentity)
+float RadiusDamage (entity inflictor, entity attacker, float coredamage, float edgedamage, float rad, entity cantbe, entity mustbe, float forceintensity, int deathtype, entity directhitentity)
 {
        return RadiusDamageForSource (inflictor, (inflictor.origin + (inflictor.mins + inflictor.maxs) * 0.5), inflictor.velocity, attacker, coredamage, edgedamage, rad, cantbe, mustbe, false, forceintensity, deathtype, directhitentity);
 }
index 4cc3f6f63e901d05e4fc863ad89ca76ce5606144..9dce060cc453e4fdbb98bacb60db727cf5d96694 100644 (file)
@@ -10,7 +10,7 @@
     #include "../common/constants.qh"
     #include "../common/teams.qh"
     #include "../common/util.qh"
-    #include "../common/weapons/weapons.qh"
+    #include "../common/weapons/all.qh"
     #include "weapons/accuracy.qh"
     #include "weapons/csqcprojectile.qh"
     #include "weapons/selection.qh"
@@ -22,7 +22,7 @@
     #include "../common/deathtypes.qh"
     #include "mutators/mutators_include.qh"
     #include "tturrets/include/turrets_early.qh"
-    #include "vehicles/vehicles_def.qh"
+    #include "vehicles/vehicle.qh"
     #include "../csqcmodellib/sv_model.qh"
     #include "../common/playerstats.qh"
     #include "g_hook.qh"
@@ -35,9 +35,9 @@
 .float dmg_force;
 .float dmg_radius;
 
-float Damage_DamageInfo_SendEntity(entity to, float sf);
+float Damage_DamageInfo_SendEntity(entity to, int sf);
 
-void Damage_DamageInfo(vector org, float coredamage, float edgedamage, float rad, vector force, float deathtype, float bloodtype, entity dmgowner);
+void Damage_DamageInfo(vector org, float coredamage, float edgedamage, float rad, vector force, int deathtype, float bloodtype, entity dmgowner);
 
 float checkrules_firstblood;
 
@@ -60,16 +60,16 @@ void UpdateFrags(entity player, float f);
 // NOTE: f=0 means still count as a (positive) kill, but count no frags for it
 void W_SwitchWeapon_Force(entity e, float w);
 entity GiveFrags_randomweapons;
-void GiveFrags (entity attacker, entity targ, float f, float deathtype);
+void GiveFrags (entity attacker, entity targ, float f, int deathtype);
 
 string AppendItemcodes(string s, entity player);
 
-void LogDeath(string mode, float deathtype, entity killer, entity killed);
+void LogDeath(string mode, int deathtype, entity killer, entity killed);
 
 void Obituary_SpecialDeath(
        entity notif_target,
        float murder,
-       float deathtype,
+       int deathtype,
        string s1, string s2, string s3,
        float f1, float f2, float f3);
 
@@ -77,11 +77,11 @@ float w_deathtype;
 float Obituary_WeaponDeath(
        entity notif_target,
        float murder,
-       float deathtype,
+       int deathtype,
        string s1, string s2, string s3,
        float f1, float f2);
 
-void Obituary(entity attacker, entity inflictor, entity targ, float deathtype);
+void Obituary(entity attacker, entity inflictor, entity targ, int deathtype);
 
 void Ice_Think();
 
@@ -94,13 +94,13 @@ entity damage_targ;
 entity damage_inflictor;
 entity damage_attacker;
 
-void Damage (entity targ, entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force);
+void Damage (entity targ, entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force);
 
 float RadiusDamage_running;
-float RadiusDamageForSource (entity inflictor, vector inflictororigin, vector inflictorvelocity, entity attacker, float coredamage, float edgedamage, float rad, entity cantbe, entity mustbe, float inflictorselfdamage, float forceintensity, float deathtype, entity directhitentity);
+float RadiusDamageForSource (entity inflictor, vector inflictororigin, vector inflictorvelocity, entity attacker, float coredamage, float edgedamage, float rad, entity cantbe, entity mustbe, float inflictorselfdamage, float forceintensity, int deathtype, entity directhitentity);
        // Returns total damage applies to creatures
 
-float RadiusDamage (entity inflictor, entity attacker, float coredamage, float edgedamage, float rad, entity cantbe, entity mustbe, float forceintensity, float deathtype, entity directhitentity);
+float RadiusDamage (entity inflictor, entity attacker, float coredamage, float edgedamage, float rad, entity cantbe, entity mustbe, float forceintensity, int deathtype, entity directhitentity);
 
 .float fire_damagepersec;
 .float fire_endtime;
index 310833e4367ce2f036ad10c4570be683bfb4f275..7a127eddab3971938567faa9479a1f64c9930222 100644 (file)
@@ -1,21 +1,19 @@
-#if defined(CSQC)
-#elif defined(MENUQC)
-#elif defined(SVQC)
-       #include "../dpdefs/progsdefs.qh"
-    #include "../dpdefs/dpextensions.qh"
-    #include "../warpzonelib/common.qh"
-    #include "../warpzonelib/server.qh"
-    #include "../common/constants.qh"
-    #include "../common/util.qh"
-    #include "../common/weapons/weapons.qh"
-    #include "autocvars.qh"
-    #include "constants.qh"
-    #include "defs.qh"
-    #include "vehicles/vehicles_def.qh"
-    #include "command/common.qh"
-    #include "g_hook.qh"
-    #include "round_handler.qh"
-#endif
+#include "g_hook.qh"
+#include "_all.qh"
+
+#include "weapons/common.qh"
+#include "weapons/weaponsystem.qh"
+#include "weapons/selection.qh"
+#include "weapons/tracing.qh"
+#include "cl_player.qh"
+#include "command/common.qh"
+#include "round_handler.qh"
+#include "vehicles/vehicle.qh"
+#include "../common/constants.qh"
+#include "../common/util.qh"
+#include "../common/weapons/all.qh"
+#include "../warpzonelib/common.qh"
+#include "../warpzonelib/server.qh"
 
 /*============================================
 
@@ -105,7 +103,7 @@ void GrapplingHook_Stop()
 }
 
 .vector hook_start, hook_end;
-float GrapplingHookSend(entity to, float sf)
+float GrapplingHookSend(entity to, int sf)
 {
        WriteByte(MSG_ENTITY, ENT_CLIENT_HOOK);
        sf = sf & 0x7F;
@@ -133,7 +131,7 @@ float GrapplingHookSend(entity to, float sf)
 
 void GrapplingHookThink()
 {
-       float spd, dist, minlength, pullspeed, ropestretch, ropeairfriction, rubberforce, newlength, rubberforce_overstretch, s;
+       float spd, dist, minlength, pullspeed, ropestretch, ropeairfriction, rubberforce, newlength, rubberforce_overstretch;
        vector dir, org, end, v0, dv, v, myorg, vs;
        if(self.realowner.hook != self) // how did that happen?
        {
@@ -150,7 +148,7 @@ void GrapplingHookThink()
 
        self.nextthink = time;
 
-       s = self.realowner.cvar_cl_gunalign;
+       int s = self.realowner.cvar_cl_gunalign;
        if(s != 1 && s != 2 && s != 4)
                s = 3; // default value
        --s;
@@ -289,7 +287,7 @@ void GrapplingHookTouch (void)
        //self.realowner.disableclientprediction = true;
 }
 
-void GrapplingHook_Damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
+void GrapplingHook_Damage (entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
 {
        if(self.health <= 0)
                return;
@@ -315,7 +313,6 @@ void FireGrapplingHook (void)
 {
        entity missile;
        vector org;
-       float s;
        vector vs;
 
        if(forbidWeaponUse()) return;
@@ -323,7 +320,7 @@ void FireGrapplingHook (void)
 
        makevectors(self.v_angle);
 
-       s = self.cvar_cl_gunalign;
+       int s = self.cvar_cl_gunalign;
        if(s != 1 && s != 2 && s != 4)
                s = 3; // default value
        --s;
index da53fbe64b2837689491d9b522780ac5999b9a27..f7382d1666b15b6c295903b3fa90260be3c720a2 100644 (file)
@@ -1,3 +1,7 @@
+#include "_all.qh"
+
+void train_next();
+
 const float LOOP = 1;
 
 const float DNOSHADOW = 2;
index 6e1c06d056f2eb5bf3306240042ad3b933af56bc..62b2cfb51dd5d3a5c9a52a38b78d9654c0e97e58 100644 (file)
@@ -1,14 +1,11 @@
-#if defined(CSQC)
-#elif defined(MENUQC)
-#elif defined(SVQC)
-       #include "../dpdefs/progsdefs.qh"
-    #include "../dpdefs/dpextensions.qh"
-    #include "../common/constants.qh"
-    #include "autocvars.qh"
-    #include "constants.qh"
-    #include "defs.qh"
-    #include "../csqcmodellib/sv_model.qh"
-#endif
+#include "_all.qh"
+
+#include "../common/triggers/subs.qh"
+
+#include "../client/bgmscript.qh"
+
+#include "../common/constants.qh"
+#include "../csqcmodellib/sv_model.qh"
 
 .float modelscale;
 
@@ -29,7 +26,22 @@ void g_model_setcolormaptoactivator (void)
 void g_clientmodel_setcolormaptoactivator (void)
 {
        g_model_setcolormaptoactivator();
-       self.SendFlags |= 1;
+       self.SendFlags |= (8 | 1);
+}
+
+void g_clientmodel_use(void)
+{
+       if (self.antiwall_flag == 1)
+       {
+               self.inactive = 1;
+               self.solid = SOLID_NOT;
+       }
+       else if (self.antiwall_flag == 2)
+       {
+               self.inactive = 0;
+               self.solid = self.default_solid;
+       }
+       g_clientmodel_setcolormaptoactivator();
 }
 
 void g_model_dropbyspawnflags()
@@ -60,12 +72,12 @@ void g_clientmodel_dropbyspawnflags()
                self.SendFlags |= 2;
 }
 
-float g_clientmodel_genericsendentity (entity to, float sf)
+float g_clientmodel_genericsendentity (entity to, int sf)
 {
        sf = sf & 0x0F;
        if(self.angles != '0 0 0')
                sf |= 0x10;
-       if(self.solid && (self.mins != '0 0 0' || self.maxs != '0 0 0'))
+       if(self.mins != '0 0 0' || self.maxs != '0 0 0')
                sf |= 0x20;
        if(self.colormap != 0)
                sf |= 0x40;
@@ -133,6 +145,12 @@ float g_clientmodel_genericsendentity (entity to, float sf)
                        WriteCoord(MSG_ENTITY, self.movedir.z);
                        WriteByte(MSG_ENTITY, floor(self.lip * 255));
                }
+               WriteShort(MSG_ENTITY, self.fade_start);
+               WriteShort(MSG_ENTITY, self.fade_end);
+               WriteShort(MSG_ENTITY, self.alpha_max);
+               WriteShort(MSG_ENTITY, self.alpha_min);
+               WriteShort(MSG_ENTITY, self.inactive);
+               WriteShort(MSG_ENTITY, self.fade_vertical_offset);
        }
 
        return true;
@@ -151,11 +169,12 @@ float g_clientmodel_genericsendentity (entity to, float sf)
        if(self.geomtype) if(autocvar_physics_ode && checkextension("DP_PHYSICS_ODE")) self.movetype = MOVETYPE_PHYSICS; \
        if(!self.scale) self.scale = self.modelscale; \
        SetBrushEntityModel(); \
-       self.use = g_clientmodel_setcolormaptoactivator; \
+       self.use = g_clientmodel_use; \
        InitializeEntity(self, g_clientmodel_dropbyspawnflags, INITPRIO_DROPTOFLOOR); \
        if(!self.solid) self.solid = (sol); else if(self.solid < 0) self.solid = SOLID_NOT; \
        if(!self.bgmscriptsustain) self.bgmscriptsustain = 1; else if(self.bgmscriptsustain < 0) self.bgmscriptsustain = 0; \
-       Net_LinkEntity(self, true, 0, g_clientmodel_genericsendentity);
+       Net_LinkEntity(self, true, 0, g_clientmodel_genericsendentity); \
+       self.default_solid = sol;
 
 // non-solid model entities:
 void spawnfunc_misc_gamemodel()         { self.angles_x = -self.angles.x; G_MODEL_INIT      (SOLID_NOT) } // model entity
index 74a8cf7f96126135f1ec45074a86d9d0036e3201..eacba6452869ce4bb9c95836f1de2b28ccf356d7 100644 (file)
@@ -1,6 +1,9 @@
 #include "g_subs.qh"
+#include "_all.qh"
 
-void SUB_NullThink(void) { }
+#include "antilag.qh"
+#include "command/common.qh"
+#include "../warpzonelib/common.qh"
 
 void spawnfunc_info_null (void)
 {
@@ -52,380 +55,6 @@ void updateanim(entity e)
        //print(ftos(time), " -> ", ftos(e.frame), "\n");
 }
 
-/*
-==================
-SUB_Remove
-
-Remove self
-==================
-*/
-void SUB_Remove (void)
-{
-       remove (self);
-}
-
-/*
-==================
-SUB_Friction
-
-Applies some friction to self
-==================
-*/
-void SUB_Friction (void)
-{
-       self.nextthink = time;
-       if(self.flags & FL_ONGROUND)
-               self.velocity = self.velocity * (1 - frametime * self.friction);
-}
-
-/*
-==================
-SUB_VanishOrRemove
-
-Makes client invisible or removes non-client
-==================
-*/
-void SUB_VanishOrRemove (entity ent)
-{
-       if (IS_CLIENT(ent))
-       {
-               // vanish
-               ent.alpha = -1;
-               ent.effects = 0;
-               ent.glow_size = 0;
-               ent.pflags = 0;
-       }
-       else
-       {
-               // remove
-               remove (ent);
-       }
-}
-
-void SUB_SetFade_Think (void)
-{
-       if(self.alpha == 0)
-               self.alpha = 1;
-       self.think = SUB_SetFade_Think;
-       self.nextthink = time;
-       self.alpha -= frametime * self.fade_rate;
-       if (self.alpha < 0.01)
-               SUB_VanishOrRemove(self);
-       else
-               self.nextthink = time;
-}
-
-/*
-==================
-SUB_SetFade
-
-Fade 'ent' out when time >= 'when'
-==================
-*/
-void SUB_SetFade (entity ent, float when, float fadetime)
-{
-       ent.fade_rate = 1/fadetime;
-       ent.think = SUB_SetFade_Think;
-       ent.nextthink = when;
-}
-
-/*
-=============
-SUB_CalcMove
-
-calculate self.velocity and self.nextthink to reach dest from
-self.origin traveling at speed
-===============
-*/
-void SUB_CalcMoveDone (void)
-{
-       // After moving, set origin to exact final destination
-
-       setorigin (self, self.finaldest);
-       self.velocity = '0 0 0';
-       self.nextthink = -1;
-       if (self.think1)
-               self.think1 ();
-}
-
-void SUB_CalcMove_controller_think (void)
-{
-       entity oldself;
-       float traveltime;
-       float phasepos;
-       float nexttick;
-       vector delta;
-       vector delta2;
-       vector veloc;
-       vector angloc;
-       vector nextpos;
-       delta = self.destvec;
-       delta2 = self.destvec2;
-       if(time < self.animstate_endtime) {
-               nexttick = time + sys_frametime;
-
-               traveltime = self.animstate_endtime - self.animstate_starttime;
-               phasepos = (nexttick - self.animstate_starttime) / traveltime; // range: [0, 1]
-               phasepos = cubic_speedfunc(self.platmovetype_start, self.platmovetype_end, phasepos);
-               nextpos = self.origin + (delta * phasepos) + (delta2 * phasepos * phasepos);
-               // derivative: delta + 2 * delta2 * phasepos (e.g. for angle positioning)
-
-               if(self.owner.platmovetype_turn)
-               {
-                       vector destangle;
-                       destangle = delta + 2 * delta2 * phasepos;
-                       destangle = vectoangles(destangle);
-                       destangle.x = -destangle.x; // flip up / down orientation
-
-                       // take the shortest distance for the angles
-                       self.owner.angles_x -= 360 * floor((self.owner.angles.x - destangle.x) / 360 + 0.5);
-                       self.owner.angles_y -= 360 * floor((self.owner.angles.y - destangle.y) / 360 + 0.5);
-                       self.owner.angles_z -= 360 * floor((self.owner.angles.z - destangle.z) / 360 + 0.5);
-                       angloc = destangle - self.owner.angles;
-                       angloc = angloc * (1 / sys_frametime); // so it arrives for the next frame
-                       self.owner.avelocity = angloc;
-               }
-               if(nexttick < self.animstate_endtime)
-                       veloc = nextpos - self.owner.origin;
-               else
-                       veloc = self.finaldest - self.owner.origin;
-               veloc = veloc * (1 / sys_frametime); // so it arrives for the next frame
-
-               self.owner.velocity = veloc;
-               self.nextthink = nexttick;
-       } else {
-               // derivative: delta + 2 * delta2 (e.g. for angle positioning)
-               oldself = self;
-               self.owner.think = self.think1;
-               self = self.owner;
-               remove(oldself);
-               self.think();
-       }
-}
-
-void SUB_CalcMove_controller_setbezier (entity controller, vector org, vector control, vector dest)
-{
-       // 0 * (1-t) * (1-t) + 2 * control * t * (1-t) + dest * t * t
-       // 2 * control * t - 2 * control * t * t + dest * t * t
-       // 2 * control * t + (dest - 2 * control) * t * t
-
-       controller.origin = org; // starting point
-       control -= org;
-       dest -= org;
-
-       controller.destvec = 2 * control; // control point
-       controller.destvec2 = dest - 2 * control; // quadratic part required to reach end point
-       // also: initial d/dphasepos origin = 2 * control, final speed = 2 * (dest - control)
-}
-
-void SUB_CalcMove_controller_setlinear (entity controller, vector org, vector dest)
-{
-       // 0 * (1-t) * (1-t) + 2 * control * t * (1-t) + dest * t * t
-       // 2 * control * t - 2 * control * t * t + dest * t * t
-       // 2 * control * t + (dest - 2 * control) * t * t
-
-       controller.origin = org; // starting point
-       dest -= org;
-
-       controller.destvec = dest; // end point
-       controller.destvec2 = '0 0 0';
-}
-
-void SUB_CalcMove_Bezier (vector tcontrol, vector tdest, float tspeedtype, float tspeed, void() func)
-{
-       float   traveltime;
-       entity controller;
-
-       if (!tspeed)
-               objerror ("No speed is defined!");
-
-       self.think1 = func;
-       self.finaldest = tdest;
-       self.think = SUB_CalcMoveDone;
-
-       switch(tspeedtype)
-       {
-               default:
-               case TSPEED_START:
-                       traveltime = 2 * vlen(tcontrol - self.origin) / tspeed;
-                       break;
-               case TSPEED_END:
-                       traveltime = 2 * vlen(tcontrol - tdest)       / tspeed;
-                       break;
-               case TSPEED_LINEAR:
-                       traveltime = vlen(tdest - self.origin)        / tspeed;
-                       break;
-               case TSPEED_TIME:
-                       traveltime = tspeed;
-                       break;
-       }
-
-       if (traveltime < 0.1) // useless anim
-       {
-               self.velocity = '0 0 0';
-               self.nextthink = self.ltime + 0.1;
-               return;
-       }
-
-       controller = spawn();
-       controller.classname = "SUB_CalcMove_controller";
-       controller.owner = self;
-       controller.platmovetype = self.platmovetype;
-       controller.platmovetype_start = self.platmovetype_start;
-       controller.platmovetype_end = self.platmovetype_end;
-       SUB_CalcMove_controller_setbezier(controller, self.origin, tcontrol, tdest);
-       controller.finaldest = (tdest + '0 0 0.125'); // where do we want to end? Offset to overshoot a bit.
-       controller.animstate_starttime = time;
-       controller.animstate_endtime = time + traveltime;
-       controller.think = SUB_CalcMove_controller_think;
-       controller.think1 = self.think;
-
-       // the thinking is now done by the controller
-       self.think = SUB_NullThink; // for PushMove
-       self.nextthink = self.ltime + traveltime;
-
-       // invoke controller
-       self = controller;
-       self.think();
-       self = self.owner;
-}
-
-void SUB_CalcMove (vector tdest, float tspeedtype, float tspeed, void() func)
-{
-       vector  delta;
-       float   traveltime;
-
-       if (!tspeed)
-               objerror ("No speed is defined!");
-
-       self.think1 = func;
-       self.finaldest = tdest;
-       self.think = SUB_CalcMoveDone;
-
-       if (tdest == self.origin)
-       {
-               self.velocity = '0 0 0';
-               self.nextthink = self.ltime + 0.1;
-               return;
-       }
-
-       delta = tdest - self.origin;
-
-       switch(tspeedtype)
-       {
-               default:
-               case TSPEED_START:
-               case TSPEED_END:
-               case TSPEED_LINEAR:
-                       traveltime = vlen (delta) / tspeed;
-                       break;
-               case TSPEED_TIME:
-                       traveltime = tspeed;
-                       break;
-       }
-
-       // Very short animations don't really show off the effect
-       // of controlled animation, so let's just use linear movement.
-       // Alternatively entities can choose to specify non-controlled movement.
-        // The only currently implemented alternative movement is linear (value 1)
-       if (traveltime < 0.15 || (self.platmovetype_start == 1 && self.platmovetype_end == 1)) // is this correct?
-       {
-               self.velocity = delta * (1/traveltime); // QuakeC doesn't allow vector/float division
-               self.nextthink = self.ltime + traveltime;
-               return;
-       }
-
-       // now just run like a bezier curve...
-       SUB_CalcMove_Bezier((self.origin + tdest) * 0.5, tdest, tspeedtype, tspeed, func);
-}
-
-void SUB_CalcMoveEnt (entity ent, vector tdest, float tspeedtype, float tspeed, void() func)
-{
-       entity  oldself;
-
-       oldself = self;
-       self = ent;
-
-       SUB_CalcMove (tdest, tspeedtype, tspeed, func);
-
-       self = oldself;
-}
-
-/*
-=============
-SUB_CalcAngleMove
-
-calculate self.avelocity and self.nextthink to reach destangle from
-self.angles rotating
-
-The calling function should make sure self.think is valid
-===============
-*/
-void SUB_CalcAngleMoveDone (void)
-{
-       // After rotating, set angle to exact final angle
-       self.angles = self.finalangle;
-       self.avelocity = '0 0 0';
-       self.nextthink = -1;
-       if (self.think1)
-               self.think1 ();
-}
-
-// FIXME: I fixed this function only for rotation around the main axes
-void SUB_CalcAngleMove (vector destangle, float tspeedtype, float tspeed, void() func)
-{
-       vector  delta;
-       float   traveltime;
-
-       if (!tspeed)
-               objerror ("No speed is defined!");
-
-       // take the shortest distance for the angles
-       self.angles_x -= 360 * floor((self.angles.x - destangle.x) / 360 + 0.5);
-       self.angles_y -= 360 * floor((self.angles.y - destangle.y) / 360 + 0.5);
-       self.angles_z -= 360 * floor((self.angles.z - destangle.z) / 360 + 0.5);
-       delta = destangle - self.angles;
-
-       switch(tspeedtype)
-       {
-               default:
-               case TSPEED_START:
-               case TSPEED_END:
-               case TSPEED_LINEAR:
-                       traveltime = vlen (delta) / tspeed;
-                       break;
-               case TSPEED_TIME:
-                       traveltime = tspeed;
-                       break;
-       }
-
-       self.think1 = func;
-       self.finalangle = destangle;
-       self.think = SUB_CalcAngleMoveDone;
-
-       if (traveltime < 0.1)
-       {
-               self.avelocity = '0 0 0';
-               self.nextthink = self.ltime + 0.1;
-               return;
-       }
-
-       self.avelocity = delta * (1 / traveltime);
-       self.nextthink = self.ltime + traveltime;
-}
-
-void SUB_CalcAngleMoveEnt (entity ent, vector destangle, float tspeedtype, float tspeed, void() func)
-{
-       entity  oldself;
-
-       oldself = self;
-       self = ent;
-
-       SUB_CalcAngleMove (destangle, tspeedtype, tspeed, func);
-
-       self = oldself;
-}
-
 /*
 ==================
 main
index 04477e62919dc48477448f104366f39d2f8224e6..d62bbb6124e57bd014b2976bde0d5532990b5f98 100644 (file)
@@ -70,12 +70,6 @@ void SUB_CalcMove_controller_setbezier (entity controller, vector org, vector co
 
 void SUB_CalcMove_controller_setlinear (entity controller, vector org, vector dest);
 
-float TSPEED_TIME = -1;
-float TSPEED_LINEAR = 0;
-float TSPEED_START = 1;
-float TSPEED_END = 2;
-// TODO average too?
-
 void SUB_CalcMove_Bezier (vector tcontrol, vector tdest, float tspeedtype, float tspeed, void() func);
 
 void SUB_CalcMove (vector tdest, float tspeedtype, float tspeed, void() func);
index 63e498bfc36075512a8d0f0581e44d8d0f9dd3c4..70a316386e83d89458bca578c84284acb725eb5c 100644 (file)
@@ -100,11 +100,11 @@ float GetXBlock(float x, string dat)
        return stof(substring(dat, x-1, 1));
 }
 
-string SetXBlock(float x, string dat, float new)
+string SetXBlock(float x, string dat, float val)
 {
        return strcat(
                substring(dat, 0, x-1),
-               ftos(new),
+               ftos(val),
                substring(dat, x, -1)
        );
 }
diff --git a/qcsrc/server/g_triggers.qc b/qcsrc/server/g_triggers.qc
deleted file mode 100644 (file)
index 9bb1e06..0000000
+++ /dev/null
@@ -1,2129 +0,0 @@
-#include "g_triggers.qh"
-#include "t_jumppads.qh"
-
-void SUB_DontUseTargets()
-{
-}
-
-
-void DelayThink()
-{
-       activator = self.enemy;
-       SUB_UseTargets ();
-       remove(self);
-}
-
-/*
-==============================
-SUB_UseTargets
-
-the global "activator" should be set to the entity that initiated the firing.
-
-If self.delay is set, a DelayedUse entity will be created that will actually
-do the SUB_UseTargets after that many seconds have passed.
-
-Centerprints any self.message to the activator.
-
-Removes all entities with a targetname that match self.killtarget,
-and removes them, so some events can remove other triggers.
-
-Search for (string)targetname in all entities that
-match (string)self.target and call their .use function
-
-==============================
-*/
-void SUB_UseTargets()
-{
-       entity t, stemp, otemp, act;
-       string s;
-       float i;
-
-//
-// check for a delay
-//
-       if (self.delay)
-       {
-       // create a temp object to fire at a later time
-               t = spawn();
-               t.classname = "DelayedUse";
-               t.nextthink = time + self.delay;
-               t.think = DelayThink;
-               t.enemy = activator;
-               t.message = self.message;
-               t.killtarget = self.killtarget;
-               t.target = self.target;
-               t.target2 = self.target2;
-               t.target3 = self.target3;
-               t.target4 = self.target4;
-               return;
-       }
-
-
-//
-// print the message
-//
-       if(self)
-       if(IS_PLAYER(activator) && self.message != "")
-       if(IS_REAL_CLIENT(activator))
-       {
-               centerprint(activator, self.message);
-               if (self.noise == "")
-                       play2(activator, "misc/talk.wav");
-       }
-
-//
-// kill the killtagets
-//
-       s = self.killtarget;
-       if (s != "")
-       {
-               for(t = world; (t = find(t, targetname, s)); )
-                       remove(t);
-       }
-
-//
-// fire targets
-//
-       act = activator;
-       stemp = self;
-       otemp = other;
-
-       if(stemp.target_random)
-               RandomSelection_Init();
-
-       for(i = 0; i < 4; ++i)
-       {
-               switch(i)
-               {
-                       default:
-                       case 0: s = stemp.target; break;
-                       case 1: s = stemp.target2; break;
-                       case 2: s = stemp.target3; break;
-                       case 3: s = stemp.target4; break;
-               }
-               if (s != "")
-               {
-                       for(t = world; (t = find(t, targetname, s)); )
-                       if(t.use)
-                       {
-                               if(stemp.target_random)
-                               {
-                                       RandomSelection_Add(t, 0, string_null, 1, 0);
-                               }
-                               else
-                               {
-                                       self = t;
-                                       other = stemp;
-                                       activator = act;
-                                       self.use();
-                               }
-                       }
-               }
-       }
-
-       if(stemp.target_random && RandomSelection_chosen_ent)
-       {
-               self = RandomSelection_chosen_ent;
-               other = stemp;
-               activator = act;
-               self.use();
-       }
-
-       activator = act;
-       self = stemp;
-       other = otemp;
-}
-
-
-//=============================================================================
-
-// the wait time has passed, so set back up for another activation
-void multi_wait()
-{
-       if (self.max_health)
-       {
-               self.health = self.max_health;
-               self.takedamage = DAMAGE_YES;
-               self.solid = SOLID_BBOX;
-       }
-}
-
-
-// the trigger was just touched/killed/used
-// self.enemy should be set to the activator so it can be held through a delay
-// so wait for the delay time before firing
-void multi_trigger()
-{
-       if (self.nextthink > time)
-       {
-               return;         // allready been triggered
-       }
-
-       if (self.classname == "trigger_secret")
-       {
-               if (!IS_PLAYER(self.enemy))
-                       return;
-               found_secrets = found_secrets + 1;
-               WriteByte (MSG_ALL, SVC_FOUNDSECRET);
-       }
-
-       if (self.noise)
-               sound (self.enemy, CH_TRIGGER, self.noise, VOL_BASE, ATTEN_NORM);
-
-// don't trigger again until reset
-       self.takedamage = DAMAGE_NO;
-
-       activator = self.enemy;
-       other = self.goalentity;
-       SUB_UseTargets();
-
-       if (self.wait > 0)
-       {
-               self.think = multi_wait;
-               self.nextthink = time + self.wait;
-       }
-       else if (self.wait == 0)
-       {
-               multi_wait(); // waiting finished
-       }
-       else
-       {       // we can't just remove (self) here, because this is a touch function
-               // called wheil C code is looping through area links...
-               self.touch = func_null;
-       }
-}
-
-void multi_use()
-{
-       self.goalentity = other;
-       self.enemy = activator;
-       multi_trigger();
-}
-
-void multi_touch()
-{
-       if(!(self.spawnflags & 2))
-       if(!other.iscreature)
-                       return;
-
-       if(self.team)
-               if(((self.spawnflags & 4) == 0) == (self.team != other.team))
-                       return;
-
-// if the trigger has an angles field, check player's facing direction
-       if (self.movedir != '0 0 0')
-       {
-               makevectors (other.angles);
-               if (v_forward * self.movedir < 0)
-                       return;         // not facing the right way
-       }
-
-       EXACTTRIGGER_TOUCH;
-
-       self.enemy = other;
-       self.goalentity = other;
-       multi_trigger ();
-}
-
-void multi_eventdamage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
-{
-       if (!self.takedamage)
-               return;
-       if(self.spawnflags & DOOR_NOSPLASH)
-               if(!(DEATH_ISSPECIAL(deathtype)) && (deathtype & HITTYPE_SPLASH))
-                       return;
-       self.health = self.health - damage;
-       if (self.health <= 0)
-       {
-               self.enemy = attacker;
-               self.goalentity = inflictor;
-               multi_trigger();
-       }
-}
-
-void multi_reset()
-{
-       if ( !(self.spawnflags & SPAWNFLAG_NOTOUCH) )
-               self.touch = multi_touch;
-       if (self.max_health)
-       {
-               self.health = self.max_health;
-               self.takedamage = DAMAGE_YES;
-               self.solid = SOLID_BBOX;
-       }
-       self.think = func_null;
-       self.nextthink = 0;
-       self.team = self.team_saved;
-}
-
-/*QUAKED spawnfunc_trigger_multiple (.5 .5 .5) ? notouch
-Variable sized repeatable trigger.  Must be targeted at one or more entities.  If "health" is set, the trigger must be killed to activate each time.
-If "delay" is set, the trigger waits some time after activating before firing.
-"wait" : Seconds between triggerings. (.2 default)
-If notouch is set, the trigger is only fired by other entities, not by touching.
-NOTOUCH has been obsoleted by spawnfunc_trigger_relay!
-sounds
-1)     secret
-2)     beep beep
-3)     large switch
-4)
-set "message" to text string
-*/
-void spawnfunc_trigger_multiple()
-{
-       self.reset = multi_reset;
-       if (self.sounds == 1)
-       {
-               precache_sound ("misc/secret.wav");
-               self.noise = "misc/secret.wav";
-       }
-       else if (self.sounds == 2)
-       {
-               precache_sound ("misc/talk.wav");
-               self.noise = "misc/talk.wav";
-       }
-       else if (self.sounds == 3)
-       {
-               precache_sound ("misc/trigger1.wav");
-               self.noise = "misc/trigger1.wav";
-       }
-
-       if (!self.wait)
-               self.wait = 0.2;
-       else if(self.wait < -1)
-               self.wait = 0;
-       self.use = multi_use;
-
-       EXACTTRIGGER_INIT;
-
-       self.team_saved = self.team;
-
-       if (self.health)
-       {
-               if (self.spawnflags & SPAWNFLAG_NOTOUCH)
-                       objerror ("health and notouch don't make sense\n");
-               self.max_health = self.health;
-               self.event_damage = multi_eventdamage;
-               self.takedamage = DAMAGE_YES;
-               self.solid = SOLID_BBOX;
-               setorigin (self, self.origin);  // make sure it links into the world
-       }
-       else
-       {
-               if ( !(self.spawnflags & SPAWNFLAG_NOTOUCH) )
-               {
-                       self.touch = multi_touch;
-                       setorigin (self, self.origin);  // make sure it links into the world
-               }
-       }
-}
-
-
-/*QUAKED spawnfunc_trigger_once (.5 .5 .5) ? notouch
-Variable sized trigger. Triggers once, then removes itself.  You must set the key "target" to the name of another object in the level that has a matching
-"targetname".  If "health" is set, the trigger must be killed to activate.
-If notouch is set, the trigger is only fired by other entities, not by touching.
-if "killtarget" is set, any objects that have a matching "target" will be removed when the trigger is fired.
-if "angle" is set, the trigger will only fire when someone is facing the direction of the angle.  Use "360" for an angle of 0.
-sounds
-1)     secret
-2)     beep beep
-3)     large switch
-4)
-set "message" to text string
-*/
-void spawnfunc_trigger_once()
-{
-       self.wait = -1;
-       spawnfunc_trigger_multiple();
-}
-
-//=============================================================================
-
-/*QUAKED spawnfunc_trigger_relay (.5 .5 .5) (-8 -8 -8) (8 8 8)
-This fixed size trigger cannot be touched, it can only be fired by other events.  It can contain killtargets, targets, delays, and messages.
-*/
-void spawnfunc_trigger_relay()
-{
-       self.use = SUB_UseTargets;
-       self.reset = spawnfunc_trigger_relay; // this spawnfunc resets fully
-}
-
-void delay_use()
-{
-    self.think = SUB_UseTargets;
-    self.nextthink = self.wait;
-}
-
-void delay_reset()
-{
-       self.think = func_null;
-       self.nextthink = 0;
-}
-
-void spawnfunc_trigger_delay()
-{
-    if(!self.wait)
-        self.wait = 1;
-
-    self.use = delay_use;
-    self.reset = delay_reset;
-}
-
-//=============================================================================
-
-
-void counter_use()
-{
-       self.count -= 1;
-       if (self.count < 0)
-               return;
-
-       if (self.count == 0)
-       {
-               if(IS_PLAYER(activator) && (self.spawnflags & SPAWNFLAG_NOMESSAGE) == 0)
-                       Send_Notification(NOTIF_ONE, activator, MSG_CENTER, CENTER_SEQUENCE_COMPLETED);
-
-               self.enemy = activator;
-               multi_trigger ();
-       }
-       else
-       {
-               if(IS_PLAYER(activator) && (self.spawnflags & SPAWNFLAG_NOMESSAGE) == 0)
-               if(self.count >= 4)
-                       Send_Notification(NOTIF_ONE, activator, MSG_CENTER, CENTER_SEQUENCE_COUNTER);
-               else
-                       Send_Notification(NOTIF_ONE, activator, MSG_CENTER, CENTER_SEQUENCE_COUNTER_FEWMORE, self.count);
-       }
-}
-
-void counter_reset()
-{
-       self.count = self.cnt;
-       multi_reset();
-}
-
-/*QUAKED spawnfunc_trigger_counter (.5 .5 .5) ? nomessage
-Acts as an intermediary for an action that takes multiple inputs.
-
-If nomessage is not set, t will print "1 more.. " etc when triggered and "sequence complete" when finished.
-
-After the counter has been triggered "count" times (default 2), it will fire all of it's targets and remove itself.
-*/
-void spawnfunc_trigger_counter()
-{
-       self.wait = -1;
-       if (!self.count)
-               self.count = 2;
-       self.cnt = self.count;
-
-       self.use = counter_use;
-       self.reset = counter_reset;
-}
-
-void trigger_hurt_use()
-{
-       if(IS_PLAYER(activator))
-               self.enemy = activator;
-       else
-               self.enemy = world; // let's just destroy it, if taking over is too much work
-}
-
-void trigger_hurt_touch()
-{
-       if (self.active != ACTIVE_ACTIVE)
-               return;
-
-       if(self.team)
-               if(((self.spawnflags & 4) == 0) == (self.team != other.team))
-                       return;
-
-       // only do the EXACTTRIGGER_TOUCH checks when really needed (saves some cpu)
-       if (other.iscreature)
-       {
-               if (other.takedamage)
-               if (other.triggerhurttime < time)
-               {
-                       EXACTTRIGGER_TOUCH;
-                       other.triggerhurttime = time + 1;
-
-                       entity own;
-                       own = self.enemy;
-                       if (!IS_PLAYER(own))
-                       {
-                               own = self;
-                               self.enemy = world; // I still hate you all
-                       }
-
-                       Damage (other, self, own, self.dmg, DEATH_HURTTRIGGER, other.origin, '0 0 0');
-               }
-       }
-       else if(other.damagedbytriggers)
-       {
-               if(other.takedamage)
-               {
-                       EXACTTRIGGER_TOUCH;
-                       Damage(other, self, self, self.dmg, DEATH_HURTTRIGGER, other.origin, '0 0 0');
-               }
-       }
-
-       return;
-}
-
-/*QUAKED spawnfunc_trigger_hurt (.5 .5 .5) ?
-Any object touching this will be hurt
-set dmg to damage amount
-defalt dmg = 5
-*/
-void spawnfunc_trigger_hurt()
-{
-       EXACTTRIGGER_INIT;
-       self.active = ACTIVE_ACTIVE;
-       self.touch = trigger_hurt_touch;
-       self.use = trigger_hurt_use;
-       self.enemy = world; // I hate you all
-       if (!self.dmg)
-               self.dmg = 1000;
-       if (self.message == "")
-               self.message = "was in the wrong place";
-       if (self.message2 == "")
-               self.message2 = "was thrown into a world of hurt by";
-       // self.message = "someone like %s always gets wrongplaced";
-
-       if(!trigger_hurt_first)
-               trigger_hurt_first = self;
-       if(trigger_hurt_last)
-               trigger_hurt_last.trigger_hurt_next = self;
-       trigger_hurt_last = self;
-}
-
-float tracebox_hits_trigger_hurt(vector start, vector mi, vector ma, vector end)
-{
-       entity th;
-
-       for(th = trigger_hurt_first; th; th = th.trigger_hurt_next)
-               if(tracebox_hits_box(start, mi, ma, end, th.absmin, th.absmax))
-                       return true;
-
-       return false;
-}
-
-//////////////////////////////////////////////////////////////
-//
-//
-//
-//Trigger heal --a04191b92fbd93aa67214ef7e72d6d2e
-//
-//////////////////////////////////////////////////////////////
-
-void trigger_heal_touch()
-{
-       if (self.active != ACTIVE_ACTIVE)
-               return;
-
-       // only do the EXACTTRIGGER_TOUCH checks when really needed (saves some cpu)
-       if (other.iscreature)
-       {
-               if (other.takedamage)
-               if (!other.deadflag)
-               if (other.triggerhealtime < time)
-               {
-                       EXACTTRIGGER_TOUCH;
-                       other.triggerhealtime = time + 1;
-
-                       if (other.health < self.max_health)
-                       {
-                               other.health = min(other.health + self.health, self.max_health);
-                               other.pauserothealth_finished = max(other.pauserothealth_finished, time + autocvar_g_balance_pause_health_rot);
-                               sound (other, CH_TRIGGER, self.noise, VOL_BASE, ATTEN_NORM);
-                       }
-               }
-       }
-}
-
-void spawnfunc_trigger_heal()
-{
-       self.active = ACTIVE_ACTIVE;
-
-       EXACTTRIGGER_INIT;
-       self.touch = trigger_heal_touch;
-       if (!self.health)
-               self.health = 10;
-       if (!self.max_health)
-               self.max_health = 200; //Max health topoff for field
-       if(self.noise == "")
-               self.noise = "misc/mediumhealth.wav";
-       precache_sound(self.noise);
-}
-
-
-//////////////////////////////////////////////////////////////
-//
-//
-//
-//End trigger_heal
-//
-//////////////////////////////////////////////////////////////
-
-void trigger_gravity_remove(entity own)
-{
-       if(own.trigger_gravity_check.owner == own)
-       {
-               UpdateCSQCProjectile(own);
-               own.gravity = own.trigger_gravity_check.gravity;
-               remove(own.trigger_gravity_check);
-       }
-       else
-               backtrace("Removing a trigger_gravity_check with no valid owner");
-       own.trigger_gravity_check = world;
-}
-void trigger_gravity_check_think()
-{
-       // This spawns when a player enters the gravity zone and checks if he left.
-       // Each frame, self.count is set to 2 by trigger_gravity_touch() and decreased by 1 here.
-       // It the player has left the gravity trigger, this will be allowed to reach 0 and indicate that.
-       if(self.count <= 0)
-       {
-               if(self.owner.trigger_gravity_check == self)
-                       trigger_gravity_remove(self.owner);
-               else
-                       remove(self);
-               return;
-       }
-       else
-       {
-               self.count -= 1;
-               self.nextthink = time;
-       }
-}
-
-void trigger_gravity_use()
-{
-       self.state = !self.state;
-}
-
-void trigger_gravity_touch()
-{
-       float g;
-
-       if(self.state != true)
-               return;
-
-       EXACTTRIGGER_TOUCH;
-
-       g = self.gravity;
-
-       if (!(self.spawnflags & 1))
-       {
-               if(other.trigger_gravity_check)
-               {
-                       if(self == other.trigger_gravity_check.enemy)
-                       {
-                               // same?
-                               other.trigger_gravity_check.count = 2; // gravity one more frame...
-                               return;
-                       }
-
-                       // compare prio
-                       if(self.cnt > other.trigger_gravity_check.enemy.cnt)
-                               trigger_gravity_remove(other);
-                       else
-                               return;
-               }
-               other.trigger_gravity_check = spawn();
-               other.trigger_gravity_check.enemy = self;
-               other.trigger_gravity_check.owner = other;
-               other.trigger_gravity_check.gravity = other.gravity;
-               other.trigger_gravity_check.think = trigger_gravity_check_think;
-               other.trigger_gravity_check.nextthink = time;
-               other.trigger_gravity_check.count = 2;
-               if(other.gravity)
-                       g *= other.gravity;
-       }
-
-       if (other.gravity != g)
-       {
-               other.gravity = g;
-               if(self.noise != "")
-                       sound (other, CH_TRIGGER, self.noise, VOL_BASE, ATTEN_NORM);
-               UpdateCSQCProjectile(self.owner);
-       }
-}
-
-void spawnfunc_trigger_gravity()
-{
-       if(self.gravity == 1)
-               return;
-
-       EXACTTRIGGER_INIT;
-       self.touch = trigger_gravity_touch;
-       if(self.noise != "")
-               precache_sound(self.noise);
-
-       self.state = true;
-       IFTARGETED
-       {
-               self.use = trigger_gravity_use;
-               if(self.spawnflags & 2)
-                       self.state = false;
-       }
-}
-
-//=============================================================================
-
-// TODO add a way to do looped sounds with sound(); then complete this entity
-void target_speaker_use_activator()
-{
-       if (!IS_REAL_CLIENT(activator))
-               return;
-       string snd;
-       if(substring(self.noise, 0, 1) == "*")
-       {
-               var .string sample;
-               sample = GetVoiceMessageSampleField(substring(self.noise, 1, -1));
-               if(GetPlayerSoundSampleField_notFound)
-                       snd = "misc/null.wav";
-               else if(activator.sample == "")
-                       snd = "misc/null.wav";
-               else
-               {
-                       tokenize_console(activator.sample);
-                       float n;
-                       n = stof(argv(1));
-                       if(n > 0)
-                               snd = strcat(argv(0), ftos(floor(random() * n + 1)), ".wav"); // randomization
-                       else
-                               snd = strcat(argv(0), ".wav"); // randomization
-               }
-       }
-       else
-               snd = self.noise;
-       msg_entity = activator;
-       soundto(MSG_ONE, self, CH_TRIGGER, snd, VOL_BASE * self.volume, self.atten);
-}
-void target_speaker_use_on()
-{
-       string snd;
-       if(substring(self.noise, 0, 1) == "*")
-       {
-               var .string sample;
-               sample = GetVoiceMessageSampleField(substring(self.noise, 1, -1));
-               if(GetPlayerSoundSampleField_notFound)
-                       snd = "misc/null.wav";
-               else if(activator.sample == "")
-                       snd = "misc/null.wav";
-               else
-               {
-                       tokenize_console(activator.sample);
-                       float n;
-                       n = stof(argv(1));
-                       if(n > 0)
-                               snd = strcat(argv(0), ftos(floor(random() * n + 1)), ".wav"); // randomization
-                       else
-                               snd = strcat(argv(0), ".wav"); // randomization
-               }
-       }
-       else
-               snd = self.noise;
-       sound(self, CH_TRIGGER_SINGLE, snd, VOL_BASE * self.volume, self.atten);
-       if(self.spawnflags & 3)
-               self.use = target_speaker_use_off;
-}
-void target_speaker_use_off()
-{
-       sound(self, CH_TRIGGER_SINGLE, "misc/null.wav", VOL_BASE * self.volume, self.atten);
-       self.use = target_speaker_use_on;
-}
-void target_speaker_reset()
-{
-       if(self.spawnflags & 1) // LOOPED_ON
-       {
-               if(self.use == target_speaker_use_on)
-                       target_speaker_use_on();
-       }
-       else if(self.spawnflags & 2)
-       {
-               if(self.use == target_speaker_use_off)
-                       target_speaker_use_off();
-       }
-}
-
-void spawnfunc_target_speaker()
-{
-       // TODO: "*" prefix to sound file name
-       // TODO: wait and random (just, HOW? random is not a field)
-       if(self.noise)
-               precache_sound (self.noise);
-
-       if(!self.atten && !(self.spawnflags & 4))
-       {
-               IFTARGETED
-                       self.atten = ATTEN_NORM;
-               else
-                       self.atten = ATTEN_STATIC;
-       }
-       else if(self.atten < 0)
-               self.atten = 0;
-
-       if(!self.volume)
-               self.volume = 1;
-
-       IFTARGETED
-       {
-               if(self.spawnflags & 8) // ACTIVATOR
-                       self.use = target_speaker_use_activator;
-               else if(self.spawnflags & 1) // LOOPED_ON
-               {
-                       target_speaker_use_on();
-                       self.reset = target_speaker_reset;
-               }
-               else if(self.spawnflags & 2) // LOOPED_OFF
-               {
-                       self.use = target_speaker_use_on;
-                       self.reset = target_speaker_reset;
-               }
-               else
-                       self.use = target_speaker_use_on;
-       }
-       else if(self.spawnflags & 1) // LOOPED_ON
-       {
-               ambientsound (self.origin, self.noise, VOL_BASE * self.volume, self.atten);
-               remove(self);
-       }
-       else if(self.spawnflags & 2) // LOOPED_OFF
-       {
-               objerror("This sound entity can never be activated");
-       }
-       else
-       {
-               // Quake/Nexuiz fallback
-               ambientsound (self.origin, self.noise, VOL_BASE * self.volume, self.atten);
-               remove(self);
-       }
-}
-
-
-void spawnfunc_func_stardust() {
-       self.effects = EF_STARDUST;
-}
-
-float pointparticles_SendEntity(entity to, float fl)
-{
-       WriteByte(MSG_ENTITY, ENT_CLIENT_POINTPARTICLES);
-
-       // optional features to save space
-       fl = fl & 0x0F;
-       if(self.spawnflags & 2)
-               fl |= 0x10; // absolute count on toggle-on
-       if(self.movedir != '0 0 0' || self.velocity != '0 0 0')
-               fl |= 0x20; // 4 bytes - saves CPU
-       if(self.waterlevel || self.count != 1)
-               fl |= 0x40; // 4 bytes - obscure features almost never used
-       if(self.mins != '0 0 0' || self.maxs != '0 0 0')
-               fl |= 0x80; // 14 bytes - saves lots of space
-
-       WriteByte(MSG_ENTITY, fl);
-       if(fl & 2)
-       {
-               if(self.state)
-                       WriteCoord(MSG_ENTITY, self.impulse);
-               else
-                       WriteCoord(MSG_ENTITY, 0); // off
-       }
-       if(fl & 4)
-       {
-               WriteCoord(MSG_ENTITY, self.origin.x);
-               WriteCoord(MSG_ENTITY, self.origin.y);
-               WriteCoord(MSG_ENTITY, self.origin.z);
-       }
-       if(fl & 1)
-       {
-               if(self.model != "null")
-               {
-                       WriteShort(MSG_ENTITY, self.modelindex);
-                       if(fl & 0x80)
-                       {
-                               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);
-                       }
-               }
-               else
-               {
-                       WriteShort(MSG_ENTITY, 0);
-                       if(fl & 0x80)
-                       {
-                               WriteCoord(MSG_ENTITY, self.maxs.x);
-                               WriteCoord(MSG_ENTITY, self.maxs.y);
-                               WriteCoord(MSG_ENTITY, self.maxs.z);
-                       }
-               }
-               WriteShort(MSG_ENTITY, self.cnt);
-               if(fl & 0x20)
-               {
-                       WriteShort(MSG_ENTITY, compressShortVector(self.velocity));
-                       WriteShort(MSG_ENTITY, compressShortVector(self.movedir));
-               }
-               if(fl & 0x40)
-               {
-                       WriteShort(MSG_ENTITY, self.waterlevel * 16.0);
-                       WriteByte(MSG_ENTITY, self.count * 16.0);
-               }
-               WriteString(MSG_ENTITY, self.noise);
-               if(self.noise != "")
-               {
-                       WriteByte(MSG_ENTITY, floor(self.atten * 64));
-                       WriteByte(MSG_ENTITY, floor(self.volume * 255));
-               }
-               WriteString(MSG_ENTITY, self.bgmscript);
-               if(self.bgmscript != "")
-               {
-                       WriteByte(MSG_ENTITY, floor(self.bgmscriptattack * 64));
-                       WriteByte(MSG_ENTITY, floor(self.bgmscriptdecay * 64));
-                       WriteByte(MSG_ENTITY, floor(self.bgmscriptsustain * 255));
-                       WriteByte(MSG_ENTITY, floor(self.bgmscriptrelease * 64));
-               }
-       }
-       return 1;
-}
-
-void pointparticles_use()
-{
-       self.state = !self.state;
-       self.SendFlags |= 2;
-}
-
-void pointparticles_think()
-{
-       if(self.origin != self.oldorigin)
-       {
-               self.SendFlags |= 4;
-               self.oldorigin = self.origin;
-       }
-       self.nextthink = time;
-}
-
-void pointparticles_reset()
-{
-       if(self.spawnflags & 1)
-               self.state = 1;
-       else
-               self.state = 0;
-}
-
-void spawnfunc_func_pointparticles()
-{
-       if(self.model != "")
-               setmodel(self, self.model);
-       if(self.noise != "")
-               precache_sound (self.noise);
-
-       if(!self.bgmscriptsustain)
-               self.bgmscriptsustain = 1;
-       else if(self.bgmscriptsustain < 0)
-               self.bgmscriptsustain = 0;
-
-       if(!self.atten)
-               self.atten = ATTEN_NORM;
-       else if(self.atten < 0)
-               self.atten = 0;
-       if(!self.volume)
-               self.volume = 1;
-       if(!self.count)
-               self.count = 1;
-       if(!self.impulse)
-               self.impulse = 1;
-
-       if(!self.modelindex)
-       {
-               setorigin(self, self.origin + self.mins);
-               setsize(self, '0 0 0', self.maxs - self.mins);
-       }
-       if(!self.cnt)
-               self.cnt = particleeffectnum(self.mdl);
-
-       Net_LinkEntity(self, (self.spawnflags & 4), 0, pointparticles_SendEntity);
-
-       IFTARGETED
-       {
-               self.use = pointparticles_use;
-               self.reset = pointparticles_reset;
-               self.reset();
-       }
-       else
-               self.state = 1;
-       self.think = pointparticles_think;
-       self.nextthink = time;
-}
-
-void spawnfunc_func_sparks()
-{
-       // self.cnt is the amount of sparks that one burst will spawn
-       if(self.cnt < 1) {
-               self.cnt = 25.0; // nice default value
-       }
-
-       // self.wait is the probability that a sparkthink will spawn a spark shower
-       // range: 0 - 1, but 0 makes little sense, so...
-       if(self.wait < 0.05) {
-               self.wait = 0.25; // nice default value
-       }
-
-       self.count = self.cnt;
-       self.mins = '0 0 0';
-       self.maxs = '0 0 0';
-       self.velocity = '0 0 -1';
-       self.mdl = "TE_SPARK";
-       self.impulse = 10 * self.wait; // by default 2.5/sec
-       self.wait = 0;
-       self.cnt = 0; // use mdl
-
-       spawnfunc_func_pointparticles();
-}
-
-float rainsnow_SendEntity(entity to, float sf)
-{
-       WriteByte(MSG_ENTITY, ENT_CLIENT_RAINSNOW);
-       WriteByte(MSG_ENTITY, self.state);
-       WriteCoord(MSG_ENTITY, self.origin.x + self.mins.x);
-       WriteCoord(MSG_ENTITY, self.origin.y + self.mins.y);
-       WriteCoord(MSG_ENTITY, self.origin.z + self.mins.z);
-       WriteCoord(MSG_ENTITY, self.maxs.x - self.mins.x);
-       WriteCoord(MSG_ENTITY, self.maxs.y - self.mins.y);
-       WriteCoord(MSG_ENTITY, self.maxs.z - self.mins.z);
-       WriteShort(MSG_ENTITY, compressShortVector(self.dest));
-       WriteShort(MSG_ENTITY, self.count);
-       WriteByte(MSG_ENTITY, self.cnt);
-       return 1;
-}
-
-/*QUAKED spawnfunc_func_rain (0 .5 .8) ?
-This is an invisible area like a trigger, which rain falls inside of.
-
-Keys:
-"velocity"
- falling direction (should be something like '0 0 -700', use the X and Y velocity for wind)
-"cnt"
- sets color of rain (default 12 - white)
-"count"
- adjusts density, this many particles fall every second for a 1024x1024 area, default is 2000
-*/
-void spawnfunc_func_rain()
-{
-       self.dest = self.velocity;
-       self.velocity = '0 0 0';
-       if (!self.dest)
-               self.dest = '0 0 -700';
-       self.angles = '0 0 0';
-       self.movetype = MOVETYPE_NONE;
-       self.solid = SOLID_NOT;
-       SetBrushEntityModel();
-       if (!self.cnt)
-               self.cnt = 12;
-       if (!self.count)
-               self.count = 2000;
-       self.count = 0.01 * self.count * (self.size.x / 1024) * (self.size.y / 1024);
-       if (self.count < 1)
-               self.count = 1;
-       if(self.count > 65535)
-               self.count = 65535;
-
-       self.state = 1; // 1 is rain, 0 is snow
-       self.Version = 1;
-
-       Net_LinkEntity(self, false, 0, rainsnow_SendEntity);
-}
-
-
-/*QUAKED spawnfunc_func_snow (0 .5 .8) ?
-This is an invisible area like a trigger, which snow falls inside of.
-
-Keys:
-"velocity"
- falling direction (should be something like '0 0 -300', use the X and Y velocity for wind)
-"cnt"
- sets color of rain (default 12 - white)
-"count"
- adjusts density, this many particles fall every second for a 1024x1024 area, default is 2000
-*/
-void spawnfunc_func_snow()
-{
-       self.dest = self.velocity;
-       self.velocity = '0 0 0';
-       if (!self.dest)
-               self.dest = '0 0 -300';
-       self.angles = '0 0 0';
-       self.movetype = MOVETYPE_NONE;
-       self.solid = SOLID_NOT;
-       SetBrushEntityModel();
-       if (!self.cnt)
-               self.cnt = 12;
-       if (!self.count)
-               self.count = 2000;
-       self.count = 0.01 * self.count * (self.size.x / 1024) * (self.size.y / 1024);
-       if (self.count < 1)
-               self.count = 1;
-       if(self.count > 65535)
-               self.count = 65535;
-
-       self.state = 0; // 1 is rain, 0 is snow
-       self.Version = 1;
-
-       Net_LinkEntity(self, false, 0, rainsnow_SendEntity);
-}
-
-void misc_laser_aim()
-{
-       vector a;
-       if(self.enemy)
-       {
-               if(self.spawnflags & 2)
-               {
-                       if(self.enemy.origin != self.mangle)
-                       {
-                               self.mangle = self.enemy.origin;
-                               self.SendFlags |= 2;
-                       }
-               }
-               else
-               {
-                       a = vectoangles(self.enemy.origin - self.origin);
-                       a.x = -a.x;
-                       if(a != self.mangle)
-                       {
-                               self.mangle = a;
-                               self.SendFlags |= 2;
-                       }
-               }
-       }
-       else
-       {
-               if(self.angles != self.mangle)
-               {
-                       self.mangle = self.angles;
-                       self.SendFlags |= 2;
-               }
-       }
-       if(self.origin != self.oldorigin)
-       {
-               self.SendFlags |= 1;
-               self.oldorigin = self.origin;
-       }
-}
-
-void misc_laser_init()
-{
-       if(self.target != "")
-               self.enemy = find(world, targetname, self.target);
-}
-
-void misc_laser_think()
-{
-       vector o;
-       entity oldself;
-       entity hitent;
-       vector hitloc;
-
-       self.nextthink = time;
-
-       if(!self.state)
-               return;
-
-       misc_laser_aim();
-
-       if(self.enemy)
-       {
-               o = self.enemy.origin;
-               if (!(self.spawnflags & 2))
-                       o = self.origin + normalize(o - self.origin) * 32768;
-       }
-       else
-       {
-               makevectors(self.mangle);
-               o = self.origin + v_forward * 32768;
-       }
-
-       if(self.dmg || self.enemy.target != "")
-       {
-               traceline(self.origin, o, MOVE_NORMAL, self);
-       }
-       hitent = trace_ent;
-       hitloc = trace_endpos;
-
-       if(self.enemy.target != "") // DETECTOR laser
-       {
-               if(trace_ent.iscreature)
-               {
-                       self.pusher = hitent;
-                       if(!self.count)
-                       {
-                               self.count = 1;
-
-                               oldself = self;
-                               self = self.enemy;
-                               activator = self.pusher;
-                               SUB_UseTargets();
-                               self = oldself;
-                       }
-               }
-               else
-               {
-                       if(self.count)
-                       {
-                               self.count = 0;
-
-                               oldself = self;
-                               self = self.enemy;
-                               activator = self.pusher;
-                               SUB_UseTargets();
-                               self = oldself;
-                       }
-               }
-       }
-
-       if(self.dmg)
-       {
-               if(self.team)
-                       if(((self.spawnflags & 8) == 0) == (self.team != hitent.team))
-                               return;
-               if(hitent.takedamage)
-                       Damage(hitent, self, self, ((self.dmg < 0) ? 100000 : (self.dmg * frametime)), DEATH_HURTTRIGGER, hitloc, '0 0 0');
-       }
-}
-
-float laser_SendEntity(entity to, float fl)
-{
-       WriteByte(MSG_ENTITY, ENT_CLIENT_LASER);
-       fl = fl - (fl & 0xF0); // use that bit to indicate finite length laser
-       if(self.spawnflags & 2)
-               fl |= 0x80;
-       if(self.alpha)
-               fl |= 0x40;
-       if(self.scale != 1 || self.modelscale != 1)
-               fl |= 0x20;
-       if(self.spawnflags & 4)
-               fl |= 0x10;
-       WriteByte(MSG_ENTITY, fl);
-       if(fl & 1)
-       {
-               WriteCoord(MSG_ENTITY, self.origin.x);
-               WriteCoord(MSG_ENTITY, self.origin.y);
-               WriteCoord(MSG_ENTITY, self.origin.z);
-       }
-       if(fl & 8)
-       {
-               WriteByte(MSG_ENTITY, self.colormod.x * 255.0);
-               WriteByte(MSG_ENTITY, self.colormod.y * 255.0);
-               WriteByte(MSG_ENTITY, self.colormod.z * 255.0);
-               if(fl & 0x40)
-                       WriteByte(MSG_ENTITY, self.alpha * 255.0);
-               if(fl & 0x20)
-               {
-                       WriteByte(MSG_ENTITY, bound(0, self.scale * 16.0, 255));
-                       WriteByte(MSG_ENTITY, bound(0, self.modelscale * 16.0, 255));
-               }
-               if((fl & 0x80) || !(fl & 0x10)) // effect doesn't need sending if the laser is infinite and has collision testing turned off
-                       WriteShort(MSG_ENTITY, self.cnt + 1);
-       }
-       if(fl & 2)
-       {
-               if(fl & 0x80)
-               {
-                       WriteCoord(MSG_ENTITY, self.enemy.origin.x);
-                       WriteCoord(MSG_ENTITY, self.enemy.origin.y);
-                       WriteCoord(MSG_ENTITY, self.enemy.origin.z);
-               }
-               else
-               {
-                       WriteAngle(MSG_ENTITY, self.mangle.x);
-                       WriteAngle(MSG_ENTITY, self.mangle.y);
-               }
-       }
-       if(fl & 4)
-               WriteByte(MSG_ENTITY, self.state);
-       return 1;
-}
-
-/*QUAKED spawnfunc_misc_laser (.5 .5 .5) ? START_ON DEST_IS_FIXED
-Any object touching the beam will be hurt
-Keys:
-"target"
- spawnfunc_target_position where the laser ends
-"mdl"
- name of beam end effect to use
-"colormod"
- color of the beam (default: red)
-"dmg"
- damage per second (-1 for a laser that kills immediately)
-*/
-void laser_use()
-{
-       self.state = !self.state;
-       self.SendFlags |= 4;
-       misc_laser_aim();
-}
-
-void laser_reset()
-{
-       if(self.spawnflags & 1)
-               self.state = 1;
-       else
-               self.state = 0;
-}
-
-void spawnfunc_misc_laser()
-{
-       if(self.mdl)
-       {
-               if(self.mdl == "none")
-                       self.cnt = -1;
-               else
-               {
-                       self.cnt = particleeffectnum(self.mdl);
-                       if(self.cnt < 0)
-                               if(self.dmg)
-                                       self.cnt = particleeffectnum("laser_deadly");
-               }
-       }
-       else if(!self.cnt)
-       {
-               if(self.dmg)
-                       self.cnt = particleeffectnum("laser_deadly");
-               else
-                       self.cnt = -1;
-       }
-       if(self.cnt < 0)
-               self.cnt = -1;
-
-       if(self.colormod == '0 0 0')
-               if(!self.alpha)
-                       self.colormod = '1 0 0';
-       if(self.message == "")
-               self.message = "saw the light";
-       if (self.message2 == "")
-               self.message2 = "was pushed into a laser by";
-       if(!self.scale)
-               self.scale = 1;
-       if(!self.modelscale)
-               self.modelscale = 1;
-       else if(self.modelscale < 0)
-               self.modelscale = 0;
-       self.think = misc_laser_think;
-       self.nextthink = time;
-       InitializeEntity(self, misc_laser_init, INITPRIO_FINDTARGET);
-
-       self.mangle = self.angles;
-
-       Net_LinkEntity(self, false, 0, laser_SendEntity);
-
-       IFTARGETED
-       {
-               self.reset = laser_reset;
-               laser_reset();
-               self.use = laser_use;
-       }
-       else
-               self.state = 1;
-}
-
-// tZorks trigger impulse / gravity
-
-// targeted (directional) mode
-void trigger_impulse_touch1()
-{
-       entity targ;
-    float pushdeltatime;
-    float str;
-
-       if (self.active != ACTIVE_ACTIVE)
-               return;
-
-       if (!isPushable(other))
-               return;
-
-       EXACTTRIGGER_TOUCH;
-
-    targ = find(world, targetname, self.target);
-    if(!targ)
-    {
-        objerror("trigger_force without a (valid) .target!\n");
-        remove(self);
-        return;
-    }
-
-    str = min(self.radius, vlen(self.origin - other.origin));
-
-    if(self.falloff == 1)
-        str = (str / self.radius) * self.strength;
-    else if(self.falloff == 2)
-        str = (1 - (str / self.radius)) * self.strength;
-    else
-        str = self.strength;
-
-    pushdeltatime = time - other.lastpushtime;
-    if (pushdeltatime > 0.15) pushdeltatime = 0;
-    other.lastpushtime = time;
-    if(!pushdeltatime) return;
-
-    other.velocity = other.velocity + normalize(targ.origin - self.origin) * str * pushdeltatime;
-    other.flags &= ~FL_ONGROUND;
-    UpdateCSQCProjectile(other);
-}
-
-// Directionless (accelerator/decelerator) mode
-void trigger_impulse_touch2()
-{
-    float pushdeltatime;
-
-       if (self.active != ACTIVE_ACTIVE)
-               return;
-
-       if (!isPushable(other))
-               return;
-
-       EXACTTRIGGER_TOUCH;
-
-    pushdeltatime = time - other.lastpushtime;
-    if (pushdeltatime > 0.15) pushdeltatime = 0;
-    other.lastpushtime = time;
-    if(!pushdeltatime) return;
-
-    // div0: ticrate independent, 1 = identity (not 20)
-    other.velocity = other.velocity * pow(self.strength, pushdeltatime);
-    UpdateCSQCProjectile(other);
-}
-
-// Spherical (gravity/repulsor) mode
-void trigger_impulse_touch3()
-{
-    float pushdeltatime;
-    float str;
-
-       if (self.active != ACTIVE_ACTIVE)
-               return;
-
-       if (!isPushable(other))
-               return;
-
-       EXACTTRIGGER_TOUCH;
-
-    pushdeltatime = time - other.lastpushtime;
-    if (pushdeltatime > 0.15) pushdeltatime = 0;
-    other.lastpushtime = time;
-    if(!pushdeltatime) return;
-
-    setsize(self, '-1 -1 -1' * self.radius,'1 1 1' * self.radius);
-
-       str = min(self.radius, vlen(self.origin - other.origin));
-
-    if(self.falloff == 1)
-        str = (1 - str / self.radius) * self.strength; // 1 in the inside
-    else if(self.falloff == 2)
-        str = (str / self.radius) * self.strength; // 0 in the inside
-    else
-        str = self.strength;
-
-    other.velocity = other.velocity + normalize(other.origin - self.origin) * str * pushdeltatime;
-    UpdateCSQCProjectile(other);
-}
-
-/*QUAKED spawnfunc_trigger_impulse (.5 .5 .5) ?
--------- KEYS --------
-target : If this is set, this points to the spawnfunc_target_position to which the player will get pushed.
-         If not, this trigger acts like a damper/accelerator field.
-
-strength : This is how mutch force to add in the direction of .target each second
-           when .target is set. If not, this is hoe mutch to slow down/accelerate
-           someting cought inside this trigger. (1=no change, 0,5 half speed rougthly each tic, 2 = doubble)
-
-radius   : If set, act as a spherical device rather then a liniar one.
-
-falloff : 0 = none, 1 = liniar, 2 = inverted liniar
-
--------- NOTES --------
-Use a brush textured with common/origin in the trigger entity to determine the origin of the force
-in directional and sperical mode. For damper/accelerator mode this is not nessesary (and has no effect).
-*/
-
-void spawnfunc_trigger_impulse()
-{
-       self.active = ACTIVE_ACTIVE;
-
-       EXACTTRIGGER_INIT;
-    if(self.radius)
-    {
-        if(!self.strength) self.strength = 2000 * autocvar_g_triggerimpulse_radial_multiplier;
-        setorigin(self, self.origin);
-        setsize(self, '-1 -1 -1' * self.radius,'1 1 1' * self.radius);
-        self.touch = trigger_impulse_touch3;
-    }
-    else
-    {
-        if(self.target)
-        {
-            if(!self.strength) self.strength = 950 * autocvar_g_triggerimpulse_directional_multiplier;
-            self.touch = trigger_impulse_touch1;
-        }
-        else
-        {
-            if(!self.strength) self.strength = 0.9;
-                       self.strength = pow(self.strength, autocvar_g_triggerimpulse_accel_power) * autocvar_g_triggerimpulse_accel_multiplier;
-            self.touch = trigger_impulse_touch2;
-        }
-    }
-}
-
-/*QUAKED spawnfunc_trigger_flipflop (.5 .5 .5) (-8 -8 -8) (8 8 8) START_ENABLED
-"Flip-flop" trigger gate... lets only every second trigger event through
-*/
-void flipflop_use()
-{
-       self.state = !self.state;
-       if(self.state)
-               SUB_UseTargets();
-}
-
-void spawnfunc_trigger_flipflop()
-{
-       if(self.spawnflags & 1)
-               self.state = 1;
-       self.use = flipflop_use;
-       self.reset = spawnfunc_trigger_flipflop; // perfect resetter
-}
-
-/*QUAKED spawnfunc_trigger_monoflop (.5 .5 .5) (-8 -8 -8) (8 8 8)
-"Mono-flop" trigger gate... turns one trigger event into one "on" and one "off" event, separated by a delay of "wait"
-*/
-void monoflop_use()
-{
-       self.nextthink = time + self.wait;
-       self.enemy = activator;
-       if(self.state)
-               return;
-       self.state = 1;
-       SUB_UseTargets();
-}
-void monoflop_fixed_use()
-{
-       if(self.state)
-               return;
-       self.nextthink = time + self.wait;
-       self.state = 1;
-       self.enemy = activator;
-       SUB_UseTargets();
-}
-
-void monoflop_think()
-{
-       self.state = 0;
-       activator = self.enemy;
-       SUB_UseTargets();
-}
-
-void monoflop_reset()
-{
-       self.state = 0;
-       self.nextthink = 0;
-}
-
-void spawnfunc_trigger_monoflop()
-{
-       if(!self.wait)
-               self.wait = 1;
-       if(self.spawnflags & 1)
-               self.use = monoflop_fixed_use;
-       else
-               self.use = monoflop_use;
-       self.think = monoflop_think;
-       self.state = 0;
-       self.reset = monoflop_reset;
-}
-
-void multivibrator_send()
-{
-       float newstate;
-       float cyclestart;
-
-       cyclestart = floor((time + self.phase) / (self.wait + self.respawntime)) * (self.wait + self.respawntime) - self.phase;
-
-       newstate = (time < cyclestart + self.wait);
-
-       activator = self;
-       if(self.state != newstate)
-               SUB_UseTargets();
-       self.state = newstate;
-
-       if(self.state)
-               self.nextthink = cyclestart + self.wait + 0.01;
-       else
-               self.nextthink = cyclestart + self.wait + self.respawntime + 0.01;
-}
-
-void multivibrator_toggle()
-{
-       if(self.nextthink == 0)
-       {
-               multivibrator_send();
-       }
-       else
-       {
-               if(self.state)
-               {
-                       SUB_UseTargets();
-                       self.state = 0;
-               }
-               self.nextthink = 0;
-       }
-}
-
-void multivibrator_reset()
-{
-       if(!(self.spawnflags & 1))
-               self.nextthink = 0; // wait for a trigger event
-       else
-               self.nextthink = max(1, time);
-}
-
-/*QUAKED trigger_multivibrator (.5 .5 .5) (-8 -8 -8) (8 8 8) START_ON
-"Multivibrator" trigger gate... repeatedly sends trigger events. When triggered, turns on or off.
--------- KEYS --------
-target: trigger all entities with this targetname when it goes off
-targetname: name that identifies this entity so it can be triggered; when off, it always uses the OFF state
-phase: offset of the timing
-wait: "on" cycle time (default: 1)
-respawntime: "off" cycle time (default: same as wait)
--------- SPAWNFLAGS --------
-START_ON: assume it is already turned on (when targeted)
-*/
-void spawnfunc_trigger_multivibrator()
-{
-       if(!self.wait)
-               self.wait = 1;
-       if(!self.respawntime)
-               self.respawntime = self.wait;
-
-       self.state = 0;
-       self.use = multivibrator_toggle;
-       self.think = multivibrator_send;
-       self.nextthink = max(1, time);
-
-       IFTARGETED
-               multivibrator_reset();
-}
-
-
-void follow_init()
-{
-       entity src, dst;
-       src = world;
-       dst = world;
-       if(self.killtarget != "")
-               src = find(world, targetname, self.killtarget);
-       if(self.target != "")
-               dst = find(world, targetname, self.target);
-
-       if(!src && !dst)
-       {
-               objerror("follow: could not find target/killtarget");
-               return;
-       }
-
-       if(self.jointtype)
-       {
-               // already done :P entity must stay
-               self.aiment = src;
-               self.enemy = dst;
-       }
-       else if(!src || !dst)
-       {
-               objerror("follow: could not find target/killtarget");
-               return;
-       }
-       else if(self.spawnflags & 1)
-       {
-               // attach
-               if(self.spawnflags & 2)
-               {
-                       setattachment(dst, src, self.message);
-               }
-               else
-               {
-                       attach_sameorigin(dst, src, self.message);
-               }
-
-               dst.solid = SOLID_NOT; // solid doesn't work with attachment
-               remove(self);
-       }
-       else
-       {
-               if(self.spawnflags & 2)
-               {
-                       dst.movetype = MOVETYPE_FOLLOW;
-                       dst.aiment = src;
-                       // dst.punchangle = '0 0 0'; // keep unchanged
-                       dst.view_ofs = dst.origin;
-                       dst.v_angle = dst.angles;
-               }
-               else
-               {
-                       follow_sameorigin(dst, src);
-               }
-
-               remove(self);
-       }
-}
-
-void spawnfunc_misc_follow()
-{
-       InitializeEntity(self, follow_init, INITPRIO_FINDTARGET);
-}
-
-
-
-void gamestart_use() {
-       activator = self;
-       SUB_UseTargets();
-       remove(self);
-}
-
-void spawnfunc_trigger_gamestart() {
-       self.use = gamestart_use;
-       self.reset2 = spawnfunc_trigger_gamestart;
-
-       if(self.wait)
-       {
-               self.think = self.use;
-               self.nextthink = game_starttime + self.wait;
-       }
-       else
-               InitializeEntity(self, gamestart_use, INITPRIO_FINDTARGET);
-}
-
-
-
-
-void target_voicescript_clear(entity pl)
-{
-       pl.voicescript = world;
-}
-
-void target_voicescript_use()
-{
-       if(activator.voicescript != self)
-       {
-               activator.voicescript = self;
-               activator.voicescript_index = 0;
-               activator.voicescript_nextthink = time + self.delay;
-       }
-}
-
-void target_voicescript_next(entity pl)
-{
-       entity vs;
-       float i, n, dt;
-
-       vs = pl.voicescript;
-       if(!vs)
-               return;
-       if(vs.message == "")
-               return;
-       if (!IS_PLAYER(pl))
-               return;
-       if(gameover)
-               return;
-
-       if(time >= pl.voicescript_voiceend)
-       {
-               if(time >= pl.voicescript_nextthink)
-               {
-                       // get the next voice...
-                       n = tokenize_console(vs.message);
-
-                       if(pl.voicescript_index < vs.cnt)
-                               i = pl.voicescript_index * 2;
-                       else if(n > vs.cnt * 2)
-                               i = ((pl.voicescript_index - vs.cnt) % ((n - vs.cnt * 2 - 1) / 2)) * 2 + vs.cnt * 2 + 1;
-                       else
-                               i = -1;
-
-                       if(i >= 0)
-                       {
-                               play2(pl, strcat(vs.netname, "/", argv(i), ".wav"));
-                               dt = stof(argv(i + 1));
-                               if(dt >= 0)
-                               {
-                                       pl.voicescript_voiceend = time + dt;
-                                       pl.voicescript_nextthink = pl.voicescript_voiceend + vs.wait * (0.5 + random());
-                               }
-                               else
-                               {
-                                       pl.voicescript_voiceend = time - dt;
-                                       pl.voicescript_nextthink = pl.voicescript_voiceend;
-                               }
-
-                               pl.voicescript_index += 1;
-                       }
-                       else
-                       {
-                               pl.voicescript = world; // stop trying then
-                       }
-               }
-       }
-}
-
-void spawnfunc_target_voicescript()
-{
-       // netname: directory of the sound files
-       // message: list of "sound file" duration "sound file" duration, a *, and again a list
-       //          foo1 4.1 foo2 4.0 foo3 -3.1 * fool1 1.1 fool2 7.1 fool3 9.1 fool4 3.7
-       //          Here, a - in front of the duration means that no delay is to be
-       //          added after this message
-       // wait: average time between messages
-       // delay: initial delay before the first message
-
-       float i, n;
-       self.use = target_voicescript_use;
-
-       n = tokenize_console(self.message);
-       self.cnt = n / 2;
-       for(i = 0; i+1 < n; i += 2)
-       {
-               if(argv(i) == "*")
-               {
-                       self.cnt = i / 2;
-                       ++i;
-               }
-               precache_sound(strcat(self.netname, "/", argv(i), ".wav"));
-       }
-}
-
-
-
-void trigger_relay_teamcheck_use()
-{
-       if(activator.team)
-       {
-               if(self.spawnflags & 2)
-               {
-                       if(activator.team != self.team)
-                               SUB_UseTargets();
-               }
-               else
-               {
-                       if(activator.team == self.team)
-                               SUB_UseTargets();
-               }
-       }
-       else
-       {
-               if(self.spawnflags & 1)
-                       SUB_UseTargets();
-       }
-}
-
-void trigger_relay_teamcheck_reset()
-{
-       self.team = self.team_saved;
-}
-
-void spawnfunc_trigger_relay_teamcheck()
-{
-       self.team_saved = self.team;
-       self.use = trigger_relay_teamcheck_use;
-       self.reset = trigger_relay_teamcheck_reset;
-}
-
-
-
-void trigger_disablerelay_use()
-{
-       entity e;
-
-       float a, b;
-       a = b = 0;
-
-       for(e = world; (e = find(e, targetname, self.target)); )
-       {
-               if(e.use == SUB_UseTargets)
-               {
-                       e.use = SUB_DontUseTargets;
-                       ++a;
-               }
-               else if(e.use == SUB_DontUseTargets)
-               {
-                       e.use = SUB_UseTargets;
-                       ++b;
-               }
-       }
-
-       if((!a) == (!b))
-               print("Invalid use of trigger_disablerelay: ", ftos(a), " relays were on, ", ftos(b), " relays were off!\n");
-}
-
-void spawnfunc_trigger_disablerelay()
-{
-       self.use = trigger_disablerelay_use;
-}
-
-string trigger_magicear_processmessage(entity ear, entity source, float teamsay, entity privatesay, string msgin)
-{
-       float domatch, dotrigger, matchstart, l;
-       string s, msg;
-       entity oldself;
-       string savemessage;
-
-       magicear_matched = false;
-
-       dotrigger = ((IS_PLAYER(source)) && (source.deadflag == DEAD_NO) && ((ear.radius == 0) || (vlen(source.origin - ear.origin) <= ear.radius)));
-       domatch = ((ear.spawnflags & 32) || dotrigger);
-
-       if (!domatch)
-               return msgin;
-
-       if (!msgin)
-       {
-               // we are in TUBA mode!
-               if (!(ear.spawnflags & 256))
-                       return msgin;
-
-               if(!W_Tuba_HasPlayed(source, ear.message, ear.movedir.x, !(ear.spawnflags & 512), ear.movedir.y, ear.movedir.z))
-                       return msgin;
-
-               magicear_matched = true;
-
-               if(dotrigger)
-               {
-                       oldself = self;
-                       activator = source;
-                       self = ear;
-                       savemessage = self.message;
-                       self.message = string_null;
-                       SUB_UseTargets();
-                       self.message = savemessage;
-                       self = oldself;
-               }
-
-               if(ear.netname != "")
-                       return ear.netname;
-
-               return msgin;
-       }
-
-       if(ear.spawnflags & 256) // ENOTUBA
-               return msgin;
-
-       if(privatesay)
-       {
-               if(ear.spawnflags & 4)
-                       return msgin;
-       }
-       else
-       {
-               if(!teamsay)
-                       if(ear.spawnflags & 1)
-                               return msgin;
-               if(teamsay > 0)
-                       if(ear.spawnflags & 2)
-                               return msgin;
-               if(teamsay < 0)
-                       if(ear.spawnflags & 8)
-                               return msgin;
-       }
-
-       matchstart = -1;
-       l = strlen(ear.message);
-
-       if(ear.spawnflags & 128)
-               msg = msgin;
-       else
-               msg = strdecolorize(msgin);
-
-       if(substring(ear.message, 0, 1) == "*")
-       {
-               if(substring(ear.message, -1, 1) == "*")
-               {
-                       // two wildcards
-                       // as we need multi-replacement here...
-                       s = substring(ear.message, 1, -2);
-                       l -= 2;
-                       if(strstrofs(msg, s, 0) >= 0)
-                               matchstart = -2; // we use strreplace on s
-               }
-               else
-               {
-                       // match at start
-                       s = substring(ear.message, 1, -1);
-                       l -= 1;
-                       if(substring(msg, -l, l) == s)
-                               matchstart = strlen(msg) - l;
-               }
-       }
-       else
-       {
-               if(substring(ear.message, -1, 1) == "*")
-               {
-                       // match at end
-                       s = substring(ear.message, 0, -2);
-                       l -= 1;
-                       if(substring(msg, 0, l) == s)
-                               matchstart = 0;
-               }
-               else
-               {
-                       // full match
-                       s = ear.message;
-                       if(msg == ear.message)
-                               matchstart = 0;
-               }
-       }
-
-       if(matchstart == -1) // no match
-               return msgin;
-
-       magicear_matched = true;
-
-       if(dotrigger)
-       {
-               oldself = self;
-               activator = source;
-               self = ear;
-               savemessage = self.message;
-               self.message = string_null;
-               SUB_UseTargets();
-               self.message = savemessage;
-               self = oldself;
-       }
-
-       if(ear.spawnflags & 16)
-       {
-               return ear.netname;
-       }
-       else if(ear.netname != "")
-       {
-               if(matchstart < 0)
-                       return strreplace(s, ear.netname, msg);
-               else
-                       return strcat(
-                               substring(msg, 0, matchstart),
-                               ear.netname,
-                               substring(msg, matchstart + l, -1)
-                       );
-       }
-       else
-               return msgin;
-}
-
-string trigger_magicear_processmessage_forallears(entity source, float teamsay, entity privatesay, string msgin)
-{
-       entity ear;
-       string msgout;
-       for(ear = magicears; ear; ear = ear.enemy)
-       {
-               msgout = trigger_magicear_processmessage(ear, source, teamsay, privatesay, msgin);
-               if(!(ear.spawnflags & 64))
-               if(magicear_matched)
-                       return msgout;
-               msgin = msgout;
-       }
-       return msgin;
-}
-
-void spawnfunc_trigger_magicear()
-{
-       self.enemy = magicears;
-       magicears = self;
-
-       // actually handled in "say" processing
-       // spawnflags:
-       //    1 = ignore say
-       //    2 = ignore teamsay
-       //    4 = ignore tell
-       //    8 = ignore tell to unknown player
-       //   16 = let netname replace the whole message (otherwise, netname is a word replacement if set)
-       //   32 = perform the replacement even if outside the radius or dead
-       //   64 = continue replacing/triggering even if this one matched
-       //  128 = don't decolorize message before matching
-       //  256 = message is a tuba note sequence (pitch.duration pitch.duration ...)
-       //  512 = tuba notes must be exact right pitch, no transposing
-       // message: either
-       //   *pattern*
-       // or
-       //   *pattern
-       // or
-       //   pattern*
-       // or
-       //   pattern
-       // netname:
-       //   if set, replacement for the matched text
-       // radius:
-       //   "hearing distance"
-       // target:
-       //   what to trigger
-       // movedir:
-       //   for spawnflags 256, defines 'instrument+1 mintempo maxtempo' (zero component doesn't matter)
-
-       self.movedir_x -= 1; // map to tuba instrument numbers
-}
-
-void relay_activators_use()
-{
-       entity trg, os;
-
-       os = self;
-
-       for(trg = world; (trg = find(trg, targetname, os.target)); )
-       {
-               self = trg;
-               if (trg.setactive)
-                       trg.setactive(os.cnt);
-               else
-               {
-                       //bprint("Not using setactive\n");
-                       if(os.cnt == ACTIVE_TOGGLE)
-                               if(trg.active == ACTIVE_ACTIVE)
-                                       trg.active = ACTIVE_NOT;
-                               else
-                                       trg.active = ACTIVE_ACTIVE;
-                       else
-                               trg.active = os.cnt;
-               }
-       }
-       self = os;
-}
-
-void spawnfunc_relay_activate()
-{
-       self.cnt = ACTIVE_ACTIVE;
-       self.use = relay_activators_use;
-}
-
-void spawnfunc_relay_deactivate()
-{
-       self.cnt = ACTIVE_NOT;
-       self.use = relay_activators_use;
-}
-
-void spawnfunc_relay_activatetoggle()
-{
-       self.cnt = ACTIVE_TOGGLE;
-       self.use = relay_activators_use;
-}
-
-void spawnfunc_target_changelevel_use()
-{
-       if(self.gametype != "")
-               MapInfo_SwitchGameType(MapInfo_Type_FromString(self.gametype));
-
-       if (self.chmap == "")
-               localcmd("endmatch\n");
-       else
-               localcmd(strcat("changelevel ", self.chmap, "\n"));
-}
-
-void spawnfunc_target_changelevel()
-{
-       self.use = spawnfunc_target_changelevel_use;
-}
diff --git a/qcsrc/server/g_triggers.qh b/qcsrc/server/g_triggers.qh
deleted file mode 100644 (file)
index 35c39f2..0000000
+++ /dev/null
@@ -1,388 +0,0 @@
-#ifndef G_TRIGGERS_H
-#define G_TRIGGERS_H
-
-void SUB_DontUseTargets();
-
-
-void() SUB_UseTargets;
-
-void DelayThink();
-
-/*
-==============================
-SUB_UseTargets
-
-the global "activator" should be set to the entity that initiated the firing.
-
-If self.delay is set, a DelayedUse entity will be created that will actually
-do the SUB_UseTargets after that many seconds have passed.
-
-Centerprints any self.message to the activator.
-
-Removes all entities with a targetname that match self.killtarget,
-and removes them, so some events can remove other triggers.
-
-Search for (string)targetname in all entities that
-match (string)self.target and call their .use function
-
-==============================
-*/
-void SUB_UseTargets();
-
-
-//=============================================================================
-
-const float    SPAWNFLAG_NOMESSAGE = 1;
-const float    SPAWNFLAG_NOTOUCH = 1;
-
-// the wait time has passed, so set back up for another activation
-void multi_wait();
-
-
-// the trigger was just touched/killed/used
-// self.enemy should be set to the activator so it can be held through a delay
-// so wait for the delay time before firing
-void multi_trigger();
-
-void multi_use();
-
-void multi_touch();
-
-void multi_eventdamage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force);
-
-void multi_reset();
-
-/*QUAKED spawnfunc_trigger_multiple (.5 .5 .5) ? notouch
-Variable sized repeatable trigger.  Must be targeted at one or more entities.  If "health" is set, the trigger must be killed to activate each time.
-If "delay" is set, the trigger waits some time after activating before firing.
-"wait" : Seconds between triggerings. (.2 default)
-If notouch is set, the trigger is only fired by other entities, not by touching.
-NOTOUCH has been obsoleted by spawnfunc_trigger_relay!
-sounds
-1)     secret
-2)     beep beep
-3)     large switch
-4)
-set "message" to text string
-*/
-void spawnfunc_trigger_multiple();
-
-
-/*QUAKED spawnfunc_trigger_once (.5 .5 .5) ? notouch
-Variable sized trigger. Triggers once, then removes itself.  You must set the key "target" to the name of another object in the level that has a matching
-"targetname".  If "health" is set, the trigger must be killed to activate.
-If notouch is set, the trigger is only fired by other entities, not by touching.
-if "killtarget" is set, any objects that have a matching "target" will be removed when the trigger is fired.
-if "angle" is set, the trigger will only fire when someone is facing the direction of the angle.  Use "360" for an angle of 0.
-sounds
-1)     secret
-2)     beep beep
-3)     large switch
-4)
-set "message" to text string
-*/
-void spawnfunc_trigger_once();
-
-//=============================================================================
-
-/*QUAKED spawnfunc_trigger_relay (.5 .5 .5) (-8 -8 -8) (8 8 8)
-This fixed size trigger cannot be touched, it can only be fired by other events.  It can contain killtargets, targets, delays, and messages.
-*/
-void spawnfunc_trigger_relay();
-
-void delay_use();
-
-void delay_reset();
-
-void spawnfunc_trigger_delay();
-
-//=============================================================================
-
-
-void counter_use();
-
-void counter_reset();
-
-/*QUAKED spawnfunc_trigger_counter (.5 .5 .5) ? nomessage
-Acts as an intermediary for an action that takes multiple inputs.
-
-If nomessage is not set, t will print "1 more.. " etc when triggered and "sequence complete" when finished.
-
-After the counter has been triggered "count" times (default 2), it will fire all of it's targets and remove itself.
-*/
-void spawnfunc_trigger_counter();
-
-void trigger_hurt_use();
-
-.float triggerhurttime;
-void trigger_hurt_touch();
-
-/*QUAKED spawnfunc_trigger_hurt (.5 .5 .5) ?
-Any object touching this will be hurt
-set dmg to damage amount
-defalt dmg = 5
-*/
-.entity trigger_hurt_next;
-entity trigger_hurt_last;
-entity trigger_hurt_first;
-void spawnfunc_trigger_hurt();
-
-float tracebox_hits_trigger_hurt(vector start, vector mi, vector ma, vector end);
-
-//////////////////////////////////////////////////////////////
-//
-//
-//
-//Trigger heal --a04191b92fbd93aa67214ef7e72d6d2e
-//
-//////////////////////////////////////////////////////////////
-
-.float triggerhealtime;
-void trigger_heal_touch();
-
-void spawnfunc_trigger_heal();
-
-
-//////////////////////////////////////////////////////////////
-//
-//
-//
-//End trigger_heal
-//
-//////////////////////////////////////////////////////////////
-
-.entity trigger_gravity_check;
-void trigger_gravity_remove(entity own);
-void trigger_gravity_check_think();
-
-void trigger_gravity_use();
-
-void trigger_gravity_touch();
-
-void spawnfunc_trigger_gravity();
-
-//=============================================================================
-
-// TODO add a way to do looped sounds with sound(); then complete this entity
-.float volume, atten;
-void target_speaker_use_off();
-void target_speaker_use_activator();
-void target_speaker_use_on();
-void target_speaker_use_off();
-void target_speaker_reset();
-
-void spawnfunc_target_speaker();
-
-
-void spawnfunc_func_stardust();
-
-.string bgmscript;
-.float bgmscriptattack;
-.float bgmscriptdecay;
-.float bgmscriptsustain;
-.float bgmscriptrelease;
-float pointparticles_SendEntity(entity to, float fl);
-
-void pointparticles_use();
-
-void pointparticles_think();
-
-void pointparticles_reset();
-
-void spawnfunc_func_pointparticles();
-
-void spawnfunc_func_sparks();
-
-float rainsnow_SendEntity(entity to, float sf);
-
-/*QUAKED spawnfunc_func_rain (0 .5 .8) ?
-This is an invisible area like a trigger, which rain falls inside of.
-
-Keys:
-"velocity"
- falling direction (should be something like '0 0 -700', use the X and Y velocity for wind)
-"cnt"
- sets color of rain (default 12 - white)
-"count"
- adjusts density, this many particles fall every second for a 1024x1024 area, default is 2000
-*/
-void spawnfunc_func_rain();
-
-
-/*QUAKED spawnfunc_func_snow (0 .5 .8) ?
-This is an invisible area like a trigger, which snow falls inside of.
-
-Keys:
-"velocity"
- falling direction (should be something like '0 0 -300', use the X and Y velocity for wind)
-"cnt"
- sets color of rain (default 12 - white)
-"count"
- adjusts density, this many particles fall every second for a 1024x1024 area, default is 2000
-*/
-void spawnfunc_func_snow();
-
-.float modelscale;
-void misc_laser_aim();
-
-void misc_laser_init();
-
-.entity pusher;
-void misc_laser_think();
-
-float laser_SendEntity(entity to, float fl);
-
-/*QUAKED spawnfunc_misc_laser (.5 .5 .5) ? START_ON DEST_IS_FIXED
-Any object touching the beam will be hurt
-Keys:
-"target"
- spawnfunc_target_position where the laser ends
-"mdl"
- name of beam end effect to use
-"colormod"
- color of the beam (default: red)
-"dmg"
- damage per second (-1 for a laser that kills immediately)
-*/
-void laser_use();
-
-void laser_reset();
-
-void spawnfunc_misc_laser();
-
-// tZorks trigger impulse / gravity
-.float radius;
-.float falloff;
-.float strength;
-.float lastpushtime;
-
-// targeted (directional) mode
-void trigger_impulse_touch1();
-
-// Directionless (accelerator/decelerator) mode
-void trigger_impulse_touch2();
-
-// Spherical (gravity/repulsor) mode
-void trigger_impulse_touch3();
-
-/*QUAKED spawnfunc_trigger_impulse (.5 .5 .5) ?
--------- KEYS --------
-target : If this is set, this points to the spawnfunc_target_position to which the player will get pushed.
-         If not, this trigger acts like a damper/accelerator field.
-
-strength : This is how mutch force to add in the direction of .target each second
-           when .target is set. If not, this is hoe mutch to slow down/accelerate
-           someting cought inside this trigger. (1=no change, 0,5 half speed rougthly each tic, 2 = doubble)
-
-radius   : If set, act as a spherical device rather then a liniar one.
-
-falloff : 0 = none, 1 = liniar, 2 = inverted liniar
-
--------- NOTES --------
-Use a brush textured with common/origin in the trigger entity to determine the origin of the force
-in directional and sperical mode. For damper/accelerator mode this is not nessesary (and has no effect).
-*/
-
-void spawnfunc_trigger_impulse();
-
-/*QUAKED spawnfunc_trigger_flipflop (.5 .5 .5) (-8 -8 -8) (8 8 8) START_ENABLED
-"Flip-flop" trigger gate... lets only every second trigger event through
-*/
-void flipflop_use();
-
-void spawnfunc_trigger_flipflop();
-
-/*QUAKED spawnfunc_trigger_monoflop (.5 .5 .5) (-8 -8 -8) (8 8 8)
-"Mono-flop" trigger gate... turns one trigger event into one "on" and one "off" event, separated by a delay of "wait"
-*/
-void monoflop_use();
-void monoflop_fixed_use();
-
-void monoflop_think();
-
-void monoflop_reset();
-
-void spawnfunc_trigger_monoflop();
-
-void multivibrator_send();
-
-void multivibrator_toggle();
-
-void multivibrator_reset();
-
-/*QUAKED trigger_multivibrator (.5 .5 .5) (-8 -8 -8) (8 8 8) START_ON
-"Multivibrator" trigger gate... repeatedly sends trigger events. When triggered, turns on or off.
--------- KEYS --------
-target: trigger all entities with this targetname when it goes off
-targetname: name that identifies this entity so it can be triggered; when off, it always uses the OFF state
-phase: offset of the timing
-wait: "on" cycle time (default: 1)
-respawntime: "off" cycle time (default: same as wait)
--------- SPAWNFLAGS --------
-START_ON: assume it is already turned on (when targeted)
-*/
-void spawnfunc_trigger_multivibrator();
-
-
-void follow_init();
-
-void spawnfunc_misc_follow();
-
-
-
-void gamestart_use();
-
-void spawnfunc_trigger_gamestart();
-
-
-
-
-.entity voicescript; // attached voice script
-.float voicescript_index; // index of next voice, or -1 to use the randomized ones
-.float voicescript_nextthink; // time to play next voice
-.float voicescript_voiceend; // time when this voice ends
-
-void target_voicescript_clear(entity pl);
-
-void target_voicescript_use();
-
-void target_voicescript_next(entity pl);
-
-void spawnfunc_target_voicescript();
-
-
-
-void trigger_relay_teamcheck_use();
-
-void trigger_relay_teamcheck_reset();
-
-void spawnfunc_trigger_relay_teamcheck();
-
-
-
-void trigger_disablerelay_use();
-
-void spawnfunc_trigger_disablerelay();
-
-float magicear_matched;
-float W_Tuba_HasPlayed(entity pl, string melody, float instrument, float ignorepitch, float mintempo, float maxtempo);
-string trigger_magicear_processmessage(entity ear, entity source, float teamsay, entity privatesay, string msgin);
-
-entity magicears;
-string trigger_magicear_processmessage_forallears(entity source, float teamsay, entity privatesay, string msgin);
-
-void spawnfunc_trigger_magicear();
-
-void relay_activators_use();
-
-void spawnfunc_relay_activate();
-
-void spawnfunc_relay_deactivate();
-
-void spawnfunc_relay_activatetoggle();
-
-.string chmap, gametype;
-void spawnfunc_target_changelevel_use();
-
-void spawnfunc_target_changelevel();
-#endif
index fdff4a66f369bf8c9e8cf45709e146395ad0f2d7..5bc8aafd377202719e58dd38569a70afedb452c5 100644 (file)
@@ -1,6 +1,7 @@
 #include "g_violence.qh"
+#include "_all.qh"
 
-float Violence_GibSplash_SendEntity(entity to, float sf)
+float Violence_GibSplash_SendEntity(entity to, int sf)
 {
        WriteByte(MSG_ENTITY, ENT_CLIENT_GIBSPLASH);
        WriteByte(MSG_ENTITY, self.state); // actually type
index 1f1df0683a7bfd8ca66b56bc46eb148bcff3bf2b..98d2b811fcd2858cec93686b65fd3e35da9fd7ea 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef G_VIOLENCE_H
 #define G_VIOLENCE_H
 
-float Violence_GibSplash_SendEntity(entity to, float sf);
+float Violence_GibSplash_SendEntity(entity to, int sf);
 
 // TODO maybe convert this to a TE?
 void Violence_GibSplash_At(vector org, vector dir, float type, float amount, entity gibowner, entity attacker);
index 04f8ff7b38afbf7551a2a162bf1153acc043c6cd..9c2003cc19d506afbe5de24d4b7e5adf0c7bdacb 100644 (file)
@@ -1,39 +1,38 @@
 #include "g_world.qh"
-
+#include "_all.qh"
+
+#include "anticheat.qh"
+#include "antilag.qh"
+#include "bot/bot.qh"
+#include "campaign.qh"
+#include "cheats.qh"
+#include "cl_client.qh"
+#include "command/common.qh"
+#include "command/getreplies.qh"
+#include "command/sv_cmd.qh"
+#include "command/vote.qh"
+#include "g_hook.qh"
+#include "ipban.qh"
+#include "mapvoting.qh"
+#include "mutators/mutators_include.qh"
+#include "race.qh"
+#include "scores.qh"
+#include "teamplay.qh"
+#include "waypointsprites.qh"
+#include "weapons/weaponstats.qh"
 #include "../common/buffs.qh"
-
-#if defined(CSQC)
-#elif defined(MENUQC)
-#elif defined(SVQC)
-    #include "../common/constants.qh"
-    #include "../common/stats.qh"
-    #include "../common/teams.qh"
-    #include "../common/util.qh"
-    #include "../common/monsters/sv_monsters.qh"
-    #include "../common/weapons/weapons.qh"
-    #include "weapons/weaponstats.qh"
-    #include "autocvars.qh"
-    #include "constants.qh"
-    #include "defs.qh"
-    #include "../common/notifications.qh"
-    #include "mutators/mutators_include.qh"
-    #include "campaign.qh"
-    #include "../common/mapinfo.qh"
-    #include "command/common.qh"
-    #include "command/vote.qh"
-    #include "command/getreplies.qh"
-    #include "command/sv_cmd.qh"
-    #include "anticheat.qh"
-    #include "cheats.qh"
-    #include "../common/playerstats.qh"
-    #include "g_hook.qh"
-    #include "scores.qh"
-    #include "mapvoting.qh"
-    #include "ipban.qh"
-    #include "race.qh"
-    #include "antilag.qh"
-    #include "secret.qh"
-#endif
+#include "../common/constants.qh"
+#include "../common/deathtypes.qh"
+#include "../common/mapinfo.qh"
+#include "../common/monsters/all.qh"
+#include "../common/monsters/sv_monsters.qh"
+#include "../common/notifications.qh"
+#include "../common/playerstats.qh"
+#include "../common/stats.qh"
+#include "../common/teams.qh"
+#include "../common/util.qh"
+#include "../common/items/all.qh"
+#include "../common/weapons/all.qh"
 
 const float LATENCY_THINKRATE = 10;
 .float latency_sum;
@@ -93,9 +92,7 @@ string redirection_target;
 float world_initialized;
 
 string GetGametype();
-void GotoNextMap(float reinit);
 void ShuffleMaplist();
-float(float reinit) DoNextMapOverride;
 
 void SetDefaultAlpha()
 {
@@ -191,6 +188,8 @@ void cvar_changes_init()
                BADCVAR("g_configversion");
                BADCVAR("g_maplist_index");
                BADCVAR("halflifebsp");
+               BADCVAR("sv_mapformat_is_quake2");
+               BADCVAR("sv_mapformat_is_quake3");
                BADPREFIX("sv_world");
 
                // client
@@ -273,6 +272,7 @@ void cvar_changes_init()
                BADCVAR("g_domination_default_teams");
                BADCVAR("g_freezetag");
                BADCVAR("g_freezetag_teams");
+               BADCVAR("g_invasion_teams");
                BADCVAR("g_keepaway");
                BADCVAR("g_keyhunt");
                BADCVAR("g_keyhunt_teams");
@@ -376,6 +376,7 @@ void cvar_changes_init()
                BADCVAR("g_ca_teams_override");
                BADCVAR("g_ctf_ignore_frags");
                BADCVAR("g_domination_point_limit");
+               BADCVAR("g_domination_teams_override");
                BADCVAR("g_freezetag_teams_override");
                BADCVAR("g_friendlyfire");
                BADCVAR("g_fullbrightitems");
@@ -396,6 +397,7 @@ void cvar_changes_init()
                BADCVAR("g_nexball_goallimit");
                BADCVAR("g_powerups");
                BADCVAR("g_start_delay");
+               BADCVAR("g_tdm_teams_override");
                BADCVAR("g_warmup");
                BADCVAR("g_weapon_stay"); BADPRESUFFIX("g_", "_weapon_stay");
                BADCVAR("hostname");
@@ -509,7 +511,7 @@ void detect_maptype()
 }
 
 entity randomseed;
-float RandomSeed_Send(entity to, float sf)
+float RandomSeed_Send(entity to, int sf)
 {
        WriteByte(MSG_ENTITY, ENT_CLIENT_RANDOMSEED);
        WriteShort(MSG_ENTITY, self.cnt);
@@ -559,6 +561,7 @@ void spawnfunc___init_dedicated_server(void)
        // needs to be done so early because of the constants they create
        CALL_ACCUMULATED_FUNCTION(RegisterWeapons);
        CALL_ACCUMULATED_FUNCTION(RegisterMonsters);
+       CALL_ACCUMULATED_FUNCTION(RegisterItems);
        CALL_ACCUMULATED_FUNCTION(RegisterGametypes);
        CALL_ACCUMULATED_FUNCTION(RegisterNotifications);
        CALL_ACCUMULATED_FUNCTION(RegisterDeathtypes);
@@ -574,9 +577,10 @@ void Nagger_Init();
 void ClientInit_Spawn();
 void WeaponStats_Init();
 void WeaponStats_Shutdown();
+void Physics_AddStats();
 void spawnfunc_worldspawn (void)
 {
-       float fd, l, i, j, n;
+       float fd, l, j, n;
        string s;
 
        cvar = cvar_normal;
@@ -607,6 +611,7 @@ void spawnfunc_worldspawn (void)
        // needs to be done so early because of the constants they create
        CALL_ACCUMULATED_FUNCTION(RegisterWeapons);
        CALL_ACCUMULATED_FUNCTION(RegisterMonsters);
+       CALL_ACCUMULATED_FUNCTION(RegisterItems);
        CALL_ACCUMULATED_FUNCTION(RegisterGametypes);
        CALL_ACCUMULATED_FUNCTION(RegisterNotifications);
        CALL_ACCUMULATED_FUNCTION(RegisterDeathtypes);
@@ -686,7 +691,7 @@ void spawnfunc_worldspawn (void)
        // character set: ASCII 33-126 without the following characters: : ; ' " \ $
        if(autocvar_sv_eventlog)
        {
-               s = sprintf("%d.%s.%06d", ftos(autocvar_sv_eventlog_files_counter), strftime(false, "%s"), floor(random() * 1000000));
+               s = sprintf("%d.%s.%06d", itos(autocvar_sv_eventlog_files_counter), strftime(false, "%s"), floor(random() * 1000000));
                matchid = strzone(s);
 
                GameLogEcho(strcat(":gamestart:", GetGametype(), "_", GetMapname(), ":", s));
@@ -814,11 +819,29 @@ void spawnfunc_worldspawn (void)
        addstat(STAT_FROZEN, AS_INT, frozen);
        addstat(STAT_REVIVE_PROGRESS, AS_FLOAT, revive_progress);
 
-       // g_movementspeed hack
-       addstat(STAT_MOVEVARS_AIRSPEEDLIMIT_NONQW, AS_FLOAT, stat_sv_airspeedlimit_nonqw);
-       addstat(STAT_MOVEVARS_MAXSPEED, AS_FLOAT, stat_sv_maxspeed);
-       addstat(STAT_MOVEVARS_AIRACCEL_QW, AS_FLOAT, stat_sv_airaccel_qw);
-       addstat(STAT_MOVEVARS_AIRSTRAFEACCEL_QW, AS_FLOAT, stat_sv_airstrafeaccel_qw);
+       // physics
+       Physics_AddStats();
+
+       // new properties
+       addstat(STAT_MOVEVARS_JUMPVELOCITY, AS_FLOAT, stat_sv_jumpvelocity);
+       addstat(STAT_MOVEVARS_AIRACCEL_QW_STRETCHFACTOR, AS_FLOAT, stat_sv_airaccel_qw_stretchfactor);
+       addstat(STAT_MOVEVARS_MAXAIRSTRAFESPEED, AS_FLOAT, stat_sv_maxairstrafespeed);
+       addstat(STAT_MOVEVARS_MAXAIRSPEED, AS_FLOAT, stat_sv_maxairspeed);
+       addstat(STAT_MOVEVARS_AIRSTRAFEACCELERATE, AS_FLOAT, stat_sv_airstrafeaccelerate);
+       addstat(STAT_MOVEVARS_WARSOWBUNNY_TURNACCEL, AS_FLOAT, stat_sv_warsowbunny_turnaccel);
+       addstat(STAT_MOVEVARS_AIRACCEL_SIDEWAYS_FRICTION, AS_FLOAT, stat_sv_airaccel_sideways_friction);
+       addstat(STAT_MOVEVARS_AIRCONTROL, AS_FLOAT, stat_sv_aircontrol);
+       addstat(STAT_MOVEVARS_AIRCONTROL_POWER, AS_FLOAT, stat_sv_aircontrol_power);
+       addstat(STAT_MOVEVARS_AIRCONTROL_PENALTY, AS_FLOAT, stat_sv_aircontrol_penalty);
+       addstat(STAT_MOVEVARS_WARSOWBUNNY_AIRFORWARDACCEL, AS_FLOAT, stat_sv_warsowbunny_airforwardaccel);
+       addstat(STAT_MOVEVARS_WARSOWBUNNY_TOPSPEED, AS_FLOAT, stat_sv_warsowbunny_topspeed);
+       addstat(STAT_MOVEVARS_WARSOWBUNNY_ACCEL, AS_FLOAT, stat_sv_warsowbunny_accel);
+       addstat(STAT_MOVEVARS_WARSOWBUNNY_BACKTOSIDERATIO, AS_FLOAT, stat_sv_warsowbunny_backtosideratio);
+       addstat(STAT_MOVEVARS_FRICTION, AS_FLOAT, stat_sv_friction);
+       addstat(STAT_MOVEVARS_ACCELERATE, AS_FLOAT, stat_sv_accelerate);
+       addstat(STAT_MOVEVARS_STOPSPEED, AS_FLOAT, stat_sv_stopspeed);
+       addstat(STAT_MOVEVARS_AIRACCELERATE, AS_FLOAT, stat_sv_airaccelerate);
+       addstat(STAT_MOVEVARS_AIRSTOPACCELERATE, AS_FLOAT, stat_sv_airstopaccelerate);
 
        // secrets
        addstat(STAT_SECRETS_TOTAL, AS_FLOAT, stat_secrets_total);
@@ -839,7 +862,7 @@ void spawnfunc_worldspawn (void)
        maplist_reply = strzone(getmaplist());
        lsmaps_reply = strzone(getlsmaps());
        monsterlist_reply = strzone(getmonsterlist());
-       for(i = 0; i < 10; ++i)
+       for(int i = 0; i < 10; ++i)
        {
                s = getrecords(i);
                if (s)
@@ -862,7 +885,7 @@ void spawnfunc_worldspawn (void)
        {
                s = "";
                n = tokenize_console(cvar_string("sv_curl_serverpackages"));
-               for(i = 0; i < n; ++i)
+               for(int i = 0; i < n; ++i)
                        if(substring(argv(i), -18, -1) != "-serverpackage.txt")
                        if(substring(argv(i), -14, -1) != ".serverpackage") // OLD legacy
                                s = strcat(s, " ", argv(i));
@@ -870,7 +893,7 @@ void spawnfunc_worldspawn (void)
                if(fd >= 0)
                {
                        j = search_getsize(fd);
-                       for(i = 0; i < j; ++i)
+                       for(int i = 0; i < j; ++i)
                                s = strcat(s, " ", search_getfilename(fd, i));
                        search_end(fd);
                }
@@ -878,7 +901,7 @@ void spawnfunc_worldspawn (void)
                if(fd >= 0)
                {
                        j = search_getsize(fd);
-                       for(i = 0; i < j; ++i)
+                       for(int i = 0; i < j; ++i)
                                s = strcat(s, " ", search_getfilename(fd, i));
                        search_end(fd);
                }
@@ -1650,7 +1673,7 @@ void SetWinners(.float field, float value)
 {
        entity head;
        FOR_EACH_PLAYER(head)
-               head.winning = (head.field == value);
+               head.winning = (head.(field) == value);
 }
 
 // set the .winning flag for those players with a given field value
@@ -1658,7 +1681,7 @@ void AddWinners(.float field, float value)
 {
        entity head;
        FOR_EACH_PLAYER(head)
-               if(head.field == value)
+               if (head.(field) == value)
                        head.winning = 1;
 }
 
@@ -1964,7 +1987,7 @@ float WinningCondition_RanOutOfSpawns()
        if(have_team_spawns <= 0)
                return WINNING_NO;
 
-       if(autocvar_g_spawn_useallspawns <= 0)
+       if(!autocvar_g_spawn_useallspawns)
                return WINNING_NO;
 
        if(!some_spawn_has_been_used)
@@ -2036,7 +2059,6 @@ CheckRules_World
 Exit deathmatch games upon conditions
 ============
 */
-void ReadyRestart();
 void CheckRules_World()
 {
        float timelimit;
index 3a5e5d5ac76b4d805a6ca9bde51d0cb219436d46..920ef71e184c1cc71d5962d57cd9c639f140d8f4 100644 (file)
@@ -13,5 +13,16 @@ const float WINNING_STARTSUDDENDEATHOVERTIME = 3; // no winner, enter suddendeat
 
 void CheckRules_Player();
 void IntermissionThink();
+void GotoNextMap(float reinit);
+void ReadyRestart();
+
+void DumpStats(float final);
+float Map_IsRecent(string m);
+string GetNextMap();
+void ShuffleMaplist();
+void Map_Goto_SetStr(string nextmapname);
+void Map_Goto(float reinit);
+float DoNextMapOverride(float reinit);
+void CheckRules_World();
 
 #endif
index 9591ee8baa9d9b7620d5b5fbe32f430a8e0a22cb..db758a8e6d41bab7300654d865c6bef18b982eb7 100644 (file)
@@ -1,15 +1,13 @@
-#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 "autocvars.qh"
-    #include "defs.qh"
-    #include "command/banning.qh"
-    #include "ipban.qh"
-#endif
+#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 f4893094efb533c429902e0defbd2ad2ad82b1df..1518151f2c85b457fff515b37634030b68f838b0 100644 (file)
@@ -1,15 +1,11 @@
-#if defined(CSQC)
-#elif defined(MENUQC)
-#elif defined(SVQC)
-       #include "../dpdefs/progsdefs.qh"
-    #include "../dpdefs/dpextensions.qh"
-    #include "../warpzonelib/util_server.qh"
-    #include "../common/util.qh"
-    #include "../common/monsters/monsters.qh"
-    #include "defs.qh"
-    #include "../common/notifications.qh"
-    #include "item_key.qh"
-#endif
+#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"
 
 /*
 TODO:
@@ -20,7 +16,8 @@ TODO:
 - should keys have a trigger?
 */
 
-bool item_keys_usekey(entity l, entity p) {
+bool item_keys_usekey(entity l, entity p)
+{
        float valid = l.itemkeys & p.itemkeys;
 
        if (!valid) {
@@ -38,9 +35,6 @@ bool item_keys_usekey(entity l, entity p) {
 }
 
 string item_keys_keylist(float keylist) {
-       float base, l;
-       string n;
-
        // no keys
        if (!keylist)
                return "";
@@ -49,10 +43,10 @@ string item_keys_keylist(float keylist) {
        if ((keylist & (keylist-1)) != 0)
                return strcat("the ", item_keys_names[lowestbit(keylist)]);
 
-       n = "";
-       base = 0;
+       string n = "";
+       int base = 0;
        while (keylist) {
-               l = lowestbit(keylist);
+               int l = lowestbit(keylist);
                if (n)
                        n = strcat(n, ", the ", item_keys_names[base + l]);
                else
@@ -281,156 +275,3 @@ void spawnfunc_item_key2(void) {
        self.itemkeys = ITEM_KEY_BIT(0);
        spawnfunc_item_key();
 };
-
-
-/*
-================================
-trigger_keylock
-================================
-*/
-
-/**
- * trigger givent targets
- */
-void trigger_keylock_trigger(string s) {
-       entity stemp = self;
-       entity otemp = other;
-       entity atemp = activator;
-
-       entity t;
-       for(t = world; (t = find(t, targetname, s)); )
-               if (t.use) {
-                       self = t;
-                       other = stemp;
-                       activator = atemp;
-                       self.use();
-               }
-
-       self = stemp;
-       other = otemp;
-       activator = atemp;
-};
-
-/**
- * kill killtarget of trigger keylock.
- */
-void trigger_keylock_kill(string s) {
-       entity t;
-       for(t = world; (t = find(t, targetname, s)); )
-               remove(t);
-};
-
-void trigger_keylock_touch(void) {
-       bool key_used = false;
-       bool started_delay = false;
-
-       // only player may trigger the lock
-       if (!IS_PLAYER(other))
-               return;
-
-
-       // check silver key
-       if (self.itemkeys)
-               key_used = item_keys_usekey(self, other);
-
-       activator = other;
-
-       if (self.itemkeys) {
-               // at least one of the keys is missing
-               if (key_used) {
-                       // one or more keys were given, but others are still missing!
-                       play2(other, self.noise1);
-                       Send_Notification(NOTIF_ONE, other, MSG_CENTER, CENTER_DOOR_LOCKED_ALSONEED, item_keys_keylist(self.itemkeys));
-                       other.key_door_messagetime = time + 2;
-               } else if (other.key_door_messagetime <= time) {
-                       // no keys were given
-                       play2(other, self.noise2);
-                       Send_Notification(NOTIF_ONE, other, MSG_CENTER, CENTER_DOOR_LOCKED_NEED, item_keys_keylist(self.itemkeys));
-                       other.key_door_messagetime = time + 2;
-               }
-
-               // trigger target2
-               if (self.delay <= time || started_delay == true)
-               if (self.target2) {
-                       trigger_keylock_trigger(self.target2);
-                       started_delay = true;
-                       self.delay = time + self.wait;
-               }
-       } else {
-               // all keys were given!
-               play2(other, self.noise);
-               centerprint(other, self.message);
-
-               if (self.target)
-                       trigger_keylock_trigger(self.target);
-
-               if (self.killtarget)
-                       trigger_keylock_kill(self.killtarget);
-
-               remove(self);
-       }
-
-};
-
-/*QUAKED trigger_keylock (.0 .5 .8) ?
-Keylock trigger.  Must target other entities.
-This trigger will trigger target entities when all required keys are provided.
--------- KEYS --------
-itemkeys: A bit field with key IDs that are needed to open this lock.
-sounds: 1 to play misc/secret.wav, 2 to play misc/talk.wav, 3 to play misc/trigger1.wav (3 is default)
-target: trigger all entities with this targetname when triggered and all keys have been given to it, then remove this trigger
-target2: trigger all entities with this targetname when triggered without giving it all the required keys.
-killtarget: remove all entities with this targetname when triggered with all the needed keys.
-message: print this message to the player who activated the trigger when all needed keys have been given.
-message2: print this message to the player who activated the trigger when not all of the needed keys have been given.
-noise: sound to play when lock gets unlocked (default: see sounds)
-noise1: sound to play when only some of the needed key were used but not all (default: misc/decreasevalue.wav)
-noise2: sound to play when a key is missing (default: misc/talk.wav)
-wait: prevent triggering again for this amount of time (default: 5) - applies to target2, target3, target4.
----------NOTES----------
-If spawned without any key specified in itemkeys, this trigger will display an error and remove itself.
-message2 and noise2 will be resent to the player every 2 seconds while he is in the trigger zone.
-*/
-void spawnfunc_trigger_keylock(void) {
-       if (!self.itemkeys) {
-               remove(self);
-               return;
-       }
-
-       // set unlocked message
-       if (self.message == "")
-               self.message = "Unlocked!";
-
-       // set default unlock noise
-       if (self.noise == "") {
-               if (self.sounds == 1)
-                       self.noise = "misc/secret.wav";
-               else if (self.sounds == 2)
-                       self.noise = "misc/talk.wav";
-               else //if (self.sounds == 3) {
-                       self.noise = "misc/trigger1.wav";
-       }
-
-       // set default use key sound
-       if (self.noise1 == "")
-               self.noise1 = "misc/decreasevalue.wav";
-
-       // set closed sourd
-       if (self.noise2 == "")
-               self.noise2 = "misc/talk.wav";
-
-       // delay between triggering message2 and trigger2
-       if (!self.wait)
-               self.wait = 5;
-
-       // precache sounds
-       precache_sound(self.noise);
-       precache_sound(self.noise1);
-       precache_sound(self.noise2);
-
-       EXACTTRIGGER_INIT;
-
-       self.touch = trigger_keylock_touch;
-};
-
-
index 6ab56050368601b25496c20717744e5ff1ff9b29..4a2acd85b7d1c015d8303f3c4d120b4b25178292 100644 (file)
@@ -11,6 +11,7 @@
 /**
  * list of key names.
  */
+#ifdef SVQC
 string item_keys_names[ITEM_KEY_MAX];
 
 /**
@@ -24,3 +25,5 @@ float item_keys_usekey(entity l, entity p);
  */
 string item_keys_keylist(float keylist);
 #endif
+
+#endif
index fd42c99ab9c6e5f30ffdfdb573a887149f2ad14f..952ce5bd0595ff40273229587503bf58403717a3 100644 (file)
@@ -1,35 +1,80 @@
-#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 "autocvars.qh"
-    #include "constants.qh"
-    #include "defs.qh"
-    #include "../common/mapinfo.qh"
-    #include "command/getreplies.qh"
-    #include "command/cmd.qh"
-    #include "../common/playerstats.qh"
-    #include "mapvoting.qh"
-#endif
-
-float GameTypeVote_AvailabilityStatus(string gtname)
+#include "mapvoting.qh"
+#include "_all.qh"
+
+#include "g_world.qh"
+#include "command/cmd.qh"
+#include "command/getreplies.qh"
+#include "../common/constants.qh"
+#include "../common/mapinfo.qh"
+#include "../common/playerstats.qh"
+#include "../common/util.qh"
+
+
+// definitions
+
+float mapvote_nextthink;
+float mapvote_keeptwotime;
+float mapvote_timeout;
+string mapvote_message;
+const float MAPVOTE_SCREENSHOT_DIRS_COUNT = 4;
+string mapvote_screenshot_dirs[MAPVOTE_SCREENSHOT_DIRS_COUNT];
+float mapvote_screenshot_dirs_count;
+
+float mapvote_count;
+float mapvote_count_real;
+string mapvote_maps[MAPVOTE_COUNT];
+float mapvote_maps_screenshot_dir[MAPVOTE_COUNT];
+string mapvote_maps_pakfile[MAPVOTE_COUNT];
+float mapvote_maps_suggested[MAPVOTE_COUNT];
+string mapvote_suggestions[MAPVOTE_COUNT];
+float mapvote_suggestion_ptr;
+float mapvote_voters;
+float mapvote_selections[MAPVOTE_COUNT];
+float mapvote_maps_flags[MAPVOTE_COUNT];
+float mapvote_run;
+float mapvote_detail;
+float mapvote_abstain;
+.float mapvote;
+
+entity mapvote_ent;
+
+/**
+ * Returns the gamtype ID from its name, if type_name isn't a real gametype it
+ * checks for sv_vote_gametype_(type_name)_type
+ */
+float GameTypeVote_Type_FromString(string type_name)
 {
-       float type = MapInfo_Type_FromString(gtname);
+       float type = MapInfo_Type_FromString(type_name);
+       if ( type == 0 )
+               type = MapInfo_Type_FromString(cvar_string(
+                       strcat("sv_vote_gametype_",type_name,"_type")));
+       return type;
+}
+
+int GameTypeVote_AvailabilityStatus(string type_name)
+{
+       int flag = GTV_FORBIDDEN;
+
+       float type = MapInfo_Type_FromString(type_name);
+       if ( type == 0 )
+       {
+               type = MapInfo_Type_FromString(cvar_string(
+                       strcat("sv_vote_gametype_",type_name,"_type")));
+               flag |= GTV_CUSTOM;
+       }
+
        if( type == 0 )
-               return GTV_FORBIDDEN;
+               return flag;
 
        if ( autocvar_nextmap != "" )
        {
                if ( !MapInfo_Get_ByName(autocvar_nextmap, false, 0) )
-                       return GTV_FORBIDDEN;
+                       return flag;
                if (!(MapInfo_Map_supportedGametypes & type))
-                       return GTV_FORBIDDEN;
+                       return flag;
        }
 
-       return GTV_AVAILABLE;
+       return flag | GTV_AVAILABLE;
 }
 
 float GameTypeVote_GetMask()
@@ -39,7 +84,7 @@ float GameTypeVote_GetMask()
        n = min(MAPVOTE_COUNT, n);
        gametype_mask = 0;
        for(j = 0; j < n; ++j)
-               gametype_mask |= MapInfo_Type_FromString(argv(j));
+               gametype_mask |= GameTypeVote_Type_FromString(argv(j));
        return gametype_mask;
 }
 
@@ -153,7 +198,7 @@ void MapVote_AddVotable(string nextMap, float isSuggestion)
 
        mapvote_maps_screenshot_dir[mapvote_count] = i;
        mapvote_maps_pakfile[mapvote_count] = strzone(pakfile);
-       mapvote_maps_availability[mapvote_count] = GTV_AVAILABLE;
+       mapvote_maps_flags[mapvote_count] = GTV_AVAILABLE;
 
        mapvote_count += 1;
 }
@@ -235,7 +280,7 @@ void MapVote_WriteMask()
                float mask,power;
                mask = 0;
                for(i = 0, power = 1; i < mapvote_count; ++i, power *= 2)
-                       if(mapvote_maps_availability[i] == GTV_AVAILABLE )
+                       if(mapvote_maps_flags[i] & GTV_AVAILABLE )
                                mask |= power;
 
                if(mapvote_count < 8)
@@ -248,11 +293,57 @@ void MapVote_WriteMask()
        else
        {
                for ( i = 0; i < mapvote_count; ++i )
-                       WriteByte(MSG_ENTITY, mapvote_maps_availability[i]);
+                       WriteByte(MSG_ENTITY, mapvote_maps_flags[i]);
+       }
+}
+
+/*
+ * Sends a single map vote option to the client
+ */
+void MapVote_SendOption(int i)
+{
+       // abstain
+       if(mapvote_abstain && i == mapvote_count - 1)
+       {
+               WriteString(MSG_ENTITY, ""); // abstain needs no text
+               WriteString(MSG_ENTITY, ""); // abstain needs no pack
+               WriteByte(MSG_ENTITY, 0); // abstain needs no screenshot dir
+       }
+       else
+       {
+               WriteString(MSG_ENTITY, mapvote_maps[i]);
+               WriteString(MSG_ENTITY, mapvote_maps_pakfile[i]);
+               WriteByte(MSG_ENTITY, mapvote_maps_screenshot_dir[i]);
        }
 }
 
-float MapVote_SendEntity(entity to, float sf)
+/*
+ * Sends a single gametype vote option to the client
+ */
+void GameTypeVote_SendOption(int i)
+{
+       // abstain
+       if(mapvote_abstain && i == mapvote_count - 1)
+       {
+               WriteString(MSG_ENTITY, ""); // abstain needs no text
+               WriteByte(MSG_ENTITY, GTV_AVAILABLE);
+       }
+       else
+       {
+               string type_name = mapvote_maps[i];
+               WriteString(MSG_ENTITY, type_name);
+               WriteByte(MSG_ENTITY, mapvote_maps_flags[i]);
+               if ( mapvote_maps_flags[i] & GTV_CUSTOM )
+               {
+                       WriteString(MSG_ENTITY, cvar_string(
+                               strcat("sv_vote_gametype_",type_name,"_name")));
+                       WriteString(MSG_ENTITY, cvar_string(
+                               strcat("sv_vote_gametype_",type_name,"_description")));
+               }
+       }
+}
+
+float MapVote_SendEntity(entity to, int sf)
 {
        float i;
 
@@ -281,7 +372,7 @@ float MapVote_SendEntity(entity to, float sf)
                }
                else if ( autocvar_sv_vote_gametype )
                {
-                        // map vote but gametype has been chosen via voting screen
+                       // map vote but gametype has been chosen via voting screen
                        WriteByte(MSG_ENTITY, 2);
                        WriteString(MSG_ENTITY, MapInfo_Type_ToText(MapInfo_CurrentGametype()));
                }
@@ -290,22 +381,13 @@ float MapVote_SendEntity(entity to, float sf)
 
                MapVote_WriteMask();
 
+               // Send data for the vote options
                for(i = 0; i < mapvote_count; ++i)
                {
-                       if(mapvote_abstain && i == mapvote_count - 1)
-                       {
-                               WriteString(MSG_ENTITY, ""); // abstain needs no text
-                               WriteString(MSG_ENTITY, ""); // abstain needs no pack
-                               WriteByte(MSG_ENTITY, 0); // abstain needs no screenshot dir
-                               WriteByte(MSG_ENTITY, GTV_AVAILABLE);
-                       }
+                       if(gametypevote)
+                               GameTypeVote_SendOption(i);
                        else
-                       {
-                               WriteString(MSG_ENTITY, mapvote_maps[i]);
-                               WriteString(MSG_ENTITY, mapvote_maps_pakfile[i]);
-                               WriteByte(MSG_ENTITY, mapvote_maps_screenshot_dir[i]);
-                               WriteByte(MSG_ENTITY, mapvote_maps_availability[i]);
-                       }
+                               MapVote_SendOption(i);
                }
        }
 
@@ -319,7 +401,7 @@ float MapVote_SendEntity(entity to, float sf)
        {
                if(mapvote_detail)
                        for(i = 0; i < mapvote_count; ++i)
-                               if ( mapvote_maps_availability[i] == GTV_AVAILABLE )
+                               if ( mapvote_maps_flags[i] & GTV_AVAILABLE )
                                        WriteByte(MSG_ENTITY, mapvote_selections[i]);
 
                WriteByte(MSG_ENTITY, to.mapvote);
@@ -358,7 +440,7 @@ float MapVote_Finished(float mappos)
                result = strcat(result, ":", ftos(mapvote_selections[mappos]), "::");
                didntvote = mapvote_voters;
                for(i = 0; i < mapvote_count; ++i)
-                       if(mapvote_maps_availability[i] == GTV_AVAILABLE )
+                       if(mapvote_maps_flags[i] & GTV_AVAILABLE )
                        {
                                didntvote -= mapvote_selections[i];
                                if(i != mappos)
@@ -407,7 +489,7 @@ void MapVote_CheckRules_1()
        float i;
 
        for(i = 0; i < mapvote_count; ++i)
-               if( mapvote_maps_availability[i] == GTV_AVAILABLE )
+               if( mapvote_maps_flags[i] & GTV_AVAILABLE )
                {
                        //dprint("Map ", ftos(i), ": "); dprint(mapvote_maps[i], "\n");
                        mapvote_selections[i] = 0;
@@ -445,7 +527,7 @@ float MapVote_CheckRules_2()
        currentPlace = 0;
        currentVotes = -1;
        for(i = 0; i < mapvote_count_real; ++i)
-               if ( mapvote_maps_availability[i] == GTV_AVAILABLE )
+               if ( mapvote_maps_flags[i] & GTV_AVAILABLE )
                {
                        RandomSelection_Add(world, i, string_null, 1, mapvote_selections[i]);
                        if ( gametypevote &&  mapvote_maps[i] == MapInfo_Type_ToString(MapInfo_CurrentGametype()) )
@@ -466,7 +548,7 @@ float MapVote_CheckRules_2()
        RandomSelection_Init();
        for(i = 0; i < mapvote_count_real; ++i)
                if(i != firstPlace)
-               if ( mapvote_maps_availability[i] == GTV_AVAILABLE )
+               if ( mapvote_maps_flags[i] & GTV_AVAILABLE )
                        RandomSelection_Add(world, i, string_null, 1, mapvote_selections[i]);
        secondPlace = RandomSelection_chosen_float;
        secondPlaceVotes = RandomSelection_best_priority;
@@ -501,7 +583,7 @@ float MapVote_CheckRules_2()
                                                result = strcat(result, ":", ftos(mapvote_selections[i]));
                                                if(i < mapvote_count_real)
                                                {
-                                                       mapvote_maps_availability[i] = GTV_FORBIDDEN;
+                                                       mapvote_maps_flags[i] &= ~GTV_AVAILABLE;
                                                }
                                        }
                        }
@@ -540,11 +622,11 @@ void MapVote_Tick()
                }
 
                // clear possibly invalid votes
-               if ( mapvote_maps_availability[other.mapvote-1] != GTV_AVAILABLE )
+               if ( !(mapvote_maps_flags[other.mapvote-1] & GTV_AVAILABLE) )
                        other.mapvote = 0;
                // use impulses as new vote
                if(other.impulse >= 1 && other.impulse <= mapvote_count)
-                       if( mapvote_maps_availability[other.impulse - 1] == GTV_AVAILABLE )
+                       if( mapvote_maps_flags[other.impulse - 1] & GTV_AVAILABLE )
                        {
                                other.mapvote = other.impulse;
                                MapVote_TouchVotes(other);
@@ -664,7 +746,7 @@ float GameTypeVote_Finished(float pos)
        if(!gametypevote || gametypevote_finished)
                return false;
 
-       if ( !GameTypeVote_SetGametype(MapInfo_Type_FromString(mapvote_maps[pos])) )
+       if ( !GameTypeVote_SetGametype(GameTypeVote_Type_FromString(mapvote_maps[pos])) )
        {
                dprint("Selected gametype is not supported by any map");
        }
@@ -680,7 +762,7 @@ float GameTypeVote_Finished(float pos)
 float GameTypeVote_AddVotable(string nextMode)
 {
        float j;
-       if ( nextMode == "" || MapInfo_Type_FromString(nextMode) == 0 )
+       if ( nextMode == "" || GameTypeVote_Type_FromString(nextMode) == 0 )
                return false;
        for(j = 0; j < mapvote_count; ++j)
                if(mapvote_maps[j] == nextMode)
@@ -691,7 +773,7 @@ float GameTypeVote_AddVotable(string nextMode)
 
        mapvote_maps_screenshot_dir[mapvote_count] = 0;
        mapvote_maps_pakfile[mapvote_count] = strzone("");
-       mapvote_maps_availability[mapvote_count] = GameTypeVote_AvailabilityStatus(nextMode);
+       mapvote_maps_flags[mapvote_count] = GameTypeVote_AvailabilityStatus(nextMode);
 
        mapvote_count += 1;
 
@@ -719,7 +801,7 @@ float GameTypeVote_Start()
        for(j = 0; j < n; ++j)
        {
                if ( GameTypeVote_AddVotable(argv(j)) )
-               if ( mapvote_maps_availability[j] == GTV_AVAILABLE )
+               if ( mapvote_maps_flags[j] & GTV_AVAILABLE )
                {
                        really_available++;
                        which_available = j;
index d2eff1cf08ec0422fef2292e25326ee96244ac65..e4e6b0b52ac8b49582751d4cd32f868824c9a5cc 100644 (file)
@@ -5,38 +5,12 @@
 void MapVote_Start();
 void MapVote_Spawn();
 void MapVote_Think();
+void MapVote_SendPicture(float id);
 float GameTypeVote_Start();
 float GameTypeVote_Finished(float pos);
 string GameTypeVote_MapInfo_FixName(string m);
 
-// definitions
 float gametypevote;
 string getmapname_stored;
 float mapvote_initialized;
-
-float mapvote_nextthink;
-float mapvote_keeptwotime;
-float mapvote_timeout;
-string mapvote_message;
-const float MAPVOTE_SCREENSHOT_DIRS_COUNT = 4;
-string mapvote_screenshot_dirs[MAPVOTE_SCREENSHOT_DIRS_COUNT];
-float mapvote_screenshot_dirs_count;
-
-float mapvote_count;
-float mapvote_count_real;
-string mapvote_maps[MAPVOTE_COUNT];
-float mapvote_maps_screenshot_dir[MAPVOTE_COUNT];
-string mapvote_maps_pakfile[MAPVOTE_COUNT];
-float mapvote_maps_suggested[MAPVOTE_COUNT];
-string mapvote_suggestions[MAPVOTE_COUNT];
-float mapvote_suggestion_ptr;
-float mapvote_voters;
-float mapvote_selections[MAPVOTE_COUNT];
-float mapvote_maps_availability[MAPVOTE_COUNT];
-float mapvote_run;
-float mapvote_detail;
-float mapvote_abstain;
-.float mapvote;
-
-entity mapvote_ent;
 #endif
index d998ea7999b836763b21472eedd131204983e1b2..2354e128e30bd9d1874e1ca0e57c16ec2f8c07d2 100644 (file)
@@ -1,34 +1,30 @@
-#if defined(CSQC)
-#elif defined(MENUQC)
-#elif defined(SVQC)
-       #include "miscfunctions.qh"
-       #include "../dpdefs/progsdefs.qh"
-    #include "../dpdefs/dpextensions.qh"
-    #include "../common/playerstats.qh"
-    #include "../warpzonelib/anglestransform.qh"
-    #include "../warpzonelib/server.qh"
-    #include "../common/constants.qh"
-    #include "../common/teams.qh"
-    #include "../common/util.qh"
-    #include "../common/urllib.qh"
-    #include "../common/command/generic.qh"
-    #include "../common/weapons/weapons.qh"
-    #include "weapons/accuracy.qh"
-    #include "weapons/csqcprojectile.qh"
-    #include "weapons/selection.qh"
-    #include "t_items.qh"
-    #include "autocvars.qh"
-    #include "constants.qh"
-    #include "defs.qh"
-    #include "../common/notifications.qh"
-    #include "../common/deathtypes.qh"
-    #include "mutators/mutators_include.qh"
-    #include "tturrets/include/turrets_early.qh"
-    #include "../common/mapinfo.qh"
-    #include "command/common.qh"
-    #include "../csqcmodellib/sv_model.qh"
-    #include "ipban.qh"
-#endif
+#include "miscfunctions.qh"
+#include "_all.qh"
+#include "antilag.qh"
+#include "command/common.qh"
+#include "constants.qh"
+#include "g_hook.qh"
+#include "ipban.qh"
+#include "mutators/mutators_include.qh"
+#include "tturrets/include/turrets_early.qh"
+#include "t_items.qh"
+#include "weapons/accuracy.qh"
+#include "weapons/csqcprojectile.qh"
+#include "weapons/selection.qh"
+#include "../common/command/generic.qh"
+#include "../common/constants.qh"
+#include "../common/deathtypes.qh"
+#include "../common/mapinfo.qh"
+#include "../common/notifications.qh"
+#include "../common/playerstats.qh"
+#include "../common/teams.qh"
+#include "../common/triggers/subs.qh"
+#include "../common/urllib.qh"
+#include "../common/util.qh"
+#include "../common/weapons/all.qh"
+#include "../csqcmodellib/sv_model.qh"
+#include "../warpzonelib/anglestransform.qh"
+#include "../warpzonelib/server.qh"
 
 void crosshair_trace(entity pl)
 {
@@ -101,7 +97,7 @@ float DistributeEvenly_GetRandomized(float weight)
 void GameLogEcho(string s)
 {
     string fn;
-    float matches;
+    int matches;
 
     if (autocvar_sv_eventlog_files)
     {
@@ -109,7 +105,7 @@ void GameLogEcho(string s)
         {
             logfile_open = true;
             matches = autocvar_sv_eventlog_files_counter + 1;
-            cvar_set("sv_eventlog_files_counter", ftos(matches));
+            cvar_set("sv_eventlog_files_counter", itos(matches));
             fn = ftos(matches);
             if (strlen(fn) < 8)
                 fn = strcat(substring("00000000", 0, 8 - strlen(fn)), fn);
@@ -226,19 +222,6 @@ entity findnearest(vector point, .string field, string value, vector axismod)
     return nearest_entity[0];
 }
 
-void spawnfunc_target_location()
-{
-    self.classname = "target_location";
-    // location name in netname
-    // eventually support: count, teamgame selectors, line of sight?
-}
-
-void spawnfunc_info_location()
-{
-    self.classname = "target_location";
-    self.message = self.netname;
-}
-
 string NearestLocation(vector p)
 {
     entity loc;
@@ -357,17 +340,17 @@ void GetCvars_handleString(string thisname, float f, .string field, string name)
 {
        if (f < 0)
        {
-               if (self.field)
-                       strunzone(self.field);
-               self.field = string_null;
+               if (self.(field))
+                       strunzone(self.(field));
+               self.(field) = string_null;
        }
        else if (f > 0)
        {
                if (thisname == name)
                {
-                       if (self.field)
-                               strunzone(self.field);
-                       self.field = strzone(argv(f + 1));
+                       if (self.(field))
+                               strunzone(self.(field));
+                       self.(field) = strzone(argv(f + 1));
                }
        }
        else
@@ -379,12 +362,11 @@ void GetCvars_handleString_Fixup(string thisname, float f, .string field, string
        if (f >= 0) // also initialize to the fitting value for "" when sending cvars out
                if (thisname == name)
                {
-                       string s;
-                       s = func(strcat1(self.field));
-                       if (s != self.field)
+                       string s = func(strcat1(self.(field)));
+                       if (s != self.(field))
                        {
-                               strunzone(self.field);
-                               self.field = strzone(s);
+                               strunzone(self.(field));
+                               self.(field) = strzone(s);
                        }
                }
 }
@@ -396,7 +378,7 @@ void GetCvars_handleFloat(string thisname, float f, .float field, string name)
        else if (f > 0)
        {
                if (thisname == name)
-                       self.field = stof(argv(f + 1));
+                       self.(field) = stof(argv(f + 1));
        }
        else
                stuffcmd(self, strcat("cl_cmd sendcvar ", name, "\n"));
@@ -410,17 +392,17 @@ void GetCvars_handleFloatOnce(string thisname, float f, .float field, string nam
        {
                if (thisname == name)
                {
-                       if(!self.field)
+                       if (!self.(field))
                        {
-                               self.field = stof(argv(f + 1));
-                               if(!self.field)
-                                       self.field = -1;
+                               self.(field) = stof(argv(f + 1));
+                               if (!self.(field))
+                                       self.(field) = -1;
                        }
                }
        }
        else
        {
-               if(!self.field)
+               if (!self.(field))
                        stuffcmd(self, strcat("cl_cmd sendcvar ", name, "\n"));
        }
 }
@@ -454,6 +436,7 @@ void GetCvars(float f)
        GetCvars_handleFloat(s, f, cvar_cl_autoscreenshot, "cl_autoscreenshot");
        GetCvars_handleFloat(s, f, cvar_cl_jetpack_jump, "cl_jetpack_jump");
        GetCvars_handleString(s, f, cvar_g_xonoticversion, "g_xonoticversion");
+       GetCvars_handleString(s, f, cvar_cl_physics, "cl_physics");
        GetCvars_handleFloat(s, f, cvar_cl_handicap, "cl_handicap");
        GetCvars_handleFloat(s, f, cvar_cl_clippedspectating, "cl_clippedspectating");
        GetCvars_handleString_Fixup(s, f, cvar_cl_weaponpriority, "cl_weaponpriority", W_FixWeaponOrder_ForceComplete_AndBuildImpulseList);
@@ -585,7 +568,7 @@ void readplayerstartcvars()
        s = cvar_string("g_weaponarena");
        if (s == "0" || s == "")
        {
-               if(g_ca)
+               if(g_ca || g_freezetag)
                        s = "most";
        }
 
@@ -714,7 +697,7 @@ void readplayerstartcvars()
                warmup_start_weapons_default = start_weapons_default;
                warmup_start_weapons_defaultmask = start_weapons_defaultmask;
 
-               if (!g_weaponarena && !g_ca)
+               if (!g_weaponarena && !g_ca && !g_freezetag)
                {
                        warmup_start_ammo_shells = cvar("g_warmup_start_ammo_shells");
                        warmup_start_ammo_nails = cvar("g_warmup_start_ammo_nails");
@@ -778,7 +761,7 @@ void readplayerstartcvars()
        warmup_start_ammo_fuel = max(0, warmup_start_ammo_fuel);
 }
 
-float sound_allowed(float _dest, entity e)
+float sound_allowed(float destin, entity e)
 {
     // sounds from world may always pass
     for (;;)
@@ -793,7 +776,7 @@ float sound_allowed(float _dest, entity e)
             break;
     }
     // sounds to self may always pass
-    if (_dest == MSG_ONE)
+    if (destin == MSG_ONE)
         if (e == msg_entity)
             return true;
     // sounds by players can be removed
@@ -805,14 +788,14 @@ float sound_allowed(float _dest, entity e)
 }
 
 #undef sound
-void sound(entity e, float chan, string samp, float vol, float _atten)
+void sound(entity e, float chan, string samp, float vol, float attenu)
 {
     if (!sound_allowed(MSG_BROADCAST, e))
         return;
-    sound7(e, chan, samp, vol, _atten, 0, 0);
+    sound7(e, chan, samp, vol, attenu, 0, 0);
 }
 
-void soundtoat(float _dest, entity e, vector o, float chan, string samp, float vol, float _atten)
+void soundtoat(float _dest, entity e, vector o, float chan, string samp, float vol, float attenu)
 {
     float entno, idx;
 
@@ -822,15 +805,15 @@ void soundtoat(float _dest, entity e, vector o, float chan, string samp, float v
     entno = num_for_edict(e);
     idx = precache_sound_index(samp);
 
-    float sflags;
+    int sflags;
     sflags = 0;
 
-    _atten = floor(_atten * 64);
+    attenu = floor(attenu * 64);
     vol = floor(vol * 255);
 
     if (vol != 255)
         sflags |= SND_VOLUME;
-    if (_atten != 64)
+    if (attenu != 64)
         sflags |= SND_ATTENUATION;
     if (entno >= 8192 || chan < 0 || chan > 7)
         sflags |= SND_LARGEENTITY;
@@ -842,7 +825,7 @@ void soundtoat(float _dest, entity e, vector o, float chan, string samp, float v
     if (sflags & SND_VOLUME)
         WriteByte(_dest, vol);
     if (sflags & SND_ATTENUATION)
-        WriteByte(_dest, _atten);
+        WriteByte(_dest, attenu);
     if (sflags & SND_LARGEENTITY)
     {
         WriteShort(_dest, entno);
@@ -1274,8 +1257,7 @@ void SetCustomizer(entity e, float(void) customizer, void(void) uncustomizer)
     e.uncustomizeentityforclient_set = !!uncustomizer;
 }
 
-
-void Net_LinkEntity(entity e, float docull, float dt, float(entity, float) sendfunc)
+void Net_LinkEntity(entity e, bool docull, float dt, bool(entity, int) sendfunc)
 {
     vector mi, ma;
 
@@ -1304,7 +1286,6 @@ void Net_LinkEntity(entity e, float docull, float dt, float(entity, float) sendf
 }
 
 
-entity eliminatedPlayers;
 .float(entity) isEliminated;
 float EliminatedPlayers_SendEntity(entity to, float sendflags)
 {
@@ -1468,7 +1449,6 @@ float SUB_NoImpactCheck()
 
 #define SUB_OwnerCheck() (other && (other == self.owner))
 
-void RemoveGrapplingHook(entity pl);
 void W_Crylink_Dequeue(entity e);
 float WarpZone_Projectile_Touch_ImpactFilter_Callback()
 {
@@ -1836,7 +1816,7 @@ vector gettaginfo_relative(entity e, float tag)
 
 .float scale2;
 
-float modeleffect_SendEntity(entity to, float sf)
+float modeleffect_SendEntity(entity to, int sf)
 {
        float f;
        WriteByte(MSG_ENTITY, ENT_CLIENT_MODELEFFECT);
index f19f53fd0b3010d021308c2a29235f195097d1d1..12dbe3a2c795a72512c012cf9deaba5cb1dbbfe6 100644 (file)
@@ -15,7 +15,7 @@
 #else
 string cvar_string_normal(string n)
 {
-       if (!(cvar_type(n) & 1))
+       if (!(cvar_type(n) & CVAR_TYPEFLAG_EXISTS))
                backtrace(strcat("Attempt to access undefined cvar: ", n));
        return builtin_cvar_string(n);
 }
@@ -32,6 +32,46 @@ float cvar_normal(string n)
 .float uncustomizeentityforclient_set;
 .float nottargeted;
 
+entity eliminatedPlayers;
+void EliminatedPlayers_Init(float(entity) isEliminated_func);
+
+string admin_name(void);
+
+void write_recordmarker(entity pl, float tstart, float dt);
+
+void play2all(string samp);
+
+void DistributeEvenly_Init(float amount, float totalweight);
+float DistributeEvenly_Get(float weight);
+
+void modeleffect_spawn(string m, float s, float f, vector o, vector v, vector ang, vector angv, float s0, float s2, float a, float t1, float t2);
+
+void shockwave_spawn(string m, vector org, float sz, float t1, float t2);
+
+vector randompos(vector m1, vector m2);
+
+void play2team(float t, string filename);
+
+void GetCvars_handleFloat(string thisname, float f, .float field, string name);
+
+float spamsound(entity e, float chan, string samp, float vol, float _atten);
+
+void GetCvars_handleString(string thisname, float f, .string field, string name);
+
+void precache_all_playermodels(string pattern);
+
+void soundat(entity e, vector o, float chan, string samp, float vol, float _atten);
+
+void defer(float fdelay, void() func);
+
+void UncustomizeEntitiesRun();
+void InitializeEntitiesRun();
+
+void stopsoundto(float _dest, entity e, float chan);
+void soundtoat(float _dest, entity e, vector o, float chan, string samp, float vol, float _atten);
+float ExponentialFalloff(float mindist, float maxdist, float halflifedist, float d);
+
+vector shotorg_adjust(vector vecs, float y_is_right, float visual);
 
 float DistributeEvenly_amount;
 float DistributeEvenly_totalweight;
@@ -68,6 +108,8 @@ float isPushable(entity e);
 
 float LostMovetypeFollow(entity ent);
 
+string uid2name(string myuid);
+
 float MoveToRandomMapLocation(entity e, float goodcontents, float badcontents, float badsurfaceflags, float attempts, float maxaboveground, float minviewdistance);
 
 string NearestLocation(vector p);
@@ -99,15 +141,11 @@ void WarpZone_crosshair_trace(entity pl);
 void WarpZone_traceline_antilag (entity source, vector v1, vector v2, float nomonst, entity forent, float lag);
 
 
-#define IFTARGETED if(!self.nottargeted && self.targetname != "")
-
 #define ITEM_TOUCH_NEEDKILL() (((trace_dpstartcontents | trace_dphitcontents) & DPCONTENTS_NODROP) || (trace_dphitq3surfaceflags & Q3SURFACEFLAG_SKY))
 #define ITEM_DAMAGE_NEEDKILL(dt) (((dt) == DEATH_HURTTRIGGER) || ((dt) == DEATH_SLIME) || ((dt) == DEATH_LAVA) || ((dt) == DEATH_SWAMP))
 
 #define PROJECTILE_TOUCH if(WarpZone_Projectile_Touch()) return
 
-#define move_out_of_solid(e) WarpZoneLib_MoveOutOfSolid(e)
-
 const string STR_PLAYER = "player";
 const string STR_SPECTATOR = "spectator";
 const string STR_OBSERVER = "observer";
@@ -401,10 +439,6 @@ const float SND_ATTENUATION = 2;
 const float SND_LARGEENTITY = 8;
 const float SND_LARGESOUND = 16;
 
-// WARNING: this kills the trace globals
-#define EXACTTRIGGER_TOUCH if(WarpZoneLib_ExactTrigger_Touch()) return
-#define EXACTTRIGGER_INIT  WarpZoneLib_ExactTrigger_Init()
-
 const float INITPRIO_FIRST                             = 0;
 const float INITPRIO_GAMETYPE                  = 0;
 const float INITPRIO_GAMETYPE_FALLBACK         = 1;
@@ -426,6 +460,6 @@ entity initialize_entity_first;
 float sound_allowed(float dest, entity e);
 void InitializeEntity(entity e, void(void) func, float order);
 void SetCustomizer(entity e, float(void) customizer, void(void) uncustomizer);
-void Net_LinkEntity(entity e, float docull, float dt, float(entity, float) sendfunc);
+void Net_LinkEntity(entity e, bool docull, float dt, bool(entity, int) sendfunc);
 
 #endif
index e13919a23b174b5372f301b06070bfe31c0182df..f642a3bdf925474734ac814ac4b091cd6d5937a5 100644 (file)
@@ -1,3 +1,6 @@
+#include "base.qh"
+#include "../_all.qh"
+
 .float() cbc_func;
 .entity cbc_next;
 .float cbc_order;
@@ -95,7 +98,7 @@ const float MAX_MUTATORS = 15;
 string loaded_mutators[MAX_MUTATORS];
 float Mutator_Add(mutatorfunc_t func, string name)
 {
-       float i, j;
+       int i, j;
        j = -1;
        for(i = 0; i < MAX_MUTATORS; ++i)
        {
@@ -128,7 +131,7 @@ float Mutator_Add(mutatorfunc_t func, string name)
 }
 void Mutator_Remove(float(float) func, string name)
 {
-       float i;
+       int i;
        for(i = 0; i < MAX_MUTATORS; ++i)
                if(name == loaded_mutators[i])
                        break;
diff --git a/qcsrc/server/mutators/gamemode.qh b/qcsrc/server/mutators/gamemode.qh
new file mode 100644 (file)
index 0000000..32e48f3
--- /dev/null
@@ -0,0 +1,49 @@
+#ifndef GAMEMODE_H
+#define GAMEMODE_H
+
+#include "mutator_nades.qh"
+
+#include "../cl_client.qh"
+#include "../cl_player.qh"
+#include "../cl_impulse.qh"
+#include "../cheats.qh"
+#include "../g_damage.qh"
+#include "../round_handler.qh"
+#include "../scores.qh"
+#include "../scores_rules.qh"
+#include "../waypointsprites.qh"
+
+#include "../bot/bot.qh"
+#include "../bot/navigation.qh"
+#include "../bot/waypoints.qh"
+#include "../bot/havocbot/roles.qh"
+#include "../bot/havocbot/role_keyhunt.qh"
+
+#include "../bot/havocbot/havocbot.qh"
+
+#include "../command/vote.qh"
+
+#include "../../common/monsters/all.qh"
+
+#include "../command/common.qh"
+
+#include "../weapons/tracing.qh"
+#include "../weapons/weaponsystem.qh"
+
+#include "../../common/deathtypes.qh"
+#include "../../common/notifications.qh"
+#include "../../common/triggers/teleporters.qh"
+#include "../../common/triggers/subs.qh"
+#include "../../common/stats.qh"
+#include "../../common/teams.qh"
+
+#include "../../warpzonelib/mathlib.qh"
+#include "../../warpzonelib/server.qh"
+#include "../../warpzonelib/util_server.qh"
+
+.float lastground;
+float total_players;
+float redalive, bluealive, yellowalive, pinkalive;
+.float redalive_stat, bluealive_stat, yellowalive_stat, pinkalive_stat;
+
+#endif
index 49deac0e8f350c1f73cfea58694a21ac7927af5b..b8a2ab1a59178d57543cef1bbd85bc19e34e7e8e 100644 (file)
@@ -1,3 +1,10 @@
+#include "gamemode_assault.qh"
+#include "../_all.qh"
+
+#include "gamemode.qh"
+
+.entity sprite;
+
 // random functions
 void assault_objective_use()
 {
index 330707e67c949bf097192658d2c0d57c8a2048bb..1266492ca091e4b99a05f3cc89ffa13822e853a5 100644 (file)
@@ -29,6 +29,5 @@ const float ST_ASSAULT_OBJECTIVES = 1;
 const float SP_ASSAULT_OBJECTIVES = 4;
 
 // predefined spawnfuncs
-void spawnfunc_func_breakable();
 void target_objective_decrease_activate();
 #endif
index a0f238358455a271a80a45d996ecf9c07fe16f36..9ad532e909e4dcfd2b56d3d187308db93a999b15 100644 (file)
@@ -1,6 +1,8 @@
-float total_players;
-float redalive, bluealive, yellowalive, pinkalive;
-.float redalive_stat, bluealive_stat, yellowalive_stat, pinkalive_stat;
+#include "gamemode_ca.qh"
+#include "../_all.qh"
+
+#include "gamemode.qh"
+
 float ca_teams;
 float allowed_to_spawn;
 
index 5ea2924cc4a40184fc80f9197ac49cebdb0dfab0..c2189155c421299f254533c88393dfb8b4851bae 100644 (file)
@@ -1,7 +1,14 @@
-// ================================================================
-//  Official capture the flag game mode coding, reworked by Samual
-//  Last updated: September, 2012
-// ================================================================
+#include "gamemode_ctf.qh"
+#include "../_all.qh"
+
+#include "gamemode.qh"
+
+#ifdef SVQC
+#include "../vehicles/vehicle.qh"
+#endif
+
+#include "../../warpzonelib/common.qh"
+#include "../../warpzonelib/mathlib.qh"
 
 void ctf_FakeTimeLimit(entity e, float t)
 {
@@ -14,7 +21,7 @@ void ctf_FakeTimeLimit(entity e, float t)
                WriteCoord(MSG_ONE, (t + 1) / 60);
 }
 
-void ctf_EventLog(string mode, float flagteam, entity actor) // use an alias for easy changing and quick editing later
+void ctf_EventLog(string mode, int flagteam, entity actor) // use an alias for easy changing and quick editing later
 {
        if(autocvar_sv_eventlog)
                GameLogEcho(strcat(":ctf:", mode, ":", ftos(flagteam), ((actor != world) ? (strcat(":", ftos(actor.playerid))) : "")));
@@ -80,7 +87,7 @@ void ctf_CalculatePassVelocity(entity flag, vector to, vector from, float turnra
        else { flag.velocity = (desired_direction * autocvar_g_ctf_pass_velocity); }
 }
 
-float ctf_CheckPassDirection(vector head_center, vector passer_center, vector passer_angle, vector nearest_to_passer)
+bool ctf_CheckPassDirection(vector head_center, vector passer_center, vector passer_angle, vector nearest_to_passer)
 {
        if(autocvar_g_ctf_pass_directional_max || autocvar_g_ctf_pass_directional_min)
        {
@@ -114,7 +121,7 @@ float ctf_CheckPassDirection(vector head_center, vector passer_center, vector pa
 // CaptureShield Functions
 // =======================
 
-float ctf_CaptureShield_CheckStatus(entity p)
+bool ctf_CaptureShield_CheckStatus(entity p)
 {
        float s, se;
        entity e;
@@ -643,7 +650,7 @@ void ctf_CheckStalemate(void)
        }
 }
 
-void ctf_FlagDamage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
+void ctf_FlagDamage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
 {
        if(ITEM_DAMAGE_NEEDKILL(deathtype))
        {
@@ -949,6 +956,7 @@ void ctf_DelayedFlagSetup(void) // called after a flag is placed on a map by ctf
        self.bot_basewaypoint = self.nearestwaypoint;
 
        // waypointsprites
+       // move_origin isnt accessible just yet
        WaypointSprite_SpawnFixed(((self.team == NUM_TEAM_1) ? "redbase" : "bluebase"), self.origin + FLAG_WAYPOINT_OFFSET, self, wps_flagbase, RADARICON_FLAG, colormapPaletteColor(self.team - 1, false));
        WaypointSprite_UpdateTeamRadar(self.wps_flagbase, RADARICON_FLAG, colormapPaletteColor(self.team - 1, false));
 
index 0e5930db2cbe83c95b439e8f75461cdce64eda7f..b183a2ae58f340a4c1e1052c56148447325c9a27 100644 (file)
@@ -7,17 +7,17 @@
 void ctf_RespawnFlag(entity flag);
 
 // score rule declarations
-const float ST_CTF_CAPS = 1;
-const float SP_CTF_CAPS = 4;
-const float SP_CTF_CAPTIME = 5;
-const float SP_CTF_PICKUPS = 6;
-const float SP_CTF_DROPS = 7;
-const float SP_CTF_FCKILLS = 8;
-const float SP_CTF_RETURNS = 9;
+const int ST_CTF_CAPS = 1;
+const int SP_CTF_CAPS = 4;
+const int SP_CTF_CAPTIME = 5;
+const int SP_CTF_PICKUPS = 6;
+const int SP_CTF_DROPS = 7;
+const int SP_CTF_FCKILLS = 8;
+const int SP_CTF_RETURNS = 9;
 
 // flag constants // for most of these, there is just one question to be asked: WHYYYYY?
-#define FLAG_MIN (PL_MIN + '0 0 -13')
-#define FLAG_MAX (PL_MAX + '0 0 -13')
+#define FLAG_MIN (PL_MIN_CONST + '0 0 -13')
+#define FLAG_MAX (PL_MAX_CONST + '0 0 -13')
 
 const float FLAG_SCALE = 0.6;
 
@@ -25,14 +25,14 @@ const float FLAG_THINKRATE = 0.2;
 const float FLAG_TOUCHRATE = 0.5;
 const float WPFE_THINKRATE = 0.5;
 
-#define FLAG_DROP_OFFSET ('0 0 32')
-#define FLAG_CARRY_OFFSET ('-16 0 8')
-#define FLAG_SPAWN_OFFSET ('0 0 1' * (PL_MAX_z - 13))
-#define FLAG_WAYPOINT_OFFSET ('0 0 64')
-#define FLAG_FLOAT_OFFSET ('0 0 32')
-#define FLAG_PASS_ARC_OFFSET ('0 0 -10')
+const vector FLAG_DROP_OFFSET = ('0 0 32');
+const vector FLAG_CARRY_OFFSET = ('-16 0 8');
+#define FLAG_SPAWN_OFFSET ('0 0 1' * (PL_MAX_CONST.z - 13))
+const vector FLAG_WAYPOINT_OFFSET = ('0 0 64');
+const vector FLAG_FLOAT_OFFSET = ('0 0 32');
+const vector FLAG_PASS_ARC_OFFSET = ('0 0 -10');
 
-#define VEHICLE_FLAG_OFFSET ('0 0 96')
+const vector VEHICLE_FLAG_OFFSET = ('0 0 96');
 const float VEHICLE_FLAG_SCALE = 1.0;
 
 // waypoint colors
@@ -71,27 +71,29 @@ float wpforenemy_announced;
 float wpforenemy_nextthink;
 
 // statuses
-const float FLAG_BASE = 1;
-const float FLAG_DROPPED = 2;
-const float FLAG_CARRY = 3;
-const float FLAG_PASSING = 4;
+const int FLAG_BASE = 1;
+const int FLAG_DROPPED = 2;
+const int FLAG_CARRY = 3;
+const int FLAG_PASSING = 4;
 
-const float DROP_NORMAL = 1;
-const float DROP_THROW = 2;
-const float DROP_PASS = 3;
-const float DROP_RESET = 4;
+const int DROP_NORMAL = 1;
+const int DROP_THROW = 2;
+const int DROP_PASS = 3;
+const int DROP_RESET = 4;
 
-const float PICKUP_BASE = 1;
-const float PICKUP_DROPPED = 2;
+const int PICKUP_BASE = 1;
+const int PICKUP_DROPPED = 2;
 
-const float CAPTURE_NORMAL = 1;
-const float CAPTURE_DROPPED = 2;
+const int CAPTURE_NORMAL = 1;
+const int CAPTURE_DROPPED = 2;
 
-const float RETURN_TIMEOUT = 1;
-const float RETURN_DROPPED = 2;
-const float RETURN_DAMAGE = 3;
-const float RETURN_SPEEDRUN = 4;
-const float RETURN_NEEDKILL = 5;
+const int RETURN_TIMEOUT = 1;
+const int RETURN_DROPPED = 2;
+const int RETURN_DAMAGE = 3;
+const int RETURN_SPEEDRUN = 4;
+const int RETURN_NEEDKILL = 5;
+
+void ctf_Handle_Throw(entity player, entity receiver, float droptype);
 
 // flag properties
 #define ctf_spawnorigin dropped_origin
@@ -103,6 +105,7 @@ float ctf_captimerecord; // record time for capturing the flag
 .entity ctf_dropper; // don't allow spam of dropping the flag
 .float max_flag_health;
 .float next_take_time;
+.float ctf_thinkrate;
 
 // passing/throwing properties
 .float pass_distance;
@@ -119,15 +122,15 @@ float ctf_captureshield_max_ratio; // punish at most 30% of each team
 float ctf_captureshield_force; // push force of the shield
 
 // bot player logic
-const float HAVOCBOT_CTF_ROLE_NONE = 0;
-const float HAVOCBOT_CTF_ROLE_DEFENSE = 2;
-const float HAVOCBOT_CTF_ROLE_MIDDLE = 4;
-const float HAVOCBOT_CTF_ROLE_OFFENSE = 8;
-const float HAVOCBOT_CTF_ROLE_CARRIER = 16;
-const float HAVOCBOT_CTF_ROLE_RETRIEVER = 32;
-const float HAVOCBOT_CTF_ROLE_ESCORT = 64;
-
-.float havocbot_cantfindflag;
+const int HAVOCBOT_CTF_ROLE_NONE = 0;
+const int HAVOCBOT_CTF_ROLE_DEFENSE = 2;
+const int HAVOCBOT_CTF_ROLE_MIDDLE = 4;
+const int HAVOCBOT_CTF_ROLE_OFFENSE = 8;
+const int HAVOCBOT_CTF_ROLE_CARRIER = 16;
+const int HAVOCBOT_CTF_ROLE_RETRIEVER = 32;
+const int HAVOCBOT_CTF_ROLE_ESCORT = 64;
+
+.bool havocbot_cantfindflag;
 
 vector havocbot_ctf_middlepoint;
 float havocbot_ctf_middlepoint_radius;
index 0886a9ce59921cf205bc71dba4a89bc9897b3846..50aa5e1fc51d48b87c7112c719a6924e2becb01b 100644 (file)
@@ -1,3 +1,10 @@
+#include "gamemode_cts.qh"
+#include "../_all.qh"
+
+#include "gamemode.qh"
+
+#include "../race.qh"
+
 // legacy bot roles
 .float race_checkpoint;
 void havocbot_role_cts()
index dd6e8b2109be3b97ceab791a5874a8ec94edf880..c365eddd300a9cb4a32fddc34c9760d8abe50e23 100644 (file)
@@ -1,3 +1,8 @@
+#include "gamemode_domination.qh"
+#include "../_all.qh"
+
+#include "gamemode.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)
index d6285cdafd112509b99e8c9ffcacd6b0430e3abe..fd3a9deb407fecfeefc7140f412428ff60ab0ceb 100644 (file)
@@ -1,8 +1,7 @@
-.float freezetag_frozen_time;
-.float freezetag_frozen_timeout;
-const float ICE_MAX_ALPHA = 1;
-const float ICE_MIN_ALPHA = 0.1;
-float freezetag_teams;
+#include "gamemode_freezetag.qh"
+#include "../_all.qh"
+
+#include "gamemode.qh"
 
 const float SP_FREEZETAG_REVIVALS = 4;
 void freezetag_ScoreRules(float teams)
@@ -425,7 +424,6 @@ MUTATOR_HOOKFUNCTION(freezetag_GiveFragsForKill)
        return 1;
 }
 
-.float reviving; // temp var
 MUTATOR_HOOKFUNCTION(freezetag_PlayerPreThink)
 {
        float n;
@@ -526,6 +524,21 @@ MUTATOR_HOOKFUNCTION(freezetag_PlayerPreThink)
        return 1;
 }
 
+MUTATOR_HOOKFUNCTION(freezetag_SetStartItems)
+{
+       start_items &= ~IT_UNLIMITED_AMMO;
+       //start_health       = warmup_start_health       = cvar("g_lms_start_health");
+       //start_armorvalue   = warmup_start_armorvalue   = cvar("g_lms_start_armor");
+       start_ammo_shells  = warmup_start_ammo_shells  = cvar("g_lms_start_ammo_shells");
+       start_ammo_nails   = warmup_start_ammo_nails   = cvar("g_lms_start_ammo_nails");
+       start_ammo_rockets = warmup_start_ammo_rockets = cvar("g_lms_start_ammo_rockets");
+       start_ammo_cells   = warmup_start_ammo_cells   = cvar("g_lms_start_ammo_cells");
+       start_ammo_plasma  = warmup_start_ammo_plasma  = cvar("g_lms_start_ammo_plasma");
+       start_ammo_fuel    = warmup_start_ammo_fuel    = cvar("g_lms_start_ammo_fuel");
+
+       return 0;
+}
+
 MUTATOR_HOOKFUNCTION(freezetag_BotRoles)
 {
        if (!self.deadflag)
@@ -573,6 +586,7 @@ MUTATOR_DEFINITION(gamemode_freezetag)
        MUTATOR_HOOK(reset_map_players, freezetag_reset_map_players, CBC_ORDER_ANY);
        MUTATOR_HOOK(GiveFragsForKill, freezetag_GiveFragsForKill, CBC_ORDER_FIRST);
        MUTATOR_HOOK(PlayerPreThink, freezetag_PlayerPreThink, CBC_ORDER_FIRST);
+       MUTATOR_HOOK(SetStartItems, freezetag_SetStartItems, CBC_ORDER_ANY);
        MUTATOR_HOOK(HavocBot_ChooseRole, freezetag_BotRoles, CBC_ORDER_ANY);
        MUTATOR_HOOK(GetTeamCount, freezetag_GetTeamCount, CBC_ORDER_EXCLUSIVE);
 
diff --git a/qcsrc/server/mutators/gamemode_freezetag.qh b/qcsrc/server/mutators/gamemode_freezetag.qh
new file mode 100644 (file)
index 0000000..19489fc
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef GAMEMODE_FREEZETAG_H
+#define GAMEMODE_FREEZETAG_H
+.float freezetag_frozen_time;
+.float freezetag_frozen_timeout;
+const float ICE_MAX_ALPHA = 1;
+const float ICE_MIN_ALPHA = 0.1;
+float freezetag_teams;
+
+.float reviving; // temp var
+
+#endif
index fe0d0a7ecc4094048a9a7b878e2428a0ad258523..c5f71ea1f376ed60487ec1e841b41b4c51a33fe0 100644 (file)
@@ -1,3 +1,11 @@
+#include "gamemode_invasion.qh"
+#include "../_all.qh"
+
+#include "gamemode.qh"
+
+#include "../../common/monsters/spawn.qh"
+#include "../../common/monsters/sv_monsters.qh"
+
 void spawnfunc_invasion_spawnpoint()
 {
        if(!g_invasion) { remove(self); return; }
index 095857e14325ebf83550b5feee918024d9bb07e4..ed69612d15c42e6f0e5abe4cf0e02c4ed811f30b 100644 (file)
@@ -1,3 +1,8 @@
+#include "gamemode_keepaway.qh"
+#include "../_all.qh"
+
+#include "gamemode.qh"
+
 // ===========================================================
 //  Keepaway game mode coding, written by Samual and Diabolik
 //  Last updated: September, 2012
@@ -20,6 +25,7 @@ void ka_EventLog(string mode, entity actor) // use an alias for easy changing an
                GameLogEcho(strcat(":ka:", mode, ((actor != world) ? (strcat(":", ftos(actor.playerid))) : "")));
 }
 
+void ka_TouchEvent();
 void ka_RespawnBall() // runs whenever the ball needs to be relocated
 {
        if(gameover) { return; }
@@ -37,6 +43,7 @@ void ka_RespawnBall() // runs whenever the ball needs to be relocated
        self.velocity = '0 0 200';
        self.angles = '0 0 0';
        self.effects = autocvar_g_keepawayball_effects;
+       self.touch = ka_TouchEvent;
        self.think = ka_RespawnBall;
        self.nextthink = time + autocvar_g_keepawayball_respawntime;
 
@@ -164,7 +171,14 @@ void ka_Reset() // used to clear the ballcarrier whenever the match switches fro
        if((self.owner) && (IS_PLAYER(self.owner)))
                ka_DropEvent(self.owner);
 
-       ka_RespawnBall();
+       if(time < game_starttime)
+       {
+               self.think = ka_RespawnBall;
+               self.touch = func_null;
+               self.nextthink = game_starttime;
+       }
+       else
+               ka_RespawnBall();
 }
 
 
@@ -187,9 +201,8 @@ void havocbot_goalrating_ball(float ratingscale, vector org)
                t = (self.health + self.armorvalue) / (ball_owner.health + ball_owner.armorvalue);
                navigation_routerating(ball_owner, t * ratingscale, 2000);
        }
-
-       // Ball has been dropped so collect.
-       navigation_routerating(ka_ball, ratingscale, 2000);
+       else // Ball has been dropped so collect.
+               navigation_routerating(ka_ball, ratingscale, 2000);
 }
 
 void havocbot_role_ka_carrier()
index fd9ed4f2f0e98b9b2c5a29ce9b0736dd99df4187..250f2fbc9f45979a0e48c05c454e0ec6f4a5f000 100644 (file)
@@ -11,4 +11,7 @@ const float SP_KEEPAWAY_BCTIME = 6;
 
 void() havocbot_role_ka_carrier;
 void() havocbot_role_ka_collector;
+
+void ka_DropEvent(entity plyr);
+
 #endif
index 2a67316101f846261dc819f6476bf7ef23f539e7..3771093a20a193de21ac10029961d24f61f4b438 100644 (file)
@@ -1,4 +1,8 @@
-#define FOR_EACH_KH_KEY(v) for(v = kh_worldkeylist; v; v = v.kh_worldkeynext )
+#include "gamemode_keyhunt.qh"
+#include "../_all.qh"
+
+#include "gamemode.qh"
+
 
 // #define KH_PLAYER_USE_ATTACHMENT
 // #define KH_PLAYER_USE_CARRIEDMODEL
@@ -271,7 +275,7 @@ void kh_Key_Detach(entity key) // runs every time a key is dropped or lost. Runs
        }
        // in any case:
        setattachment(key, world, "");
-       setorigin(key, key.owner.origin + '0 0 1' * (PL_MIN_z - KH_KEY_MIN_z));
+       setorigin(key, key.owner.origin + '0 0 1' * (PL_MIN.z - KH_KEY_MIN_z));
        key.angles = key.owner.angles;
 #else
        setorigin(key, key.owner.origin + key.origin.z * '0 0 1');
@@ -397,7 +401,7 @@ void kh_Key_AssignTo(entity key, entity player)  // runs every time a key is pic
        }
 }
 
-void kh_Key_Damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
+void kh_Key_Damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
 {
        if(self.owner)
                return;
index 6b27431c2207cc81f39319b3d6c580477451d2cc..4d1645d02c0201ecebe82485e1f771f025e69b82 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef GAMEMODE_KEYHUNT_H
 #define GAMEMODE_KEYHUNT_H
 
+#define FOR_EACH_KH_KEY(v) for(v = kh_worldkeylist; v; v = v.kh_worldkeynext )
+
 // ALL OF THESE should be removed in the future, as other code should not have to care
 
 // used by bots:
@@ -11,4 +13,7 @@ float kh_Key_AllOwnedByWhichTeam();
 typedef void(void) kh_Think_t;
 void kh_StartRound();
 void kh_Controller_SetThink(float t, kh_Think_t func);
+
+void kh_Key_DropAll(entity player, float suicide);
+
 #endif
index 13b77305a25429c78dd95768701167057b7a699e..61e51451fbaf9d354407568d20706a92b857fa5a 100644 (file)
@@ -1,3 +1,11 @@
+#include "gamemode_lms.qh"
+#include "../_all.qh"
+
+#include "gamemode.qh"
+
+#include "../campaign.qh"
+#include "../command/cmd.qh"
+
 // main functions
 float LMS_NewPlayerLives()
 {
index afdb769cf6b0c4025bc6e31f7f175f1557520982..9844875b3d9eb27ac56efc69049e59aed1a70f2c 100644 (file)
@@ -1,3 +1,8 @@
+#include "gamemode_nexball.qh"
+#include "../_all.qh"
+
+#include "gamemode.qh"
+
 float autocvar_g_nexball_safepass_turnrate;
 float autocvar_g_nexball_safepass_maxdist;
 float autocvar_g_nexball_safepass_holdtime;
index d1f20f7ee950e5e3af577fe9dcbc154302cda51a..c99643169ba598907d83c97e22a4dc58e7f6f89b 100644 (file)
@@ -1,3 +1,7 @@
+#include "../_all.qh"
+
+#include "gamemode.qh"
+
 float autocvar_g_onslaught_spawn_at_controlpoints;
 float autocvar_g_onslaught_spawn_at_generator;
 float autocvar_g_onslaught_cp_proxydecap;
@@ -25,7 +29,7 @@ void onslaught_link_checkupdate();
 entity ons_red_generator;
 entity ons_blue_generator;
 
-void ons_gib_damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector vforce)
+void ons_gib_damage (entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector vforce)
 {
        self.velocity = self.velocity + vforce;
 }
@@ -570,7 +574,7 @@ void onslaught_generator_deaththink()
        self.count = self.count - 1;
 }
 
-void onslaught_generator_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
+void onslaught_generator_damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
 {
        float i;
        if (damage <= 0)
@@ -966,7 +970,7 @@ void spawnfunc_onslaught_generator()
 float ons_notification_time_team1;
 float ons_notification_time_team2;
 
-void onslaught_controlpoint_icon_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
+void onslaught_controlpoint_icon_damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
 {
        entity oself;
        float nag;
index 7ba8328469765b40513ba9160aceb139b2bf3873..3cefc86692f6d6e8fbc9d6a094f424bdc5e4b01c 100644 (file)
@@ -1,3 +1,10 @@
+#include "gamemode_race.qh"
+#include "../_all.qh"
+
+#include "gamemode.qh"
+
+#include "../race.qh"
+
 // legacy bot roles
 .float race_checkpoint;
 void havocbot_role_race()
index de172873e29255af8f14c0c8ae972758519f5c60..afff8bdb2583dc8a187b0814c56e8d75ead365e7 100644 (file)
@@ -1,3 +1,7 @@
+#include "../_all.qh"
+
+#include "gamemode.qh"
+
 /*QUAKED spawnfunc_tdm_team (0 .5 .8) (-16 -16 -24) (16 16 32)
 Team declaration for TDM gameplay, this allows you to decide what team names and control point models are used in your map.
 Note: If you use spawnfunc_tdm_team entities you must define at least 2!  However, unlike domination, you don't need to make a blank one too.
diff --git a/qcsrc/server/mutators/mutator.qh b/qcsrc/server/mutators/mutator.qh
new file mode 100644 (file)
index 0000000..36bf631
--- /dev/null
@@ -0,0 +1,47 @@
+#ifndef MUTATOR_H
+#define MUTATOR_H
+
+#include "base.qh"
+#include "mutator_nades.qh"
+
+#include "../cl_client.qh"
+#include "../cl_player.qh"
+#include "../cl_impulse.qh"
+#include "../cheats.qh"
+#include "../g_damage.qh"
+#include "../round_handler.qh"
+#include "../scores.qh"
+#include "../scores_rules.qh"
+#include "../waypointsprites.qh"
+
+#include "../bot/bot.qh"
+#include "../bot/navigation.qh"
+#include "../bot/waypoints.qh"
+
+#include "../bot/havocbot/havocbot.qh"
+#include "../bot/havocbot/roles.qh"
+#include "../bot/havocbot/role_keyhunt.qh"
+
+#include "../command/vote.qh"
+#include "../command/common.qh"
+
+#include "../weapons/common.qh"
+#include "../weapons/tracing.qh"
+#include "../weapons/throwing.qh"
+#include "../weapons/weaponsystem.qh"
+
+#include "../../common/deathtypes.qh"
+#include "../../common/notifications.qh"
+#include "../../common/triggers/teleporters.qh"
+#include "../../common/triggers/subs.qh"
+#include "../../common/stats.qh"
+#include "../../common/teams.qh"
+
+#include "../../common/monsters/all.qh"
+
+#include "../../warpzonelib/anglestransform.qh"
+#include "../../warpzonelib/mathlib.qh"
+#include "../../warpzonelib/server.qh"
+#include "../../warpzonelib/util_server.qh"
+
+#endif
index 08e14199ee3f4d460044f02f056cc2750b2692a0..eb179a0c8c8499b73dba3c150a985d21b26280d8 100644 (file)
@@ -1,3 +1,7 @@
+#include "../_all.qh"
+
+#include "mutator.qh"
+
 .float bloodloss_timer;
 
 MUTATOR_HOOKFUNCTION(bloodloss_PlayerThink)
index 7dfdaca6225f8c6c5c1b0164e1f43d99fa6663ee..e8366cd31ee2787dedc99fa358a521b35d8c46a7 100644 (file)
@@ -1,3 +1,12 @@
+#include "mutator_buffs.qh"
+#include "../_all.qh"
+
+#include "mutator.qh"
+
+#include "../../common/buffs.qh"
+
+.float lifetime;
+
 float buffs_BuffModel_Customize()
 {
        entity player, myowner;
@@ -524,7 +533,6 @@ MUTATOR_HOOKFUNCTION(buffs_PlayerJump)
 {
        if(self.buffs & BUFF_JUMP)
                player_jumpheight = autocvar_g_buffs_jump_height;
-       self.stat_jumpheight = player_jumpheight;
 
        return false;
 }
@@ -934,7 +942,6 @@ void buffs_Initialize()
 
        addstat(STAT_BUFFS, AS_INT, buffs);
        addstat(STAT_BUFF_TIME, AS_FLOAT, buff_time);
-       addstat(STAT_MOVEVARS_JUMPVELOCITY, AS_FLOAT, stat_jumpheight);
 
        InitializeEntity(world, buffs_DelayedInit, INITPRIO_FINDTARGET);
 }
index af600a4a6cf8aa8e09d89db0a35ecc05c752dad1..29e59316f216cd729f0fb012e29e1504cbf2e64b 100644 (file)
@@ -10,8 +10,6 @@
 .float buff_invisible_prev_alpha;
 // flight
 .float buff_flight_prev_gravity;
-// jump
-.float stat_jumpheight;
 // disability
 .float buff_disability_time;
 .float buff_disability_effect_time;
index 21dd71f98b5dfc74302c10c01510b37073ee2fb3..bacc590b78d731f3d639ae99cbf7cbbc3ef554f8 100644 (file)
@@ -1,3 +1,9 @@
+#include "../_all.qh"
+
+#include "mutator.qh"
+
+#include "../campaign.qh"
+
 .float campcheck_nextcheck;
 .float campcheck_traveled_distance;
 
index ad52d3e2919f29a3563927a4c900ca401f35ee40..ab70fb217da5829ae99d1df98c8dd7c9e5dfb007 100644 (file)
@@ -1,6 +1,63 @@
+#ifdef CSQC
+       #define PHYS_DODGING_FRAMETIME                          (1 / (frametime <= 0 ? 60 : frametime))
+       #define PHYS_DODGING                                            getstati(STAT_DODGING)
+       #define PHYS_DODGING_DELAY                                      getstatf(STAT_DODGING_DELAY)
+       #define PHYS_DODGING_TIMEOUT(s)                         getstatf(STAT_DODGING_TIMEOUT)
+       #define PHYS_DODGING_HORIZ_SPEED_FROZEN         getstatf(STAT_DODGING_HORIZ_SPEED_FROZEN)
+       #define PHYS_DODGING_FROZEN_NODOUBLETAP         getstati(STAT_DODGING_FROZEN_NO_DOUBLETAP)
+       #define PHYS_DODGING_HORIZ_SPEED                        getstatf(STAT_DODGING_HORIZ_SPEED)
+       #define PHYS_DODGING_PRESSED_KEYS(s)            s.pressedkeys
+       #define PHYS_DODGING_HEIGHT_THRESHOLD           getstatf(STAT_DODGING_HEIGHT_THRESHOLD)
+       #define PHYS_DODGING_DISTANCE_THRESHOLD         getstatf(STAT_DODGING_DISTANCE_THRESHOLD)
+       #define PHYS_DODGING_RAMP_TIME                          getstatf(STAT_DODGING_RAMP_TIME)
+       #define PHYS_DODGING_UP_SPEED                           getstatf(STAT_DODGING_UP_SPEED)
+       #define PHYS_DODGING_WALL                                       getstatf(STAT_DODGING_WALL)
+#elif defined(SVQC)
+       #define PHYS_DODGING_FRAMETIME                          sys_frametime
+       #define PHYS_DODGING                                            g_dodging
+       #define PHYS_DODGING_DELAY                                      autocvar_sv_dodging_delay
+       #define PHYS_DODGING_TIMEOUT(s)                         s.cvar_cl_dodging_timeout
+       #define PHYS_DODGING_HORIZ_SPEED_FROZEN         autocvar_sv_dodging_horiz_speed_frozen
+       #define PHYS_DODGING_FROZEN_NODOUBLETAP         autocvar_sv_dodging_frozen_doubletap
+       #define PHYS_DODGING_HORIZ_SPEED                        autocvar_sv_dodging_horiz_speed
+       #define PHYS_DODGING_PRESSED_KEYS(s)            s.pressedkeys
+       #define PHYS_DODGING_HEIGHT_THRESHOLD           autocvar_sv_dodging_height_threshold
+       #define PHYS_DODGING_DISTANCE_THRESHOLD         autocvar_sv_dodging_wall_distance_threshold
+       #define PHYS_DODGING_RAMP_TIME                          autocvar_sv_dodging_ramp_time
+       #define PHYS_DODGING_UP_SPEED                           autocvar_sv_dodging_up_speed
+       #define PHYS_DODGING_WALL                                       autocvar_sv_dodging_wall_dodging
+#endif
+
+#ifdef SVQC
+#include "mutator_dodging.qh"
+#include "../_all.qh"
+
+#include "mutator.qh"
+
+#include "../../common/animdecide.qh"
 
 .float cvar_cl_dodging_timeout;
 
+.float stat_dodging;
+.float stat_dodging_delay;
+.float stat_dodging_horiz_speed_frozen;
+.float stat_dodging_frozen_nodoubletap;
+.float stat_dodging_frozen;
+.float stat_dodging_horiz_speed;
+.float stat_dodging_height_threshold;
+.float stat_dodging_distance_threshold;
+.float stat_dodging_ramp_time;
+.float stat_dodging_up_speed;
+.float stat_dodging_wall;
+
+#endif
+
+// set to 1 to indicate dodging has started.. reset by physics hook after dodge has been done..
+.float dodging_action;
+
+// the jump part of the dodge cannot be ramped
+.float dodging_single_action;
+
 
 // these are used to store the last key press time for each of the keys..
 .float last_FORWARD_KEY_time;
 // until it's 0.
 .float dodging_velocity_gain;
 
-MUTATOR_HOOKFUNCTION(dodging_GetCvars) {
-       GetCvars_handleFloat(get_cvars_s, get_cvars_f, cvar_cl_dodging_timeout, "cl_dodging_timeout");
-       return 0;
+#ifdef CSQC
+.int pressedkeys;
+
+#elif defined(SVQC)
+
+void dodging_UpdateStats()
+{
+       self.stat_dodging = PHYS_DODGING;
+       self.stat_dodging_delay = PHYS_DODGING_DELAY;
+       self.stat_dodging_horiz_speed_frozen = PHYS_DODGING_HORIZ_SPEED_FROZEN;
+       self.stat_dodging_frozen = PHYS_DODGING_FROZEN;
+       self.stat_dodging_frozen_nodoubletap = PHYS_DODGING_FROZEN_NODOUBLETAP;
+       self.stat_dodging_height_threshold = PHYS_DODGING_HEIGHT_THRESHOLD;
+       self.stat_dodging_distance_threshold = PHYS_DODGING_DISTANCE_THRESHOLD;
+       self.stat_dodging_ramp_time = PHYS_DODGING_RAMP_TIME;
+       self.stat_dodging_up_speed = PHYS_DODGING_UP_SPEED;
+       self.stat_dodging_wall = PHYS_DODGING_WALL;
 }
 
-MUTATOR_HOOKFUNCTION(dodging_PlayerPhysics) {
-       // print("dodging_PlayerPhysics\n");
+void dodging_Initialize()
+{
+       addstat(STAT_DODGING, AS_INT, stat_dodging);
+       addstat(STAT_DODGING_DELAY, AS_FLOAT, stat_dodging_delay);
+       addstat(STAT_DODGING_TIMEOUT, AS_FLOAT, cvar_cl_dodging_timeout); // we stat this, so it is updated on the client when updated on server (otherwise, chaos)
+       addstat(STAT_DODGING_FROZEN_NO_DOUBLETAP, AS_INT, stat_dodging_frozen_nodoubletap);
+       addstat(STAT_DODGING_HORIZ_SPEED_FROZEN, AS_FLOAT, stat_dodging_horiz_speed_frozen);
+       addstat(STAT_DODGING_FROZEN, AS_INT, stat_dodging_frozen);
+       addstat(STAT_DODGING_HORIZ_SPEED, AS_FLOAT, stat_dodging_horiz_speed);
+       addstat(STAT_DODGING_HEIGHT_THRESHOLD, AS_FLOAT, stat_dodging_height_threshold);
+       addstat(STAT_DODGING_DISTANCE_THRESHOLD, AS_FLOAT, stat_dodging_distance_threshold);
+       addstat(STAT_DODGING_RAMP_TIME, AS_FLOAT, stat_dodging_ramp_time);
+       addstat(STAT_DODGING_UP_SPEED, AS_FLOAT, stat_dodging_up_speed);
+       addstat(STAT_DODGING_WALL, AS_FLOAT, stat_dodging_wall);
+}
+
+#endif
+
+// returns 1 if the player is close to a wall
+bool check_close_to_wall(float threshold)
+{
+       if (PHYS_DODGING_WALL == 0) { return false; }
+
+       #define X(OFFSET)                                                                                                                               \
+       tracebox(self.origin, self.mins, self.maxs, self.origin + OFFSET, true, self);  \
+       if (trace_fraction < 1 && vlen (self.origin - trace_endpos) < threshold)                \
+               return true;
+       X(1000*v_right);
+       X(-1000*v_right);
+       X(1000*v_forward);
+       X(-1000*v_forward);
+       #undef X
+
+       return false;
+}
+
+bool check_close_to_ground(float threshold)
+{
+       return IS_ONGROUND(self) ? true : false;
+}
+
+float PM_dodging_checkpressedkeys()
+{
+       if(!PHYS_DODGING)
+               return false;
+
+       float frozen_dodging = (PHYS_FROZEN(self) && PHYS_DODGING_FROZEN);
+       float frozen_no_doubletap = (frozen_dodging && !PHYS_DODGING_FROZEN_NODOUBLETAP);
 
-       float common_factor;
-       float new_velocity_gain;
-       float velocity_difference;
-       float clean_up_and_do_nothing;
-       float horiz_speed = autocvar_sv_dodging_horiz_speed;
+       // first check if the last dodge is far enough back in time so we can dodge again
+       if ((time - self.last_dodging_time) < PHYS_DODGING_DELAY)
+               return false;
+
+       makevectors(self.angles);
+
+       if (check_close_to_ground(PHYS_DODGING_HEIGHT_THRESHOLD) != 1
+               && check_close_to_wall(PHYS_DODGING_DISTANCE_THRESHOLD) != 1)
+               return true;
+
+       float tap_direction_x = 0;
+       float tap_direction_y = 0;
+       float dodge_detected = 0;
+
+       #define X(COND,BTN,RESULT)                                                                                                                      \
+       if (self.movement_##COND)                                                                                               \
+               /* is this a state change? */                                                                                                   \
+               if(!(PHYS_DODGING_PRESSED_KEYS(self) & KEY_##BTN) || frozen_no_doubletap) {             \
+                               tap_direction_##RESULT;                                                                                                 \
+                               if ((time - self.last_##BTN##_KEY_time) < PHYS_DODGING_TIMEOUT(self))   \
+                                       dodge_detected = 1;                                                                                                     \
+                               self.last_##BTN##_KEY_time = time;                                                                              \
+               }
+       X(x < 0, BACKWARD,      x--);
+       X(x > 0, FORWARD,       x++);
+       X(y < 0, LEFT,          y--);
+       X(y > 0, RIGHT,         y++);
+       #undef X
+
+       if (dodge_detected == 1)
+       {
+               self.last_dodging_time = time;
+
+               self.dodging_action = 1;
+               self.dodging_single_action = 1;
+
+               self.dodging_velocity_gain = PHYS_DODGING_HORIZ_SPEED;
+
+               self.dodging_direction_x = tap_direction_x;
+               self.dodging_direction_y = tap_direction_y;
 
-       if(self.frozen)
-               horiz_speed = autocvar_sv_dodging_horiz_speed_frozen;
+               // normalize the dodging_direction vector.. (unlike UT99) XD
+               float length = self.dodging_direction_x * self.dodging_direction_x
+                                       + self.dodging_direction_y * self.dodging_direction_y;
+               length = sqrt(length);
+
+               self.dodging_direction_x = self.dodging_direction_x * 1.0 / length;
+               self.dodging_direction_y = self.dodging_direction_y * 1.0 / length;
+               return true;
+       }
+       return false;
+}
 
-    if (self.deadflag != DEAD_NO)
-        return 0;
+void PM_dodging()
+{
+       if (!PHYS_DODGING)
+               return;
 
-       new_velocity_gain = 0;
-       clean_up_and_do_nothing = 0;
+#ifdef SVQC
+       dodging_UpdateStats();
+#endif
 
-       if (g_dodging == 0)
-               clean_up_and_do_nothing = 1;
+    if (PHYS_DEAD(self))
+        return;
 
        // when swimming, no dodging allowed..
        if (self.waterlevel >= WATERLEVEL_SWIMMING)
-               clean_up_and_do_nothing = 1;
-
-       if (clean_up_and_do_nothing != 0) {
+       {
                self.dodging_action = 0;
                self.dodging_direction_x = 0;
                self.dodging_direction_y = 0;
-               return 0;
+               return;
        }
 
        // make sure v_up, v_right and v_forward are sane
@@ -63,190 +225,77 @@ MUTATOR_HOOKFUNCTION(dodging_PlayerPhysics) {
        // if we have e.g. 0.5 sec ramptime and a frametime of 0.25, then the ramp code
        // will be called ramp_time/frametime times = 2 times. so, we need to
        // add 0.5 * the total speed each frame until the dodge action is done..
-       common_factor = sys_frametime / autocvar_sv_dodging_ramp_time;
+       float common_factor = PHYS_DODGING_FRAMETIME / PHYS_DODGING_RAMP_TIME;
 
        // if ramp time is smaller than frametime we get problems ;D
-       if (common_factor > 1)
-               common_factor = 1;
+       common_factor = min(common_factor, 1);
 
-       new_velocity_gain = self.dodging_velocity_gain - (common_factor * horiz_speed);
-       if (new_velocity_gain < 0)
-               new_velocity_gain = 0;
+       float horiz_speed = PHYS_FROZEN(self) ? PHYS_DODGING_HORIZ_SPEED_FROZEN : PHYS_DODGING_HORIZ_SPEED;
+       float new_velocity_gain = self.dodging_velocity_gain - (common_factor * horiz_speed);
+       new_velocity_gain = max(0, new_velocity_gain);
 
-       velocity_difference = self.dodging_velocity_gain - new_velocity_gain;
+       float velocity_difference = self.dodging_velocity_gain - new_velocity_gain;
 
        // ramp up dodging speed by adding some velocity each frame.. TODO: do it! :D
-       if (self.dodging_action == 1) {
+       if (self.dodging_action == 1)
+       {
                //disable jump key during dodge accel phase
-               if (self.movement.z > 0) self.movement_z = 0;
+               if(self.movement_z > 0) { self.movement_z = 0; }
 
-               self.velocity =
-                         self.velocity
-                       + ((self.dodging_direction.y * velocity_difference) * v_right)
-                       + ((self.dodging_direction.x * velocity_difference) * v_forward);
+               self.velocity += ((self.dodging_direction_y * velocity_difference) * v_right)
+                                       + ((self.dodging_direction_x * velocity_difference) * v_forward);
 
                self.dodging_velocity_gain = self.dodging_velocity_gain - velocity_difference;
        }
 
        // the up part of the dodge is a single shot action
-       if (self.dodging_single_action == 1) {
-               self.flags &= ~FL_ONGROUND;
+       if (self.dodging_single_action == 1)
+       {
+               UNSET_ONGROUND(self);
 
-               self.velocity =
-                         self.velocity
-                       + (autocvar_sv_dodging_up_speed * v_up);
+               self.velocity += PHYS_DODGING_UP_SPEED * v_up;
 
-               if (autocvar_sv_dodging_sound == 1)
+#ifdef SVQC
+               if (autocvar_sv_dodging_sound)
                        PlayerSound(playersound_jump, CH_PLAYER, VOICETYPE_PLAYERSOUND);
 
                animdecide_setaction(self, ANIMACTION_JUMP, true);
+#endif
 
                self.dodging_single_action = 0;
        }
 
        // are we done with the dodging ramp yet?
-       if((self.dodging_action == 1) && ((time - self.last_dodging_time) > autocvar_sv_dodging_ramp_time))
+       if((self.dodging_action == 1) && ((time - self.last_dodging_time) > PHYS_DODGING_RAMP_TIME))
        {
                // reset state so next dodge can be done correctly
                self.dodging_action = 0;
                self.dodging_direction_x = 0;
                self.dodging_direction_y = 0;
        }
-
-       return 0;
 }
 
+#ifdef SVQC
 
-// returns 1 if the player is close to a wall
-float check_close_to_wall(float threshold) {
-       if (autocvar_sv_dodging_wall_dodging == 0)
-               return 0;
-
-       vector trace_start;
-       vector trace_end;
-
-       trace_start = self.origin;
-
-       trace_end = self.origin + (1000*v_right);
-       tracebox(trace_start, self.mins, self.maxs, trace_end, true, self);
-       if (trace_fraction < 1 && vlen (self.origin - trace_endpos) < threshold)
-               return 1;
-
-       trace_end = self.origin - (1000*v_right);
-       tracebox(trace_start, self.mins, self.maxs, trace_end, true, self);
-       if (trace_fraction < 1 && vlen (self.origin - trace_endpos) < threshold)
-               return 1;
-
-       trace_end = self.origin + (1000*v_forward);
-       tracebox(trace_start, self.mins, self.maxs, trace_end, true, self);
-       if (trace_fraction < 1 && vlen (self.origin - trace_endpos) < threshold)
-               return 1;
-
-       trace_end = self.origin - (1000*v_forward);
-       tracebox(trace_start, self.mins, self.maxs, trace_end, true, self);
-       if (trace_fraction < 1 && vlen (self.origin - trace_endpos) < threshold)
-               return 1;
-
-       return 0;
-}
-
-float check_close_to_ground(float threshold) {
-       if (self.flags & FL_ONGROUND)
-               return 1;
-
-       return 0;
+MUTATOR_HOOKFUNCTION(dodging_GetCvars)
+{
+       GetCvars_handleFloat(get_cvars_s, get_cvars_f, cvar_cl_dodging_timeout, "cl_dodging_timeout");
+       return false;
 }
 
-
-MUTATOR_HOOKFUNCTION(dodging_GetPressedKeys) {
+MUTATOR_HOOKFUNCTION(dodging_PlayerPhysics)
+{
        // print("dodging_PlayerPhysics\n");
+       PM_dodging();
 
-       float length;
-       vector tap_direction = '0 0 0';
-
-       float frozen_dodging, frozen_no_doubletap;
-       frozen_dodging = (self.frozen && autocvar_sv_dodging_frozen);
-       frozen_no_doubletap = (frozen_dodging && !autocvar_sv_dodging_frozen_doubletap);
-
-       float dodge_detected;
-       if (g_dodging == 0)
-               return 0;
-
-       dodge_detected = 0;
-
-       // first check if the last dodge is far enough back in time so we can dodge again
-       if ((time - self.last_dodging_time) < autocvar_sv_dodging_delay)
-               return 0;
-
-       if (check_close_to_ground(autocvar_sv_dodging_height_threshold) != 1
-               && check_close_to_wall(autocvar_sv_dodging_wall_distance_threshold) != 1)
-               return 0;
-
-       if (self.movement.x > 0) {
-               // is this a state change?
-               if (!(self.pressedkeys & KEY_FORWARD) || frozen_no_doubletap) {
-                       if ((time - self.last_FORWARD_KEY_time) < self.cvar_cl_dodging_timeout) {
-                               tap_direction.x = 1.0;
-                               dodge_detected = 1;
-                       }
-                       self.last_FORWARD_KEY_time = time;
-               }
-       }
-
-       if (self.movement.x < 0) {
-               // is this a state change?
-               if (!(self.pressedkeys & KEY_BACKWARD) || frozen_no_doubletap) {
-                       tap_direction.x = -1.0;
-                       if ((time - self.last_BACKWARD_KEY_time) < self.cvar_cl_dodging_timeout)        {
-                               dodge_detected = 1;
-                       }
-                       self.last_BACKWARD_KEY_time = time;
-               }
-       }
-
-       if (self.movement.y > 0) {
-               // is this a state change?
-               if (!(self.pressedkeys & KEY_RIGHT) || frozen_no_doubletap) {
-                       tap_direction.y = 1.0;
-                       if ((time - self.last_RIGHT_KEY_time) < self.cvar_cl_dodging_timeout)   {
-                               dodge_detected = 1;
-                       }
-                       self.last_RIGHT_KEY_time = time;
-               }
-       }
-
-       if (self.movement.y < 0) {
-               // is this a state change?
-               if (!(self.pressedkeys & KEY_LEFT) || frozen_no_doubletap) {
-                       tap_direction.y = -1.0;
-                       if ((time - self.last_LEFT_KEY_time) < self.cvar_cl_dodging_timeout)    {
-                               dodge_detected = 1;
-                       }
-                       self.last_LEFT_KEY_time = time;
-               }
-       }
-
-       if (dodge_detected == 1) {
-               self.last_dodging_time = time;
-
-               self.dodging_action = 1;
-               self.dodging_single_action = 1;
-
-               self.dodging_velocity_gain = autocvar_sv_dodging_horiz_speed;
-
-               self.dodging_direction_x = tap_direction.x;
-               self.dodging_direction_y = tap_direction.y;
-
-               // normalize the dodging_direction vector.. (unlike UT99) XD
-               length =          self.dodging_direction.x * self.dodging_direction.x;
-               length = length + self.dodging_direction.y * self.dodging_direction.y;
-               length = sqrt(length);
+       return false;
+}
 
-               self.dodging_direction_x = self.dodging_direction.x * 1.0/length;
-               self.dodging_direction_y = self.dodging_direction.y * 1.0/length;
-       }
+MUTATOR_HOOKFUNCTION(dodging_GetPressedKeys)
+{
+       PM_dodging_checkpressedkeys();
 
-       return 0;
+       return false;
 }
 
 MUTATOR_DEFINITION(mutator_dodging)
@@ -264,7 +313,8 @@ MUTATOR_DEFINITION(mutator_dodging)
        // this just turns on the cvar.
        MUTATOR_ONADD
        {
-               g_dodging = 1;
+               g_dodging = cvar("g_dodging");
+               dodging_Initialize();
        }
 
        // this just turns off the cvar.
@@ -273,9 +323,6 @@ MUTATOR_DEFINITION(mutator_dodging)
                g_dodging = 0;
        }
 
-       MUTATOR_ONREMOVE
-       {
-       }
-
-       return 0;
+       return false;
 }
+#endif
index b3502b0f783573c6467ec9752dc13d4d13326f0b..17381d34aba82e5151b09c7d9e4fed29d03f24f7 100644 (file)
@@ -1,20 +1,25 @@
+#include "../_all.qh"
+
+#include "mutator.qh"
+
+#include "../cl_client.qh"
+#include "../../common/buffs.qh"
+
+#include "../../common/items/all.qc"
+
 void spawnfunc_item_minst_cells (void)
 {
        if (!g_instagib) { remove(self); return; }
        if (!self.ammo_cells)
                self.ammo_cells = autocvar_g_instagib_ammo_drop;
 
-       StartItem ("models/items/a_cells.md3",
-                          "misc/itempickup.wav", 45, 0,
-                          "Vaporizer Ammo", IT_CELLS, 0, 0, generic_pickupevalfunc, 100);
+       StartItemA (ITEM_VaporizerCells);
 }
 
 void instagib_health_mega()
 {
        self.max_health = 1;
-       StartItem ("models/items/g_h100.md3",
-                          "misc/megahealth.wav", g_pickup_respawntime_powerup, g_pickup_respawntimejitter_powerup,
-                          "Extralife", IT_NAILS, 0, FL_POWERUP, generic_pickupevalfunc, BOT_PICKUP_RATING_HIGH);
+       StartItemA (ITEM_ExtraLife);
 }
 
 .float instagib_nextthink;
diff --git a/qcsrc/server/mutators/mutator_instagib_items.qc b/qcsrc/server/mutators/mutator_instagib_items.qc
new file mode 100644 (file)
index 0000000..40340b1
--- /dev/null
@@ -0,0 +1,41 @@
+#include "../../common/items/item.qh"
+
+#define WITH(it) this.m_##it;
+#define CONFIGURE(...) MAP(WITH, __VA_ARGS__)
+
+float instagib_respawntime_ammo = 45;
+float instagib_respawntimejitter_ammo = 0;
+GETTER(float, instagib_respawntime_ammo)
+GETTER(float, instagib_respawntimejitter_ammo)
+
+REGISTER_ITEM(VaporizerCells, Pickup, APPLY(UNWORDS
+    ,APPLY(CONFIGURE
+    ,   model               =   "models/items/a_cells.md3"
+    ,   sound               =   "misc/itempickup.wav"
+    ,   name                =   "Vaporizer Ammo"
+    )
+    ,IF(SV, CONFIGURE
+    ,   botvalue            =   100
+    ,   itemid              =   IT_CELLS
+    ,   respawntime         =         GET(instagib_respawntime_ammo)
+    ,   respawntimejitter   =   GET(instagib_respawntimejitter_ammo)
+    )
+))
+
+REGISTER_ITEM(ExtraLife, Pickup, APPLY(UNWORDS
+    ,APPLY(CONFIGURE
+    ,   model               =   "models/items/g_h100.md3"
+    ,   sound               =   "misc/megahealth.wav"
+    ,   name                =   "Extralife"
+    )
+    ,IF(SV, CONFIGURE
+    ,   botvalue            =   BOT_PICKUP_RATING_HIGH
+    ,   itemflags           =   FL_POWERUP
+    ,   itemid              =   IT_NAILS
+    ,   respawntime         =         GET(g_pickup_respawntime_powerup)
+    ,   respawntimejitter   =   GET(g_pickup_respawntimejitter_powerup)
+    )
+))
+
+#undef WITH
+#undef CONFIGURE
index d1ab520001d4580b25bbd1d07470401a8b843fd0..e7c066afc3030117e399628344e43f45acc74c96 100644 (file)
@@ -1,3 +1,7 @@
+#include "../_all.qh"
+
+#include "mutator.qh"
+
 MUTATOR_HOOKFUNCTION(invincibleprojectiles_EditProjectile)
 {
        if(other.health)
index b4f9c37716c39c70426d05b5039a4735f84c37e8..ed7cd2074620616546212f546090a41c7d1fd685 100644 (file)
@@ -1,3 +1,7 @@
+#include "../_all.qh"
+
+#include "mutator.qh"
+
 MUTATOR_HOOKFUNCTION(melee_SetStartItems)
 {
        start_ammo_shells = warmup_start_ammo_shells = 0;
index d582c05ce7d39b3150eed52452e49cb99f1e1d78..686df9a567ad123316f2200c08e1e9d0c1efc4a9 100644 (file)
@@ -1,3 +1,7 @@
+#include "../_all.qh"
+
+#include "mutator.qh"
+
 .float midair_shieldtime;
 
 MUTATOR_HOOKFUNCTION(midair_PlayerDamage)
index d36f3ecbe82e566a030968198c11564cbefb7a2c..dd879e5de4bc4858c3bf19c14c0f561843c13b0d 100644 (file)
@@ -1,28 +1,71 @@
+#ifdef SVQC
+       #include "../_all.qh"
+       #include "mutator.qh"
+       #include "../antilag.qh"
+#endif
+
 .float multijump_count;
 .float multijump_ready;
 
-MUTATOR_HOOKFUNCTION(multijump_PlayerPhysics)
+#ifdef CSQC
+
+#define PHYS_MULTIJUMP                                 getstati(STAT_MULTIJUMP)
+#define PHYS_MULTIJUMP_SPEED           getstatf(STAT_MULTIJUMP_SPEED)
+#define PHYS_MULTIJUMP_ADD                     getstati(STAT_MULTIJUMP_ADD)
+
+#elif defined(SVQC)
+
+#define PHYS_MULTIJUMP                                 autocvar_g_multijump
+#define PHYS_MULTIJUMP_SPEED           autocvar_g_multijump_speed
+#define PHYS_MULTIJUMP_ADD                     autocvar_g_multijump_add
+
+
+.float stat_multijump;
+.float stat_multijump_speed;
+.float stat_multijump_add;
+
+void multijump_UpdateStats()
 {
-       if(self.flags & FL_ONGROUND)
-               self.multijump_count = 0;
+       self.stat_multijump = PHYS_MULTIJUMP;
+       self.stat_multijump_speed = PHYS_MULTIJUMP_SPEED;
+       self.stat_multijump_add = PHYS_MULTIJUMP_ADD;
+}
 
-       return false;
+void multijump_AddStats()
+{
+       addstat(STAT_MULTIJUMP, AS_INT, stat_multijump);
+       addstat(STAT_MULTIJUMP_SPEED, AS_FLOAT, stat_multijump_speed);
+       addstat(STAT_MULTIJUMP_ADD, AS_INT, stat_multijump_add);
 }
 
-MUTATOR_HOOKFUNCTION(multijump_PlayerJump)
+#endif
+
+void PM_multijump()
+{
+       if(!PHYS_MULTIJUMP) { return; }
+
+       if(IS_ONGROUND(self))
+       {
+               self.multijump_count = 0;
+       }
+}
+
+float PM_multijump_checkjump()
 {
-       if (self.flags & FL_JUMPRELEASED && !(self.flags & FL_ONGROUND)) // jump button pressed this frame and we are in midair
+       if(!PHYS_MULTIJUMP) { return false; }
+
+       if (!IS_JUMP_HELD(self) && !IS_ONGROUND(self)) // jump button pressed this frame and we are in midair
                self.multijump_ready = true;  // this is necessary to check that we released the jump button and pressed it again
        else
                self.multijump_ready = false;
 
-       if(!player_multijump && self.multijump_ready && (autocvar_g_multijump == -1 || self.multijump_count < autocvar_g_multijump) && self.velocity.z > autocvar_g_multijump_speed)
+       if(!player_multijump && self.multijump_ready && (self.multijump_count < PHYS_MULTIJUMP || PHYS_MULTIJUMP == -1) && self.velocity_z > PHYS_MULTIJUMP_SPEED)
        {
-               if (autocvar_g_multijump)
+               if (PHYS_MULTIJUMP)
                {
-                       if (autocvar_g_multijump_add == 0) // in this case we make the z velocity == jumpvelocity
+                       if (!PHYS_MULTIJUMP_ADD) // in this case we make the z velocity == jumpvelocity
                        {
-                               if (self.velocity.z < autocvar_sv_jumpvelocity)
+                               if (self.velocity_z < PHYS_JUMPVELOCITY)
                                {
                                        player_multijump = true;
                                        self.velocity_z = 0;
@@ -33,21 +76,26 @@ MUTATOR_HOOKFUNCTION(multijump_PlayerJump)
 
                        if(player_multijump)
                        {
-                               if(self.movement.x != 0 || self.movement.y != 0) // don't remove all speed if player isnt pressing any movement keys
+                               if(self.movement_x != 0 || self.movement_y != 0) // don't remove all speed if player isnt pressing any movement keys
                                {
                                        float curspeed;
                                        vector wishvel, wishdir;
 
+#ifdef SVQC
                                        curspeed = max(
                                                vlen(vec2(self.velocity)), // current xy speed
                                                vlen(vec2(antilag_takebackavgvelocity(self, max(self.lastteleporttime + sys_frametime, time - 0.25), time))) // average xy topspeed over the last 0.25 secs
                                        );
-                                       makevectors(self.v_angle.y * '0 1 0');
-                                       wishvel = v_forward * self.movement.x + v_right * self.movement.y;
+#elif defined(CSQC)
+                                       curspeed = vlen(vec2(self.velocity));
+#endif
+
+                                       makevectors(self.v_angle_y * '0 1 0');
+                                       wishvel = v_forward * self.movement_x + v_right * self.movement_y;
                                        wishdir = normalize(wishvel);
 
-                                       self.velocity_x = wishdir.x * curspeed; // allow "dodging" at a multijump
-                                       self.velocity_y = wishdir.y * curspeed;
+                                       self.velocity_x = wishdir_x * curspeed; // allow "dodging" at a multijump
+                                       self.velocity_y = wishdir_y * curspeed;
                                        // keep velocity_z unchanged!
                                }
                                self.multijump_count += 1;
@@ -59,6 +107,20 @@ MUTATOR_HOOKFUNCTION(multijump_PlayerJump)
        return false;
 }
 
+#ifdef SVQC
+MUTATOR_HOOKFUNCTION(multijump_PlayerPhysics)
+{
+       multijump_UpdateStats();
+       PM_multijump();
+
+       return false;
+}
+
+MUTATOR_HOOKFUNCTION(multijump_PlayerJump)
+{
+       return PM_multijump_checkjump();
+}
+
 MUTATOR_HOOKFUNCTION(multijump_BuildMutatorsString)
 {
        ret_string = strcat(ret_string, ":multijump");
@@ -78,5 +140,11 @@ MUTATOR_DEFINITION(mutator_multijump)
        MUTATOR_HOOK(BuildMutatorsString, multijump_BuildMutatorsString, CBC_ORDER_ANY);
        MUTATOR_HOOK(BuildMutatorsPrettyString, multijump_BuildMutatorsPrettyString, CBC_ORDER_ANY);
 
+       MUTATOR_ONADD
+       {
+               multijump_AddStats();
+       }
+
        return false;
 }
+#endif
index 60b2acce56053ea2b1d2ab295b393c99737a0df6..292bba261aad86083993bc4b699209d9e7f04db5 100644 (file)
@@ -1,3 +1,16 @@
+#include "mutator_nades.qh"
+#include "../_all.qh"
+
+#include "mutator.qh"
+
+#include "gamemode_keyhunt.qh"
+#include "gamemode_freezetag.qh"
+#include "../../common/nades.qh"
+#include "../../common/monsters/spawn.qh"
+#include "../../common/monsters/sv_monsters.qh"
+
+.float lifetime;
+
 .entity nade_spawnloc;
 
 void nade_timer_think()
@@ -475,7 +488,7 @@ void nade_monster_boom()
 void nade_boom()
 {
        string expef;
-       float nade_blast = 1;
+       bool nade_blast = true;
 
        switch ( self.nade_type )
        {
@@ -484,16 +497,16 @@ void nade_boom()
                        expef = "explosion_medium";
                        break;
                case NADE_TYPE_ICE:
-                       nade_blast = 0;
+                       nade_blast = false;
                        expef = "electro_combo"; // hookbomb_explode electro_combo bigplasma_impact
                        break;
                case NADE_TYPE_TRANSLOCATE:
-                       nade_blast = 0;
+                       nade_blast = false;
                        expef = "";
                        break;
                case NADE_TYPE_MONSTER:
                case NADE_TYPE_SPAWN:
-                       nade_blast = 0;
+                       nade_blast = false;
                        switch(self.realowner.team)
                        {
                                case NUM_TEAM_1: expef = "spawn_event_red"; break;
@@ -504,7 +517,7 @@ void nade_boom()
                        }
                        break;
                case NADE_TYPE_HEAL:
-                       nade_blast = 0;
+                       nade_blast = false;
                        expef = "spawn_event_red";
                        break;
 
@@ -583,7 +596,7 @@ void nade_beep()
        self.nextthink = max(self.wait, time);
 }
 
-void nade_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
+void nade_damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
 {
        if(ITEM_DAMAGE_NEEDKILL(deathtype))
        {
index 5aa94b1875d8d070ac6c76250874f586d31fdfcd..d52bd09ee32c68ddd70a332ca62bd139f4b287c7 100644 (file)
@@ -1,3 +1,7 @@
+#include "../_all.qh"
+
+#include "mutator.qh"
+
 /*
 
 CORE    laser   vortex     lg      rl      cry     gl      elec    hagar   fireb   hook
index a0ec6adaa020ca3d2273ee988886fe1e642d14d0..42a490b00e8befbf5bc4542200ecc86358155ec1 100644 (file)
@@ -1,6 +1,10 @@
+#include "../_all.qh"
+
+#include "mutator.qh"
+
 float g_nix_with_blaster;
 // WEAPONTODO
-float nix_weapon;
+int nix_weapon;
 float nix_nextchange;
 float nix_nextweapon;
 .float nix_lastchange_id;
index 78a61510602787209533b227e909982e2d63d304..39b244a724ef97116cf988d0d186730cd72ae497 100644 (file)
@@ -1,4 +1,13 @@
-void ok_DecreaseCharge(entity ent, float wep)
+#include "mutator_overkill.qh"
+#include "../_all.qh"
+
+#include "mutator.qh"
+
+void W_Blaster_Attack(float, float, float, float, float, float, float, float, float, float);
+void spawnfunc_weapon_hmg();
+void spawnfunc_weapon_rpc();
+
+void ok_DecreaseCharge(entity ent, int wep)
 {
        if(!ent.ok_use_ammocharge) return;
 
@@ -10,7 +19,7 @@ void ok_DecreaseCharge(entity ent, float wep)
        ent.ammo_charge[wep] -= max(0, cvar(sprintf("g_overkill_ammo_decharge_%s", wepent.netname)));
 }
 
-void ok_IncreaseCharge(entity ent, float wep)
+void ok_IncreaseCharge(entity ent, int wep)
 {
        entity wepent = get_weaponinfo(wep);
 
@@ -22,7 +31,7 @@ void ok_IncreaseCharge(entity ent, float wep)
                ent.ammo_charge[wep] = min(autocvar_g_overkill_ammo_charge_limit, ent.ammo_charge[wep] + cvar(sprintf("g_overkill_ammo_charge_rate_%s", wepent.netname)) * frametime / W_TICSPERFRAME);
 }
 
-float ok_CheckWeaponCharge(entity ent, float wep)
+float ok_CheckWeaponCharge(entity ent, int wep)
 {
        if(!ent.ok_use_ammocharge) return true;
 
@@ -183,9 +192,7 @@ MUTATOR_HOOKFUNCTION(ok_PlayerSpawn)
 {
        if(autocvar_g_overkill_ammo_charge)
        {
-               float i;
-
-               for(i = WEP_FIRST; i <= WEP_LAST; ++i)
+               for(int i = WEP_FIRST; i <= WEP_LAST; ++i)
                        self.ammo_charge[i] = autocvar_g_overkill_ammo_charge_limit;
 
                self.ok_use_ammocharge = 1;
index dd2d8556d68fe7801111bc60ac0fd987f84ebea2..d82bec99fecdaa24f5dea3b7eb0a28fc4e84f4e4 100644 (file)
@@ -1,3 +1,7 @@
+#include "../_all.qh"
+
+#include "mutator.qh"
+
 .vector spawn_origin, spawn_angles;
 
 void physical_item_think()
@@ -45,7 +49,7 @@ void physical_item_touch()
        }
 }
 
-void physical_item_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
+void physical_item_damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
 {
        if(!self.cnt) // not for dropped items
        if(ITEM_DAMAGE_NEEDKILL(deathtype))
index 7cf405ef7679cc0331c5d89fb622d42cf1d97f5c..5dd6aa92e46e90b02aae2e1277f70460b9243db7 100644 (file)
@@ -1,3 +1,7 @@
+#include "../_all.qh"
+
+#include "mutator.qh"
+
 MUTATOR_HOOKFUNCTION(pinata_PlayerDies)
 {
        float j;
index f70ee4ba32c9d01d312a81a81e67ebfc9c34f5e2..b48deddcfa95c00f8bea029072efd283c2ca72a9 100644 (file)
@@ -1,3 +1,7 @@
+#include "../_all.qh"
+
+#include "mutator.qh"
+
 // Random Gravity
 //
 // Mutator by Mario
index 03a5bde619683445ac5929017ca51ade53936b71..5f684b353191f84bc45a150fb34b3609974b24e1 100644 (file)
@@ -1,3 +1,7 @@
+#include "../_all.qh"
+
+#include "mutator.qh"
+
 MUTATOR_HOOKFUNCTION(rocketflying_EditProjectile)
 {
        if(other.classname == "rocket" || other.classname == "mine")
index 8dc3bbc6c0ad049c50ed1702825221901a56b635..c3ab07a72635271dec43b04e0a87e1982361d8a6 100644 (file)
@@ -1,3 +1,7 @@
+#include "../_all.qh"
+
+#include "mutator.qh"
+
 .entity msnt_lookat;
 
 .float msnt_timer;
index 1fd1022e72d2131d57edacd22c8ed8e2df2f6c6e..3570e220431d531d437b60aff61de4aab2899c3e 100644 (file)
@@ -1,3 +1,7 @@
+#include "../_all.qh"
+
+#include "mutator.qh"
+
 #define _SSMAGIX "SUPERSPEC_OPTIONSFILE_V1"
 #define _ISLOCAL ((edict_num(1) == self) ? true : false)
 
index fb58b3955cbbbcae1913b3628bce8e354a521dff..a45c64f5c5b03fa42513b3f342ed3cd056510e76 100644 (file)
@@ -1,3 +1,7 @@
+#include "../_all.qh"
+
+#include "mutator.qh"
+
 .float touchexplode_time;
 
 void PlayerTouchExplode(entity p1, entity p2)
index aa45fc1acfb777fea7c1ea078f38767fded15f42..6b2859f440b17ec46b042e8d850c51f0fb231eb1 100644 (file)
@@ -1,3 +1,7 @@
+#include "../_all.qh"
+
+#include "mutator.qh"
+
 MUTATOR_HOOKFUNCTION(vampire_PlayerDamage)
 {
        if(time >= frag_target.spawnshieldtime)
index a0170e4803f04ae82fad8c363f97f3fa5f27d454..e139865ab56395936c000fe3e28a6981d8f553a5 100644 (file)
     #include "../../common/command/markup.qh"
     #include "../../common/command/rpn.qh"
     #include "../../common/command/generic.qh"
-    #include "../../common/command/shared_defs.qh"
+    #include "../../common/command/command.qh"
     #include "../../common/net_notice.qh"
     #include "../../common/animdecide.qh"
-    #include "../../common/monsters/monsters.qh"
+    #include "../../common/monsters/all.qh"
     #include "../../common/monsters/sv_monsters.qh"
     #include "../../common/monsters/spawn.qh"
     #include "../../common/weapons/config.qh"
-    #include "../../common/weapons/weapons.qh"
+    #include "../../common/weapons/all.qh"
     #include "../weapons/accuracy.qh"
     #include "../weapons/common.qh"
     #include "../weapons/csqcprojectile.qh"
@@ -46,7 +46,7 @@
     #include "../../common/deathtypes.qh"
     #include "mutators_include.qh"
     #include "../tturrets/include/turrets_early.qh"
-    #include "../vehicles/vehicles_def.qh"
+    #include "../vehicles/vehicle.qh"
     #include "../campaign.qh"
     #include "../../common/campaign_common.qh"
     #include "../../common/mapinfo.qh"
     #include "../playerdemo.qh"
     #include "../round_handler.qh"
     #include "../item_key.qh"
-    #include "../secret.qh"
     #include "../pathlib/pathlib.qh"
     #include "../tturrets/include/turrets.qh"
-    #include "../vehicles/vehicles.qh"
+    #include "../vehicles/all.qh"
 #endif
 
 #include "base.qc"
index f66b5019a603b06402290bd58adaf82d12d87563..3593c57b9e35be773c712378458bef3044bf3cf7 100644 (file)
@@ -1,3 +1,7 @@
+#include "../_all.qh"
+
+#include "mutator.qh"
+
 const float MAX_STORAGE_ATTACHMENTS = 16;
 float object_count;
 .float object_flood;
index 2f66441f7a00111eaca7ab8b4795ca06c15a65f1..bfd9c0b35fca09633e67710f2f7b5acf26d49933 100644 (file)
@@ -1,54 +1,9 @@
-//#define PATHLIB_RDFIELDS
-#ifdef PATHLIB_RDFIELDS
-    #define path_next swampslug
-    #define path_prev lasertarget
-#else
-    .entity path_next;
-    .entity path_prev;
-#endif
+#include "pathlib.qh"
+#include "_all.qh"
 
 #define medium spawnshieldtime
 
 //#define DEBUGPATHING
-
-entity openlist;
-entity closedlist;
-entity scraplist;
-
-.float pathlib_node_g;
-.float pathlib_node_h;
-.float pathlib_node_f;
-
-float pathlib_open_cnt;
-float pathlib_closed_cnt;
-float pathlib_made_cnt;
-float pathlib_merge_cnt;
-float pathlib_recycle_cnt;
-float pathlib_searched_cnt;
-
-#ifdef DEBUGPATHING
-
-#endif
-
-float pathlib_bestopen_seached;
-float pathlib_bestcash_hits;
-float pathlib_bestcash_saved;
-
-float pathlib_gridsize;
-
-float pathlib_movecost;
-float pathlib_movecost_diag;
-float pathlib_movecost_waterfactor;
-
-float pathlib_edge_check_size;
-
-float pathlib_foundgoal;
-entity goal_node;
-
-entity best_open_node;
-.float is_path_node;
-
-
 #ifdef DEBUGPATHING
 float edge_show(vector point,float fsize);
 void mark_error(vector where,float lifetime);
@@ -161,16 +116,6 @@ float floor_ok(vector point)
     return 0;
 }
 
-#define inwater(point) (pointcontents(point) == CONTENT_WATER)
-/*
-float inwater(vector point)
-{
-    if(pointcontents(point) == CONTENT_WATER)
-        return 1;
-    return 0;
-}
-*/
-
 #define _pcheck(p) traceline(p+z_up,p-z_down,MOVE_WORLDONLY,self); if (!floor_ok(trace_endpos)) return 1
 float edge_check(vector point,float fsize)
 {
@@ -259,7 +204,7 @@ vector pathlib_swimnode(vector start,vector end,float doedge)
     end.y = fsnap(end.y, pathlib_gridsize);
 
     if(pointcontents(end) == CONTENT_EMPTY)
-        return pathlib_wateroutnode( start, end);
+        return pathlib_wateroutnode( start, end, doedge);
 
     tracebox(start, walknode_boxmin,walknode_boxmax, end, MOVE_WORLDONLY, self);
     if(trace_fraction == 1)
@@ -519,7 +464,6 @@ float pathlib_h_diagonal3(vector a,vector b)
     return h;
 }
 
-//#define PATHLIB_USE_NODESCRAP
 const float PATHLIB_NODEEXPIRE = 0.05;
 float pathlib_scraplist_cnt;
 entity newnode()
@@ -541,7 +485,6 @@ entity newnode()
 #endif
     ++pathlib_made_cnt;
     n = spawn();
-#ifdef PATHLIB_NODEEXPIRE
     n.think      = SUB_Remove;
     n.nextthink  = time + PATHLIB_NODEEXPIRE;
     return n;
@@ -736,7 +679,7 @@ float pathlib_expandnode_star(entity node, vector start, vector goal)
 {
     vector point;
     vector where;
-    float nodecnt;
+    float nodecnt = 0;
 
     where = node.origin;
 
@@ -1044,6 +987,3 @@ entity pathlib_astar(vector from,vector to)
 
     return world;
 }
-
-
-
diff --git a/qcsrc/server/pathlib.qh b/qcsrc/server/pathlib.qh
new file mode 100644 (file)
index 0000000..da4ae0c
--- /dev/null
@@ -0,0 +1,48 @@
+#ifndef PATHLIB_H
+#define PATHLIB_H
+
+//#define PATHLIB_RDFIELDS
+#ifdef PATHLIB_RDFIELDS
+    #define path_next swampslug
+    #define path_prev lasertarget
+#else
+    .entity path_next;
+    .entity path_prev;
+#endif
+
+entity openlist;
+entity closedlist;
+entity scraplist;
+
+.float pathlib_node_g;
+.float pathlib_node_h;
+.float pathlib_node_f;
+
+float pathlib_open_cnt;
+float pathlib_closed_cnt;
+float pathlib_made_cnt;
+float pathlib_merge_cnt;
+float pathlib_recycle_cnt;
+float pathlib_searched_cnt;
+
+float pathlib_bestopen_seached;
+float pathlib_bestcash_hits;
+float pathlib_bestcash_saved;
+
+float pathlib_gridsize;
+
+float pathlib_movecost;
+float pathlib_movecost_diag;
+float pathlib_movecost_waterfactor;
+
+float pathlib_edge_check_size;
+
+float pathlib_foundgoal;
+entity goal_node;
+
+entity best_open_node;
+.float is_path_node;
+
+#define inwater(point) (pointcontents(point) == CONTENT_WATER)
+
+#endif
index 0b2ee4559995671b324050c7664cf0dc2455a5e5..878e8fd5b113fda6f8e03a6fb6f2b04521999d85 100644 (file)
@@ -1,3 +1,5 @@
+#include "../pathlib.qh"
+
 float pathlib_g_static(entity parent,vector to, float static_cost)
 {
     return parent.pathlib_node_g + static_cost;
index 4f73b24733bcbf75714a07a33db840cb4e9bc8b6..5c97cf7ac41575adba77f604d88399f000597d95 100644 (file)
@@ -1,3 +1,4 @@
+#include "../pathlib.qh"
 
 #ifdef TURRET_DEBUG
 void mark_error(vector where,float lifetime);
@@ -65,6 +66,8 @@ void pathlib_showsquare2(entity node ,vector ncolor,float align)
     }
 }
 
+void SUB_Remove();
+
 void pathlib_showsquare(vector where,float goodsquare,float _lifetime)
 {
     entity s;
index 4427f9b7fd03f432fc23a6c9d370ebb36629d672..9d49be9ecea3c9a5eb8a5cb75188d56bdfc6ee5a 100644 (file)
@@ -1,3 +1,6 @@
+#include "pathlib.qh"
+#include "utility.qh"
+
 vector plib_points2[8];
 vector plib_points[8];
 float  plib_fvals[8];
@@ -5,7 +8,7 @@ float  plib_fvals[8];
 float pathlib_expandnode_starf(entity node, vector start, vector goal)
 {
     vector where,f,r,t;
-    float i,fc,fc2,c;
+    float fc,c;
     entity nap;
 
     where = node.origin;
@@ -37,7 +40,7 @@ float pathlib_expandnode_starf(entity node, vector start, vector goal)
     // Back-left
     plib_points[7] = where - f - r;
 
-    for(i=0;i < 8; ++i)
+    for(int i=0;i < 8; ++i)
     {
         t = plib_points[i];
         fc  = pathlib_heuristic(t,goal) + pathlib_cost(node, t, pathlib_gridsize);
@@ -49,8 +52,8 @@ float pathlib_expandnode_starf(entity node, vector start, vector goal)
     plib_points2[0] = plib_points[0];
     vector bp;
     bp = plib_points[0];
-    fc2 = 0;
-    for(i = 0; i < 8; ++i)
+    int fc2 = 0;
+    for(int i = 0; i < 8; ++i)
     {
         c = 0;
         nap = pathlib_nodeatpoint(plib_points[i]);
@@ -80,7 +83,7 @@ float pathlib_expandnode_starf(entity node, vector start, vector goal)
 
     pathlib_makenode(node, start, bp, goal, pathlib_gridsize);
 
-    for(i = 0; i < 3; ++i)
+    for(int i = 0; i < 3; ++i)
     {
         pathlib_makenode(node, start, plib_points2[i], goal, pathlib_gridsize);
     }
index 5fef3251f64b568680f124c442a85572d2ee35c0..cf000801a855afd15481a24ce1480aa77a7521e4 100644 (file)
@@ -1,3 +1,9 @@
+#include "../_all.qh"
+
+#include "pathlib.qh"
+#include "utility.qh"
+#include "../command/common.qh"
+
 void pathlib_deletepath(entity start)
 {
     entity e;
diff --git a/qcsrc/server/pathlib/main.qh b/qcsrc/server/pathlib/main.qh
new file mode 100644 (file)
index 0000000..177c432
--- /dev/null
@@ -0,0 +1,5 @@
+#ifndef PATHLIB_MAIN_H
+#define PATHLIB_MAIN_H
+float buildpath_nodefilter_none(vector n,vector c,vector p);
+entity path_build(entity next, vector where, entity prev, entity start);
+#endif
index 1da6fe16718065a64a0f69ef81767a496399bbaa..f1e596d798dab61eaabca0f54309209a499b181a 100644 (file)
@@ -1,3 +1,8 @@
+#include "../_all.qh"
+
+#include "pathlib.qh"
+#include "utility.qh"
+
 vector pathlib_wateroutnode(vector start,vector end, float doedge)
 {
     vector surface;
index 231c14f21bbbf6b6c8464a62d857ba593394116d..1bc115dc0e49323e033963aa227c9ed4402635bc 100644 (file)
@@ -1,3 +1,8 @@
+#include "../bot/waypoints.qh"
+
+#include "pathlib.qh"
+#include "main.qh"
+
 var float pathlib_wpp_open(entity wp, entity child, float cost);
 
 void pathlib_wpp_close(entity wp)
index d0029bfc4809be08e2d93195781100a082c755ad..dbf785266ae67a266a1b9d9c4f66ebac245fc60c 100644 (file)
@@ -113,10 +113,4 @@ var float  pathlib_wpp_waypointcallback(entity wp, entity wp_prev);
        #include "debug.qc"
 #endif
 
-#include "utility.qc"
-#include "movenode.qc"
-#include "costs.qc"
-#include "expandnode.qc"
-#include "main.qc"
-#include "path_waypoint.qc"
 #endif
index 7bdc70877420a38d60bd7ce7b3da04e99abe4c28..4851dbcc0c52db8a957bf80d2ab85f2762fe80f8 100644 (file)
@@ -1,3 +1,7 @@
+#include "utility.qh"
+
+#include "pathlib.qh"
+
 float fsnap(float val,float fsize)
 {
     return rint(val / fsize) * fsize;
diff --git a/qcsrc/server/pathlib/utility.qh b/qcsrc/server/pathlib/utility.qh
new file mode 100644 (file)
index 0000000..bf72549
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef PATHLIB_UTILITY
+#define PATHLIB_UTILITY
+float fsnap(float val,float fsize);
+entity pathlib_nodeatpoint(vector where);
+float tile_check_plus2(vector where);
+#endif
index 4d58a95f6ff0bc82da280d6f60bc22628d389f4b..c2e812c2c10e6463e49ec2cee4185c23fce5d8b3 100644 (file)
@@ -71,27 +71,27 @@ void playerdemo_open_write(string f)
 
 void playerdemo_write_originvector(.vector f, string name)
 {
-       fputs(self.playerdemo_fh, strcat(vtos(self.f), "\n"));
+       fputs(self.playerdemo_fh, strcat(vtos(self.(f)), "\n"));
 }
 void playerdemo_write_sizevector(.vector f, string name)
 {
-       fputs(self.playerdemo_fh, strcat(vtos(self.f), "\n"));
+       fputs(self.playerdemo_fh, strcat(vtos(self.(f)), "\n"));
 }
 void playerdemo_write_vector(.vector f, string name)
 {
-       fputs(self.playerdemo_fh, strcat(vtos(self.f), "\n"));
+       fputs(self.playerdemo_fh, strcat(vtos(self.(f)), "\n"));
 }
 void playerdemo_write_string(.string f, string name)
 {
-       fputs(self.playerdemo_fh, strcat(self.f, "\n"));
+       fputs(self.playerdemo_fh, strcat(self.(f), "\n"));
 }
 void playerdemo_write_modelstring(.string f, string name)
 {
-       fputs(self.playerdemo_fh, strcat(self.f, "\n"));
+       fputs(self.playerdemo_fh, strcat(self.(f), "\n"));
 }
 void playerdemo_write_float(.float f, string name)
 {
-       fputs(self.playerdemo_fh, strcat(ftos(self.f), "\n"));
+       fputs(self.playerdemo_fh, strcat(ftos(self.(f)), "\n"));
 }
 void playerdemo_write()
 {
@@ -106,36 +106,34 @@ void playerdemo_read_originvector(.vector f, string name)
 }
 void playerdemo_read_sizevector(.vector f, string name)
 {
-       self.f = stov(fgets(self.playerdemo_fh));
+       self.(f) = stov(fgets(self.playerdemo_fh));
        setsize(self, self.mins, self.maxs);
 }
 void playerdemo_read_vector(.vector f, string name)
 {
-       self.f = stov(fgets(self.playerdemo_fh));
+       self.(f) = stov(fgets(self.playerdemo_fh));
 }
 void playerdemo_read_string(.string f, string name)
 {
-       string s;
-       s = fgets(self.playerdemo_fh);
-       if(s != self.f)
+       string s = fgets(self.playerdemo_fh);
+       if (s != self.(f))
        {
                /*
                if(self.f)
                        strunzone(self.f);
                */
-               self.f = strzone(s);
+               self.(f) = strzone(s);
        }
 }
 void playerdemo_read_modelstring(.string f, string name)
 {
-       string s;
-       s = fgets(self.playerdemo_fh);
-       if(s != self.f)
+       string s = fgets(self.playerdemo_fh);
+       if (s != self.(f))
                setmodel(self, s);
 }
 void playerdemo_read_float(.float f, string name)
 {
-       self.f = stof(fgets(self.playerdemo_fh));
+       self.(f) = stof(fgets(self.playerdemo_fh));
 }
 float playerdemo_read()
 {
index 53c77ecceefc089e6215e93fd2d9bc771205bc3a..ad8aea50cdf068c9c0f164a2ab384b9e5fa7bac9 100644 (file)
@@ -1,22 +1,18 @@
-#if defined(CSQC)
-#elif defined(MENUQC)
-#elif defined(SVQC)
-       #include "../dpdefs/progsdefs.qh"
-    #include "../dpdefs/dpextensions.qh"
-    #include "../warpzonelib/anglestransform.qh"
-    #include "../warpzonelib/util_server.qh"
-    #include "../common/constants.qh"
-    #include "../common/util.qh"
-    #include "../common/weapons/weapons.qh"
-    #include "autocvars.qh"
-    #include "defs.qh"
-    #include "../common/notifications.qh"
-    #include "../common/deathtypes.qh"
-    #include "mutators/mutators_include.qh"
-    #include "../csqcmodellib/sv_model.qh"
-    #include "portals.qh"
-    #include "g_hook.qh"
-#endif
+#include "portals.qh"
+#include "_all.qh"
+
+#include "g_hook.qh"
+#include "mutators/mutators_include.qh"
+#include "../common/constants.qh"
+#include "../common/deathtypes.qh"
+#include "../common/notifications.qh"
+#include "../common/triggers/teleporters.qh"
+#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"
 
 #define PORTALS_ARE_NOT_SOLID
 
@@ -310,8 +306,8 @@ void Portal_Touch()
                return;
 
        /*
-       if(other.mins_x < PL_MIN_x || other.mins_y < PL_MIN_y || other.mins_z < PL_MIN_z
-       || other.maxs_x > PL_MAX_x || other.maxs_y > PL_MAX_y || other.maxs_z > PL_MAX_z)
+       if(other.mins_x < PL_MIN.x || other.mins_y < PL_MIN.y || other.mins_z < PL_MIN.z
+       || other.maxs_x > PL_MAX.x || other.maxs_y > PL_MAX.y || other.maxs_z > PL_MAX.z)
        {
                // can't teleport this
                return;
@@ -430,7 +426,7 @@ void Portal_Remove(entity portal, float killed)
        }
 }
 
-void Portal_Damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
+void Portal_Damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
 {
        if(deathtype == DEATH_TELEFRAG)
                return;
index 85e75cda9e2fce18b2f2715b0bd1c10e8452b7bb..ab87642aaa5843e6f9b05150b6f80aa0ec198ab0 100644 (file)
@@ -8,71 +8,69 @@ sys-post.qh
 
 anticheat.qc
 antilag.qc
-// assault.qc
 campaign.qc
 cheats.qc
 cl_client.qc
 cl_impulse.qc
-cl_physics.qc
 cl_player.qc
 csqceffects.qc
-// ctf.qc
-// domination.qc
 ent_cs.qc
-func_breakable.qc
 g_casings.qc
 g_damage.qc
 g_hook.qc
+// g_lights.qc // TODO: was never used
 g_models.qc
 g_subs.qc
 g_tetris.qc
-g_triggers.qc
 g_violence.qc
 g_world.qc
 ipban.qc
 item_key.qc
 mapvoting.qc
 miscfunctions.qc
-// mode_onslaught.qc
 movelib.qc
-// nexball.qc
+// pathlib.qc // TODO: was never used. Seems to duplicate `pathlib/`
 playerdemo.qc
 portals.qc
 race.qc
 round_handler.qc
-// runematch.qc
 scores.qc
 scores_rules.qc
-secret.qc
 spawnpoints.qc
 steerlib.qc
 sv_main.qc
-target_music.qc
-target_spawn.qc
 teamplay.qc
 t_halflife.qc
 t_items.qc
-t_jumppads.qc
-t_plats.qc
 t_quake3.qc
 t_quake.qc
-t_swamp.qc
-t_teleporters.qc
 waypointsprites.qc
 
+bot/aim.qc
 bot/bot.qc
+bot/navigation.qc
+bot/scripting.qc
+bot/waypoints.qc
 
-command/banning.qc
-command/cmd.qc
-command/common.qc
-command/getreplies.qc
-command/radarmap.qc
-command/sv_cmd.qc
-command/vote.qc
+bot/havocbot/havocbot.qc
+bot/havocbot/role_keyhunt.qc
+bot/havocbot/role_onslaught.qc
+bot/havocbot/roles.qc
+
+command/all.qc
 
 mutators/mutators_include.qc
 mutators/mutators.qc
 
+pathlib/costs.qc
+pathlib/expandnode.qc
+pathlib/main.qc
+pathlib/movenode.qc
+pathlib/path_waypoint.qc
+pathlib/utility.qc
+
+vehicles/all.qc
+
 weapons/accuracy.qc
 weapons/common.qc
 weapons/csqcprojectile.qc // TODO
@@ -88,22 +86,25 @@ weapons/weaponsystem.qc
 ../common/buffs.qc
 ../common/campaign_file.qc
 ../common/campaign_setup.qc
-../common/command/generic.qc
-../common/command/markup.qc
-../common/command/rpn.qc
 ../common/mapinfo.qc
-../common/monsters/monsters.qc
+../common/monsters/all.qc
 ../common/monsters/spawn.qc
 ../common/monsters/sv_monsters.qc
+../common/movetypes/include.qc
 ../common/nades.qc
 ../common/net_notice.qc
 ../common/notifications.qc
+../common/physics.qc
 ../common/playerstats.qc
 ../common/test.qc
+../common/triggers/include.qc
 ../common/urllib.qc
 ../common/util.qc
+
+../common/items/all.qc
+
 ../common/weapons/config.qc
-../common/weapons/weapons.qc // TODO
+../common/weapons/all.qc // TODO
 
 ../csqcmodellib/sv_model.qc
 
index bb7f0eccc2297ad547b06181fa225d3957ad318d..4482fe327901b7e42a4e91da460fc596f6f3d525 100644 (file)
@@ -1,4 +1,18 @@
 #include "race.qh"
+#include "_all.qh"
+
+#include "cl_client.qh"
+#include "portals.qh"
+#include "scores.qh"
+#include "spawnpoints.qh"
+#include "waypointsprites.qh"
+#include "bot/waypoints.qh"
+#include "bot/navigation.qh"
+#include "command/getreplies.qh"
+#include "../common/deathtypes.qh"
+#include "../common/notifications.qh"
+#include "../common/mapinfo.qh"
+#include "../warpzonelib/util_server.qh"
 
 void W_Porto_Fail(float failhard);
 
@@ -79,7 +93,6 @@ void spawnfunc_target_checkpoint();
 .float race_penalty_accumulator;
 .string race_penalty_reason;
 .float race_checkpoint; // player: next checkpoint that has to be reached
-.float race_laptime;
 .entity race_lastpenalty;
 
 .entity sprite;
@@ -176,6 +189,27 @@ void race_send_recordtime(float msg)
        WriteInt24_t(msg, race_readTime(GetMapname(), 1));
 }
 
+
+void race_send_speedaward(float msg)
+{
+       // send the best speed of the round
+       WriteByte(msg, SVC_TEMPENTITY);
+       WriteByte(msg, TE_CSQC_RACE);
+       WriteByte(msg, RACE_NET_SPEED_AWARD);
+       WriteInt24_t(msg, floor(speedaward_speed+0.5));
+       WriteString(msg, speedaward_holder);
+}
+
+void race_send_speedaward_alltimebest(float msg)
+{
+       // send the best speed
+       WriteByte(msg, SVC_TEMPENTITY);
+       WriteByte(msg, TE_CSQC_RACE);
+       WriteByte(msg, RACE_NET_SPEED_AWARD_BEST);
+       WriteInt24_t(msg, floor(speedaward_alltimebest+0.5));
+       WriteString(msg, speedaward_alltimebest_holder);
+}
+
 void race_SendRankings(float pos, float prevpos, float del, float msg)
 {
        WriteByte(msg, SVC_TEMPENTITY);
index bfdc9be4305b80f27265d4c526694a51cfd6ee1e..47c1db4a3860176672e7e9ad486be8cf06a1f181 100644 (file)
@@ -10,6 +10,7 @@ float race_timelimit;
 .float race_place;
 .float race_started;
 .float race_completed;
+.float race_laptime;
 float race_completing;
 
 .float race_movetime; // for reading
@@ -29,4 +30,26 @@ float race_GetFractionalLapCount(entity e);
 float race_readTime(string map, float pos);
 string race_readUID(string map, float pos);
 string race_readName(string map, float pos);
+void race_ClearRecords();
+void race_SendNextCheckpoint(entity e, float spec);
+void race_PreparePlayer();
+void race_send_recordtime(float msg);
+void race_send_speedaward(float msg);
+
+float speedaward_speed;
+string speedaward_holder;
+string speedaward_uid;
+
+float speedaward_alltimebest;
+string speedaward_alltimebest_holder;
+string speedaward_alltimebest_uid;
+
+void race_send_speedaward(float msg);
+
+void race_send_speedaward_alltimebest(float msg);
+
+void race_SendRankings(float pos, float prevpos, float del, float msg);
+
+void race_RetractPlayer();
+
 #endif
index 70d2d144d984c5c3220c0d8da9cc7a9c25f159dc..d5b0281338ac22f1999db48338432feb482f0af2 100644 (file)
@@ -1,12 +1,8 @@
-#if defined(CSQC)
-#elif defined(MENUQC)
-#elif defined(SVQC)
-       #include "../dpdefs/progsdefs.qh"
-    #include "../dpdefs/dpextensions.qh"
-    #include "../common/util.qh"
-    #include "defs.qh"
-    #include "round_handler.qh"
-#endif
+#include "round_handler.qh"
+#include "_all.qh"
+
+#include "command/vote.qh"
+#include "../common/util.qh"
 
 void round_handler_Think()
 {
index 8f9da8b061d581bf609d34c3cf4c9ae84f877ede..57f5e95f8fd6878951ac9d42e5ce79c7ba1dcbd2 100644 (file)
@@ -1,4 +1,10 @@
 #include "scores.qh"
+#include "_all.qh"
+
+#include "command/common.qh"
+#include "mutators/mutators_include.qh"
+#include "../common/playerstats.qh"
+#include "../common/teams.qh"
 
 .entity scorekeeper;
 entity teamscorekeepers[16];
@@ -18,29 +24,29 @@ vector ScoreField_Compare(entity t1, entity t2, .float field, float fieldflags,
                return previous;
        if((fieldflags & SFL_SORT_PRIO_MASK) < previous.y)
                return previous;
-       if(t1.field == t2.field)
+       if (t1.(field) == t2.(field))
                return previous;
 
        previous.y = fieldflags & SFL_SORT_PRIO_MASK;
 
        if(fieldflags & SFL_ZERO_IS_WORST)
        {
-               if(t1.field == 0)
+               if (t1.(field) == 0)
                {
                        previous.x = -1;
                        return previous;
                }
-               else if(t2.field == 0)
+               else if (t2.(field) == 0)
                {
                        previous.x = +1;
                        return previous;
                }
        }
 
-       if(fieldflags & SFL_LOWER_IS_BETTER)
-               previous.x = (t2.field - t1.field);
+       if (fieldflags & SFL_LOWER_IS_BETTER)
+               previous.x = (t2.(field) - t1.(field));
        else
-               previous.x = (t1.field - t2.field);
+               previous.x = (t1.(field) - t2.(field));
 
        return previous;
 }
@@ -180,7 +186,7 @@ void ScoreInfo_SetLabel_TeamScore(float i, string label, float scoreflags)
        }
 }
 
-float ScoreInfo_SendEntity(entity to, float sf)
+float ScoreInfo_SendEntity(entity to, int sf)
 {
        float i;
        WriteByte(MSG_ENTITY, ENT_CLIENT_SCORES_INFO);
@@ -699,7 +705,7 @@ entity PlayerScore_Sort(.float field, float teams, float strict, float nospectat
        plist = world;
 
        FOR_EACH_CLIENT(p)
-               p.field = 0;
+               p.(field) = 0;
 
        FOR_EACH_CLIENT(p) if(p.scorekeeper)
        {
@@ -739,7 +745,7 @@ entity PlayerScore_Sort(.float field, float teams, float strict, float nospectat
                if(!plast || PlayerTeamScore_Compare(plast, pbest, teams, 0))
                        j = i;
 
-               pbest.field = j;
+               pbest.(field) = j;
 
                if (!pfirst)
                        pfirst = pbest;
index ff0555cad6cf4d24a27dc9089a327d45dc9bed97..8c9af4534fa1158106727abaf7b52716f4ad0908 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef SCORES_H
 #define SCORES_H
 
+#include "../common/constants.qh"
+
 entity scores_initialized; // non-world when scores labels/rules have been set
 .float scores[MAX_SCORE];
 .float teamscores[MAX_TEAMSCORE];
index 4d5296c81603503cafd812c5b5d59c29e1e7786e..aefb1754b5ceaab137e2e4d1bb13fa4fa2a3374f 100644 (file)
@@ -1,14 +1,9 @@
-#if defined(CSQC)
-#elif defined(MENUQC)
-#elif defined(SVQC)
-       #include "../dpdefs/progsdefs.qh"
-    #include "../common/constants.qh"
-    #include "autocvars.qh"
-    #include "defs.qh"
-    #include "scores.qh"
-#endif
-
-//float c1, c2, c3, c4;
+#include "scores_rules.qh"
+#include "_all.qh"
+
+#include "cl_client.qh"
+#include "scores.qh"
+
 void CheckAllowedTeams (entity for_whom);
 
 // NOTE: SP_ constants may not be >= MAX_SCORE; ST_constants may not be >= MAX_TEAMSCORE
diff --git a/qcsrc/server/scores_rules.qh b/qcsrc/server/scores_rules.qh
new file mode 100644 (file)
index 0000000..b307eeb
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef SCORES_RULES_H
+#define SCORES_RULES_H
+
+void ScoreRules_basics(float teams, float sprio, float stprio, float score_enabled);
+void ScoreRules_basics_end();
+void ScoreRules_generic();
+
+#endif
diff --git a/qcsrc/server/secret.qc b/qcsrc/server/secret.qc
deleted file mode 100644 (file)
index 30fbedc..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-#if defined(CSQC)
-#elif defined(MENUQC)
-#elif defined(SVQC)
-       #include "../dpdefs/progsdefs.qh"
-    #include "../common/util.qh"
-    #include "defs.qh"
-    #include "secret.qh"
-#endif
-
-void secrets_setstatus() {
-       self.stat_secrets_total = secrets_total;
-       self.stat_secrets_found = secrets_found;
-}
-
-/**
- * A secret has been found (maybe :P)
- */
-void trigger_secret_touch() {
-       // only a player can trigger this
-       if (!IS_PLAYER(other))
-               return;
-
-       // update secrets found counter
-       secrets_found += 1;
-       //print("Secret found: ", ftos(secret_counter.cnt), "/");
-       //print(ftos(secret_counter.count), "\n");
-
-       // centerprint message (multi_touch() doesn't always call centerprint())
-       centerprint(other, self.message);
-       self.message = "";
-
-       // handle normal trigger features
-       multi_touch();
-       remove(self);
-}
-
-/*QUAKED trigger_secret (.5 .5 .5) ?
-Variable sized secret trigger. Can be targeted at one or more entities.
-Basically, it's a trigger_once (with restrictions, see notes) that additionally updates the number of secrets found.
--------- KEYS --------
-sounds: 1 to play misc/secret.wav, 2 to play misc/talk.wav, 3 to play misc/trigger1.wav (default: 1)
-noise: path to sound file, if you want to play something else
-target: trigger all entities with this targetname when triggered
-message: print this message to the player who activated the trigger instead of the standard 'You found a secret!'
-killtarget: remove all entities with this targetname when triggered
--------- NOTES --------
-You should create a common/trigger textured brush covering the entrance to a secret room/area.
-Trigger secret can only be trigger by a player's touch and can not be a target itself.
-*/
-void spawnfunc_trigger_secret() {
-       // FIXME: should it be disabled in most modes?
-
-       // update secrets count
-       secrets_total += 1;
-
-       // add default message
-       if (self.message == "")
-               self.message = "You found a secret!";
-
-       // set default sound
-       if (self.noise == "")
-       if (!self.sounds)
-               self.sounds = 1; // misc/secret.wav
-
-       // this entity can't be a target itself!!!!
-       self.targetname = "";
-
-       // you can't just shoot a room to find it, can you?
-       self.health = 0;
-
-       // a secret can not be delayed
-       self.delay = 0;
-
-       // convert this trigger to trigger_once
-       self.classname = "trigger_once";
-       spawnfunc_trigger_once();
-
-       // take over the touch() function, so we can mark secret as found
-       self.touch = trigger_secret_touch;
-       // ignore triggering;
-       self.use = func_null;
-}
-
diff --git a/qcsrc/server/secret.qh b/qcsrc/server/secret.qh
deleted file mode 100644 (file)
index 6e6ae0b..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-#ifndef SECRET_H
-#define SECRET_H
-
-/**
- * Total number of secrets on the map.
- */
-float secrets_total;
-
-/**
- * Total numbe of secrets found on the map.
- */
-float secrets_found;
-
-
-.float stat_secrets_total;
-.float stat_secrets_found;
-
-/**
- * update secrets status.
- */
-void secrets_setstatus();
-#endif
index 253c70fbe071eff1be2f03a54c64bd18a7d06b58..b86da6b54ee9f0823dec8d72f2a34d11de7f40b0 100644 (file)
@@ -1,21 +1,15 @@
-#if defined(CSQC)
-#elif defined(MENUQC)
-#elif defined(SVQC)
-       #include "../dpdefs/progsdefs.qh"
-    #include "../dpdefs/dpextensions.qh"
-    #include "../warpzonelib/util_server.qh"
-    #include "../common/constants.qh"
-    #include "../common/teams.qh"
-    #include "../common/util.qh"
-    #include "autocvars.qh"
-    #include "constants.qh"
-    #include "defs.qh"
-    #include "mutators/mutators_include.qh"
-    #include "spawnpoints.qh"
-    #include "race.qh"
-#endif
-
-float SpawnPoint_Send(entity to, float sf)
+#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/util.qh"
+#include "../warpzonelib/util_server.qh"
+
+float SpawnPoint_Send(entity to, int sf)
 {
        WriteByte(MSG_ENTITY, ENT_CLIENT_SPAWNPOINT);
 
@@ -27,7 +21,7 @@ float SpawnPoint_Send(entity to, float sf)
        return true;
 }
 
-float SpawnEvent_Send(entity to, float sf)
+float SpawnEvent_Send(entity to, int sf)
 {
        float send;
 
@@ -67,13 +61,13 @@ void relocate_spawnpoint()
     // nudge off the floor
     setorigin(self, self.origin + '0 0 1');
 
-    tracebox(self.origin, PL_MIN, PL_MAX, self.origin, true, self);
+    tracebox(self.origin, PL_MIN_CONST, PL_MAX_CONST, self.origin, true, self);
     if (trace_startsolid)
     {
         vector o;
         o = self.origin;
-        self.mins = PL_MIN;
-        self.maxs = PL_MAX;
+        self.mins = PL_MIN_CONST;
+        self.maxs = PL_MAX_CONST;
         if (!move_out_of_solid(self))
             objerror("could not get out of solid at all!");
         print("^1NOTE: this map needs FIXING. Spawnpoint at ", vtos(o - '0 0 1'));
index beab71c7ad104db99c7a87a593ce4bcd13191c28..b654d83caf2af105857004642c06701259e7c691 100644 (file)
@@ -3,7 +3,7 @@
 
 .vector spawnpoint_score;
 float spawnpoint_nag;
-float SpawnEvent_Send(entity to, float sf);
+float SpawnEvent_Send(entity to, int sf);
 entity Spawn_FilterOutBadSpots(entity firstspot, float mindist, float teamcheck);
 entity SelectSpawnPoint (float anypoint);
 #endif
index ec76dfef2cda72354df3d1557fdd30e71f19dd7b..f102017b5fc79ce58ae10a4117db276acfe33bc5 100644 (file)
@@ -5,8 +5,6 @@
     #include "../dpdefs/dpextensions.qh"
 #endif
 
-.vector steerto;
-
 /**
     Uniform pull towards a point
 **/
diff --git a/qcsrc/server/steerlib.qh b/qcsrc/server/steerlib.qh
new file mode 100644 (file)
index 0000000..fcd35ba
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef STEERLIB_H
+#define STEERLIB_H
+
+.vector steerto;
+
+vector steerlib_arrive(vector point,float maximal_distance);
+vector steerlib_attract2(vector point, float min_influense,float max_distance,float max_influense);
+vector steerlib_pull(vector point);
+
+#endif
index c2d3dc7dd855c3eb3f84e6f0dd0efde296a30e09..48cd05361ed9b9192a4949b27117c9287b2462ab 100644 (file)
@@ -1,26 +1,31 @@
-#if defined(CSQC)
-#elif defined(MENUQC)
-#elif defined(SVQC)
-       #include "../dpdefs/progsdefs.qh"
-    #include "../dpdefs/dpextensions.qh"
-    #include "../warpzonelib/common.qh"
-    #include "../warpzonelib/server.qh"
-    #include "../common/constants.qh"
-    #include "../common/util.qh"
-    #include "../common/weapons/weapons.qh"
-    #include "weapons/csqcprojectile.qh"
-    #include "autocvars.qh"
-    #include "constants.qh"
-    #include "defs.qh"
-    #include "../common/deathtypes.qh"
-    #include "mutators/mutators_include.qh"
-    #include "vehicles/vehicles_def.qh"
-    #include "../common/mapinfo.qh"
-    #include "command/common.qh"
-    #include "../csqcmodellib/sv_model.qh"
-    #include "anticheat.qh"
-    #include "g_hook.qh"
-#endif
+#include "_all.qh"
+
+#include "anticheat.qh"
+#include "g_hook.qh"
+#include "g_world.qh"
+
+#include "bot/bot.qh"
+#include "bot/waypoints.qh"
+
+#include "command/common.qh"
+
+#include "mutators/mutators_include.qh"
+#include "vehicles/vehicle.qh"
+#include "weapons/csqcprojectile.qh"
+
+#include "../common/constants.qh"
+#include "../common/deathtypes.qh"
+#include "../common/mapinfo.qh"
+#include "../common/util.qh"
+
+#include "../common/weapons/all.qh"
+
+#include "../csqcmodellib/sv_model.qh"
+
+#include "../warpzonelib/common.qh"
+#include "../warpzonelib/server.qh"
+
+.float lastground;
 
 void CreatureFrame (void)
 {
@@ -135,6 +140,7 @@ void CreatureFrame (void)
                        if (g_footsteps)
                        if (!gameover)
                        if (self.flags & FL_ONGROUND)
+                       if (!self.crouch)
                        if (velocity_len > autocvar_sv_maxspeed * 0.6)
                        if (!self.deadflag)
                        if (time < self.lastground + 0.2)
index 681c5dc7d3f0998788b485baf38bd495d49a9682..f041dd39659aebd31a8b375b6e14d1fd51820f1c 100644 (file)
@@ -1,12 +1,3 @@
-#if defined(CSQC)
-#elif defined(MENUQC)
-#elif defined(SVQC)
-       #include "../dpdefs/progsdefs.qh"
-    #include "../warpzonelib/util_server.qh"
-    #include "defs.qh"
-    #include "vehicles/vehicles_def.qh"
-#endif
-
 .float  roomtype;
 .float  radius;
 .float  pitch;
@@ -41,30 +32,3 @@ void spawnfunc_info_node() {}
 void spawnfunc_env_sound() {}
 void spawnfunc_light_spot() {}
 void spawnfunc_func_healthcharger() {}
-
-
-void func_ladder_touch()
-{
-       if (!other.iscreature)
-               return;
-       if (other.vehicle_flags & VHF_ISVEHICLE)
-               return;
-
-       EXACTTRIGGER_TOUCH;
-
-       other.ladder_time = time + 0.1;
-       other.ladder_entity = self;
-}
-
-void spawnfunc_func_ladder()
-{
-       EXACTTRIGGER_INIT;
-       self.touch = func_ladder_touch;
-}
-
-void spawnfunc_func_water()
-{
-       EXACTTRIGGER_INIT;
-       self.touch = func_ladder_touch;
-}
-
index 03af802e71c12d8b762c0e34df606ba8c096ee3d..4e3e376e3b26625d03bb5c8ff1cd8f22c20a60c0 100644 (file)
@@ -1,31 +1,32 @@
-#if defined(CSQC)
-    #include "../dpdefs/csprogsdefs.qh"
-    #include "../common/util.qh"
-    #include "../common/buffs.qh"
-    #include "../common/weapons/weapons.qh"
-    #include "../client/autocvars.qh"
-    #include "../client/movetypes.qh"
-    #include "../client/main.qh"
-    #include "../csqcmodellib/common.qh"
-    #include "../csqcmodellib/cl_model.qh"
-    #include "t_items.qh"
-#elif defined(MENUQC)
-#elif defined(SVQC)
-    #include "../dpdefs/progsdefs.qh"
-    #include "../dpdefs/dpextensions.qh"
-    #include "../warpzonelib/util_server.qh"
-    #include "../common/constants.qh"
-    #include "../common/util.qh"
-    #include "../common/monsters/monsters.qh"
-    #include "../common/weapons/weapons.qh"
+#include "t_items.qh"
+
+#include "../common/items/all.qc"
+
+#if defined(SVQC)
+    #include "_all.qh"
+
+    #include "waypointsprites.qh"
+
+    #include "bot/bot.qh"
+    #include "bot/waypoints.qh"
+
+    #include "mutators/mutators_include.qh"
+
+    #include "weapons/common.qh"
+    #include "weapons/selection.qh"
     #include "weapons/weaponsystem.qh"
-    #include "t_items.qh"
-    #include "autocvars.qh"
-    #include "constants.qh"
-    #include "defs.qh"
-    #include "../common/notifications.qh"
+
+    #include "../common/constants.qh"
     #include "../common/deathtypes.qh"
-    #include "mutators/mutators_include.qh"
+    #include "../common/notifications.qh"
+       #include "../common/triggers/subs.qh"
+    #include "../common/util.qh"
+
+    #include "../common/monsters/all.qh"
+
+    #include "../common/weapons/all.qh"
+
+    #include "../warpzonelib/util_server.qh"
 #endif
 
 #ifdef CSQC
@@ -229,7 +230,7 @@ void ItemRead(float _IsNew)
 #endif
 
 #ifdef SVQC
-float ItemSend(entity to, float sf)
+bool ItemSend(entity to, int sf)
 {
     if(self.gravity)
         sf |= ISF_DROP;
@@ -537,23 +538,23 @@ void Item_ScheduleInitialRespawn(entity e)
 
 float Item_GiveAmmoTo(entity item, entity player, .float ammotype, float ammomax, float mode)
 {
-       if (!item.ammotype)
+       if (!item.(ammotype))
                return false;
 
        if (item.spawnshieldtime)
        {
-               if ((player.ammotype < ammomax) || item.pickup_anyway)
+               if ((player.(ammotype) < ammomax) || item.pickup_anyway)
                {
-                       player.ammotype = bound(player.ammotype, ammomax, player.ammotype + item.ammotype);
+                       player.(ammotype) = bound(player.(ammotype), ammomax, player.(ammotype) + item.(ammotype));
                        goto YEAH;
                }
        }
        else if(g_weapon_stay == 2)
        {
-               float mi = min(item.ammotype, ammomax);
-               if (player.ammotype < mi)
+               float mi = min(item.(ammotype), ammomax);
+               if (player.(ammotype) < mi)
                {
-                       player.ammotype = mi;
+                       player.(ammotype) = mi;
                        goto YEAH;
                }
        }
@@ -664,6 +665,8 @@ float Item_GiveTo(entity item, entity player)
        return 1;
 }
 
+.entity itemdef;
+
 void Item_Touch (void)
 {
        entity e, head;
@@ -703,8 +706,9 @@ void Item_Touch (void)
                self.invincible_finished = max(0, self.invincible_finished - time);
                self.superweapons_finished = max(0, self.superweapons_finished - time);
        }
-
-       if(!Item_GiveTo(self, other))
+       entity it = self.itemdef;
+       bool gave = (it && it.instanceOfPickup) ? ITEM_HANDLE(Pickup, it, self, other) : Item_GiveTo(self, other);
+       if (!gave)
        {
                if (self.classname == "droppedweapon")
                {
@@ -725,9 +729,7 @@ void Item_Touch (void)
 
        if (self.classname == "droppedweapon")
                remove (self);
-       else if (!self.spawnshieldtime)
-               return;
-       else
+       else if (self.spawnshieldtime)
        {
                if(self.team)
                {
@@ -811,7 +813,7 @@ float generic_pickupevalfunc(entity player, entity item) {return item.bot_pickup
 
 float weapon_pickupevalfunc(entity player, entity item)
 {
-       float c, j, position;
+       float c;
 
        // See if I have it already
        if(item.weapons & ~player.weapons)
@@ -834,8 +836,8 @@ float weapon_pickupevalfunc(entity player, entity item)
        if( bot_custom_weapon && c )
        {
                // Find the highest position on any range
-               position = -1;
-               for(j = 0; j < WEP_LAST ; ++j){
+               int position = -1;
+               for (int j = 0; j < WEP_LAST ; ++j){
                        if(
                                        bot_weapons_far[j] == item.weapon ||
                                        bot_weapons_mid[j] == item.weapon ||
@@ -925,7 +927,7 @@ float commodity_pickupevalfunc(entity player, entity item)
        return item.bot_pickupbasevalue * c;
 }
 
-void Item_Damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
+void Item_Damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
 {
        if(ITEM_DAMAGE_NEEDKILL(deathtype))
                RemoveItem();
@@ -1152,15 +1154,21 @@ void StartItem (string itemmodel, string pickupsound, float defaultrespawntime,
                return;
        }
 }
+
+void StartItemA (entity a)
+{
+    self.itemdef = a;
+    StartItem(a.m_model, a.m_sound, a.m_respawntime(), a.m_respawntimejitter(), a.m_name, a.m_itemid, 0, a.m_itemflags, a.m_pickupevalfunc, a.m_botvalue);
+}
+
 void spawnfunc_item_rockets (void) {
        if(!self.ammo_rockets)
                self.ammo_rockets = g_pickup_rockets;
        if(!self.pickup_anyway)
                self.pickup_anyway = g_pickup_ammo_anyway;
-       StartItem ("models/items/a_rockets.md3", "misc/itempickup.wav", g_pickup_respawntime_ammo, g_pickup_respawntimejitter_ammo, "rockets", IT_ROCKETS, 0, 0, commodity_pickupevalfunc, 3000);
+    StartItemA (ITEM_Rockets);
 }
 
-void spawnfunc_item_shells (void);
 void spawnfunc_item_bullets (void) {
        if(!weaponswapping)
        if(autocvar_sv_q3acompat_machineshotgunswap)
@@ -1176,7 +1184,7 @@ void spawnfunc_item_bullets (void) {
                self.ammo_nails = g_pickup_nails;
        if(!self.pickup_anyway)
                self.pickup_anyway = g_pickup_ammo_anyway;
-       StartItem ("models/items/a_bullets.mdl", "misc/itempickup.wav", g_pickup_respawntime_ammo, g_pickup_respawntimejitter_ammo, "bullets", IT_NAILS, 0, 0, commodity_pickupevalfunc, 2000);
+    StartItemA (ITEM_Bullets);
 }
 
 void spawnfunc_item_cells (void) {
@@ -1184,7 +1192,7 @@ void spawnfunc_item_cells (void) {
                self.ammo_cells = g_pickup_cells;
        if(!self.pickup_anyway)
                self.pickup_anyway = g_pickup_ammo_anyway;
-       StartItem ("models/items/a_cells.md3", "misc/itempickup.wav", g_pickup_respawntime_ammo, g_pickup_respawntimejitter_ammo, "cells", IT_CELLS, 0, 0, commodity_pickupevalfunc, 2000);
+       StartItemA (ITEM_Cells);
 }
 
 void spawnfunc_item_plasma()
@@ -1193,7 +1201,7 @@ void spawnfunc_item_plasma()
                self.ammo_plasma = g_pickup_plasma;
        if(!self.pickup_anyway)
                self.pickup_anyway = g_pickup_ammo_anyway;
-       StartItem ("models/items/a_cells.md3", "misc/itempickup.wav", g_pickup_respawntime_ammo, g_pickup_respawntimejitter_ammo, "plasma", IT_PLASMA, 0, 0, commodity_pickupevalfunc, 2000);
+       StartItemA (ITEM_Plasma);
 }
 
 void spawnfunc_item_shells (void) {
@@ -1211,7 +1219,7 @@ void spawnfunc_item_shells (void) {
                self.ammo_shells = g_pickup_shells;
        if(!self.pickup_anyway)
                self.pickup_anyway = g_pickup_ammo_anyway;
-       StartItem ("models/items/a_shells.md3", "misc/itempickup.wav", g_pickup_respawntime_ammo, g_pickup_respawntimejitter_ammo, "shells", IT_SHELLS, 0, 0, commodity_pickupevalfunc, 500);
+       StartItemA (ITEM_Shells);
 }
 
 void spawnfunc_item_armor_small (void) {
@@ -1221,7 +1229,7 @@ void spawnfunc_item_armor_small (void) {
                self.max_armorvalue = g_pickup_armorsmall_max;
        if(!self.pickup_anyway)
                self.pickup_anyway = g_pickup_armorsmall_anyway;
-       StartItem ("models/items/item_armor_small.md3", "misc/armor1.wav", g_pickup_respawntime_short, g_pickup_respawntimejitter_short, "5 Armor", IT_ARMOR_SHARD, 0, 0, commodity_pickupevalfunc, BOT_PICKUP_RATING_LOW);
+       StartItemA (ITEM_ArmorSmall);
 }
 
 void spawnfunc_item_armor_medium (void) {
@@ -1231,7 +1239,7 @@ void spawnfunc_item_armor_medium (void) {
                self.max_armorvalue = g_pickup_armormedium_max;
        if(!self.pickup_anyway)
                self.pickup_anyway = g_pickup_armormedium_anyway;
-       StartItem ("models/items/item_armor_medium.md3", "misc/armor10.wav", g_pickup_respawntime_medium, g_pickup_respawntimejitter_medium, "25 Armor", IT_ARMOR, 0, 0, commodity_pickupevalfunc, BOT_PICKUP_RATING_MID);
+       StartItemA (ITEM_ArmorMedium);
 }
 
 void spawnfunc_item_armor_big (void) {
@@ -1241,7 +1249,7 @@ void spawnfunc_item_armor_big (void) {
                self.max_armorvalue = g_pickup_armorbig_max;
        if(!self.pickup_anyway)
                self.pickup_anyway = g_pickup_armorbig_anyway;
-       StartItem ("models/items/item_armor_big.md3", "misc/armor17_5.wav", g_pickup_respawntime_long, g_pickup_respawntimejitter_long, "50 Armor", IT_ARMOR, 0, 0, commodity_pickupevalfunc, 20000);
+       StartItemA (ITEM_ArmorBig);
 }
 
 void spawnfunc_item_armor_large (void) {
@@ -1251,7 +1259,7 @@ void spawnfunc_item_armor_large (void) {
                self.max_armorvalue = g_pickup_armorlarge_max;
        if(!self.pickup_anyway)
                self.pickup_anyway = g_pickup_armorlarge_anyway;
-       StartItem ("models/items/item_armor_large.md3", "misc/armor25.wav", g_pickup_respawntime_long, g_pickup_respawntimejitter_long, "100 Armor", IT_ARMOR, 0, 0, commodity_pickupevalfunc, BOT_PICKUP_RATING_HIGH);
+       StartItemA (ITEM_ArmorLarge);
 }
 
 void spawnfunc_item_health_small (void) {
@@ -1261,7 +1269,7 @@ void spawnfunc_item_health_small (void) {
                self.health = g_pickup_healthsmall;
        if(!self.pickup_anyway)
                self.pickup_anyway = g_pickup_healthsmall_anyway;
-       StartItem ("models/items/g_h1.md3", "misc/minihealth.wav", g_pickup_respawntime_short, g_pickup_respawntimejitter_short, "5 Health", IT_5HP, 0, 0, commodity_pickupevalfunc, BOT_PICKUP_RATING_LOW);
+       StartItemA (ITEM_HealthSmall);
 }
 
 void spawnfunc_item_health_medium (void) {
@@ -1271,7 +1279,7 @@ void spawnfunc_item_health_medium (void) {
                self.health = g_pickup_healthmedium;
        if(!self.pickup_anyway)
                self.pickup_anyway = g_pickup_healthmedium_anyway;
-       StartItem ("models/items/g_h25.md3", "misc/mediumhealth.wav", g_pickup_respawntime_short, g_pickup_respawntimejitter_short, "25 Health", IT_25HP, 0, 0, commodity_pickupevalfunc, BOT_PICKUP_RATING_MID);
+    StartItemA (ITEM_HealthMedium);
 }
 
 void spawnfunc_item_health_large (void) {
@@ -1281,17 +1289,17 @@ void spawnfunc_item_health_large (void) {
                self.health = g_pickup_healthlarge;
        if(!self.pickup_anyway)
                self.pickup_anyway = g_pickup_healthlarge_anyway;
-       StartItem ("models/items/g_h50.md3", "misc/mediumhealth.wav", g_pickup_respawntime_medium, g_pickup_respawntimejitter_medium, "50 Health", IT_25HP, 0, 0, commodity_pickupevalfunc, BOT_PICKUP_RATING_MID);
+       StartItemA (ITEM_HealthLarge);
 }
 
 void spawnfunc_item_health_mega (void) {
-               if(!self.max_health)
-                       self.max_health = g_pickup_healthmega_max;
-               if(!self.health)
-                       self.health = g_pickup_healthmega;
-               if(!self.pickup_anyway)
-                       self.pickup_anyway = g_pickup_healthmega_anyway;
-               StartItem ("models/items/g_h100.md3", "misc/megahealth.wav", g_pickup_respawntime_long, g_pickup_respawntimejitter_long, "100 Health", IT_HEALTH, 0, 0, commodity_pickupevalfunc, BOT_PICKUP_RATING_HIGH);
+    if(!self.max_health)
+        self.max_health = g_pickup_healthmega_max;
+    if(!self.health)
+        self.health = g_pickup_healthmega;
+    if(!self.pickup_anyway)
+        self.pickup_anyway = g_pickup_healthmega_anyway;
+    StartItemA (ITEM_HealthMega);
 }
 
 // support old misnamed entities
@@ -1305,13 +1313,13 @@ void spawnfunc_item_strength (void) {
                precache_sound("weapons/strength_fire.wav");
                if(!self.strength_finished)
                        self.strength_finished = autocvar_g_balance_powerup_strength_time;
-               StartItem ("models/items/g_strength.md3", "misc/powerup.wav", g_pickup_respawntime_powerup, g_pickup_respawntimejitter_powerup, "Strength Powerup", IT_STRENGTH, 0, FL_POWERUP, generic_pickupevalfunc, 100000);
+               StartItemA (ITEM_Strength);
 }
 
 void spawnfunc_item_invincible (void) {
                if(!self.invincible_finished)
                        self.invincible_finished = autocvar_g_balance_powerup_invincible_time;
-               StartItem ("models/items/g_invincible.md3", "misc/powerup_shield.wav", g_pickup_respawntime_powerup, g_pickup_respawntimejitter_powerup, "Shield", IT_INVINCIBLE, 0, FL_POWERUP, generic_pickupevalfunc, 100000);
+               StartItemA (ITEM_Shield);
 }
 
 // compatibility:
@@ -1472,7 +1480,7 @@ void spawnfunc_item_fuel(void)
                self.ammo_fuel = g_pickup_fuel;
        if(!self.pickup_anyway)
                self.pickup_anyway = g_pickup_ammo_anyway;
-       StartItem ("models/items/g_fuel.md3", "misc/itempickup.wav", g_pickup_respawntime_ammo, g_pickup_respawntimejitter_ammo, "Fuel", IT_FUEL, 0, 0, commodity_pickupevalfunc, BOT_PICKUP_RATING_LOW);
+       StartItemA (ITEM_JetpackFuel);
 }
 
 void spawnfunc_item_fuel_regen(void)
@@ -1482,7 +1490,7 @@ void spawnfunc_item_fuel_regen(void)
                spawnfunc_item_fuel();
                return;
        }
-       StartItem ("models/items/g_fuelregen.md3", "misc/itempickup.wav", g_pickup_respawntime_powerup, g_pickup_respawntimejitter_powerup, "Fuel regenerator", IT_FUEL_REGEN, 0, FL_POWERUP, commodity_pickupevalfunc, BOT_PICKUP_RATING_LOW);
+       StartItemA (ITEM_JetpackRegen);
 }
 
 void spawnfunc_item_jetpack(void)
@@ -1494,7 +1502,7 @@ void spawnfunc_item_jetpack(void)
                spawnfunc_item_fuel();
                return;
        }
-       StartItem ("models/items/g_jetpack.md3", "misc/itempickup.wav", g_pickup_respawntime_powerup, g_pickup_respawntimejitter_powerup, "Jet pack", IT_JETPACK, 0, FL_POWERUP, commodity_pickupevalfunc, BOT_PICKUP_RATING_LOW);
+       StartItemA (ITEM_Jetpack);
 }
 
 float GiveWeapon(entity e, float wpn, float op, float val)
@@ -1530,56 +1538,56 @@ float GiveWeapon(entity e, float wpn, float op, float val)
 float GiveBit(entity e, .float fld, float bit, float op, float val)
 {
        float v0, v1;
-       v0 = (e.fld & bit);
+       v0 = (e.(fld) & bit);
        switch(op)
        {
                case OP_SET:
                        if(val > 0)
-                               e.fld |= bit;
+                               e.(fld) |= bit;
                        else
-                               e.fld &= ~bit;
+                               e.(fld) &= ~bit;
                        break;
                case OP_MIN:
                case OP_PLUS:
                        if(val > 0)
-                               e.fld |= bit;
+                               e.(fld) |= bit;
                        break;
                case OP_MAX:
                        if(val <= 0)
-                               e.fld &= ~bit;
+                               e.(fld) &= ~bit;
                        break;
                case OP_MINUS:
                        if(val > 0)
-                               e.fld &= ~bit;
+                               e.(fld) &= ~bit;
                        break;
        }
-       v1 = (e.fld & bit);
+       v1 = (e.(fld) & bit);
        return (v0 != v1);
 }
 
 float GiveValue(entity e, .float fld, float op, float val)
 {
        float v0, v1;
-       v0 = e.fld;
+       v0 = e.(fld);
        switch(op)
        {
                case OP_SET:
-                       e.fld = val;
+                       e.(fld) = val;
                        break;
                case OP_MIN:
-                       e.fld = max(e.fld, val); // min 100 cells = at least 100 cells
+                       e.(fld) = max(e.(fld), val); // min 100 cells = at least 100 cells
                        break;
                case OP_MAX:
-                       e.fld = min(e.fld, val);
+                       e.(fld) = min(e.(fld), val);
                        break;
                case OP_PLUS:
-                       e.fld += val;
+                       e.(fld) += val;
                        break;
                case OP_MINUS:
-                       e.fld -= val;
+                       e.(fld) -= val;
                        break;
        }
-       v1 = e.fld;
+       v1 = e.(fld);
        return (v0 != v1);
 }
 
@@ -1602,9 +1610,9 @@ void GiveSound(entity e, float v0, float v1, float t, string snd_incr, string sn
 void GiveRot(entity e, float v0, float v1, .float rotfield, float rottime, .float regenfield, float regentime)
 {
        if(v0 < v1)
-               e.rotfield = max(e.rotfield, time + rottime);
+               e.(rotfield) = max(e.(rotfield), time + rottime);
        else if(v0 > v1)
-               e.regenfield = max(e.regenfield, time + regentime);
+               e.(regenfield) = max(e.(regenfield), time + regentime);
 }
 float GiveItems(entity e, float beginarg, float endarg)
 {
index bb914234e1c26bf8abfe8d385ce718bc1d36f0de..a33e45a82c388acbb55dd9cf59fe4c1819752803 100644 (file)
@@ -10,10 +10,14 @@ const int IT_JETPACK                        =      16; // actual item
 const int IT_FUEL_REGEN                        =      32; // fuel regeneration trigger
 // where is 64... ?
 const int IT_FUEL                                      =     128;
-const int IT_SHELLS                                    =     256;
-const int IT_NAILS                                     =     512;
-const int IT_ROCKETS                                   =    1024;
-const int IT_CELLS                                     =    2048;
+// -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;
@@ -22,8 +26,10 @@ const int IT_PLASMA                                  =   65536;
 
 // shared value space (union):
        // for items:
-       const int IT_KEY1                                       =  131072;
-       const int IT_KEY2                                       =  262144;
+       // -Wdouble-declaration
+       #define IT_KEY1                                                 131072
+       // -Wdouble-declaration
+       #define IT_KEY2                                                 262144
        // for players:
        const int IT_RED_FLAG_TAKEN             =   32768;
        const int IT_RED_FLAG_LOST              =   65536;
@@ -84,8 +90,15 @@ void ItemRead(float _IsNew);
 
 #endif
 #ifdef SVQC
+void spawnfunc_item_strength();
+void spawnfunc_item_invincible();
+void spawnfunc_item_armor_small();
+void spawnfunc_item_shells();
+void spawnfunc_item_bullets();
+void spawnfunc_item_rockets();
+
 float autocvar_sv_simple_items;
-float ItemSend(entity to, float sf);
+bool ItemSend(entity to, int sf);
 
 
 float have_pickup_item(void);
@@ -126,7 +139,7 @@ void Item_FindTeam();
 // Savage: used for item garbage-collection
 // TODO: perhaps nice special effect?
 
-float ItemSend(entity to, float sf);
+bool ItemSend(entity to, int sf);
 void ItemUpdate(entity item);
 
 // pickup evaluation functions
diff --git a/qcsrc/server/t_jumppads.qc b/qcsrc/server/t_jumppads.qc
deleted file mode 100644 (file)
index 92af1cd..0000000
+++ /dev/null
@@ -1,330 +0,0 @@
-#include "t_jumppads.qh"
-
-void trigger_push_use()
-{
-       if(teamplay)
-               self.team = activator.team;
-}
-
-/*
-       trigger_push_calculatevelocity
-
-       Arguments:
-         org - origin of the object which is to be pushed
-         tgt - target entity (can be either a point or a model entity; if it is
-               the latter, its midpoint is used)
-         ht  - jump height, measured from the higher one of org and tgt's midpoint
-
-       Returns: velocity for the jump
-       the global trigger_push_calculatevelocity_flighttime is set to the total
-       jump time
- */
-
-vector trigger_push_calculatevelocity(vector org, entity tgt, float ht)
-{
-       float grav, sdist, zdist, vs, vz, jumpheight;
-       vector sdir, torg;
-
-       torg = tgt.origin + (tgt.mins + tgt.maxs) * 0.5;
-
-       grav = autocvar_sv_gravity;
-       if(other.gravity)
-               grav *= other.gravity;
-
-       zdist = torg.z - org.z;
-       sdist = vlen(torg - org - zdist * '0 0 1');
-       sdir = normalize(torg - org - zdist * '0 0 1');
-
-       // how high do we need to push the player?
-       jumpheight = fabs(ht);
-       if(zdist > 0)
-               jumpheight = jumpheight + zdist;
-
-       /*
-               STOP.
-
-               You will not understand the following equations anyway...
-               But here is what I did to get them.
-
-               I used the functions
-
-                 s(t) = t * vs
-                 z(t) = t * vz - 1/2 grav t^2
-
-               and solved for:
-
-                 s(ti) = sdist
-                 z(ti) = zdist
-                 max(z, ti) = jumpheight
-
-               From these three equations, you will find the three parameters vs, vz
-               and ti.
-        */
-
-       // push him so high...
-       vz = sqrt(fabs(2 * grav * jumpheight)); // NOTE: sqrt(positive)!
-
-       // we start with downwards velocity only if it's a downjump and the jump apex should be outside the jump!
-       if(ht < 0)
-               if(zdist < 0)
-                       vz = -vz;
-
-       vector solution;
-       solution = solve_quadratic(0.5 * grav, -vz, zdist); // equation "z(ti) = zdist"
-       // ALWAYS solvable because jumpheight >= zdist
-       if(!solution.z)
-               solution.y = solution.x; // just in case it is not solvable due to roundoff errors, assume two equal solutions at their center (this is mainly for the usual case with ht == 0)
-       if(zdist == 0)
-               solution.x = solution.y; // solution_x is 0 in this case, so don't use it, but rather use solution_y (which will be sqrt(0.5 * jumpheight / grav), actually)
-
-       if(zdist < 0)
-       {
-               // down-jump
-               if(ht < 0)
-               {
-                       // almost straight line type
-                       // jump apex is before the jump
-                       // we must take the larger one
-                       trigger_push_calculatevelocity_flighttime = solution.y;
-               }
-               else
-               {
-                       // regular jump
-                       // jump apex is during the jump
-                       // we must take the larger one too
-                       trigger_push_calculatevelocity_flighttime = solution.y;
-               }
-       }
-       else
-       {
-               // up-jump
-               if(ht < 0)
-               {
-                       // almost straight line type
-                       // jump apex is after the jump
-                       // we must take the smaller one
-                       trigger_push_calculatevelocity_flighttime = solution.x;
-               }
-               else
-               {
-                       // regular jump
-                       // jump apex is during the jump
-                       // we must take the larger one
-                       trigger_push_calculatevelocity_flighttime = solution.y;
-               }
-       }
-       vs = sdist / trigger_push_calculatevelocity_flighttime;
-
-       // finally calculate the velocity
-       return sdir * vs + '0 0 1' * vz;
-}
-
-void trigger_push_touch()
-{
-       if (self.active == ACTIVE_NOT)
-               return;
-
-       if (!isPushable(other))
-               return;
-
-       if(self.team)
-               if(((self.spawnflags & 4) == 0) == (self.team != other.team))
-                       return;
-
-       EXACTTRIGGER_TOUCH;
-
-       if(self.enemy)
-       {
-               other.velocity = trigger_push_calculatevelocity(other.origin, self.enemy, self.height);
-       }
-       else if(self.target)
-       {
-               entity e;
-               RandomSelection_Init();
-               for(e = world; (e = find(e, targetname, self.target)); )
-               {
-                       if(e.cnt)
-                               RandomSelection_Add(e, 0, string_null, e.cnt, 1);
-                       else
-                               RandomSelection_Add(e, 0, string_null, 1, 1);
-               }
-               other.velocity = trigger_push_calculatevelocity(other.origin, RandomSelection_chosen_ent, self.height);
-       }
-       else
-       {
-               other.velocity = self.movedir;
-       }
-
-       other.flags &= ~FL_ONGROUND;
-
-       if (IS_PLAYER(other))
-       {
-               // reset tracking of oldvelocity for impact damage (sudden velocity changes)
-               other.oldvelocity = other.velocity;
-
-               if(self.pushltime < time)  // prevent "snorring" sound when a player hits the jumppad more than once
-               {
-                       // flash when activated
-                       pointparticles(particleeffectnum("jumppad_activate"), other.origin, other.velocity, 1);
-                       sound (other, CH_TRIGGER, self.noise, VOL_BASE, ATTEN_NORM);
-                       self.pushltime = time + 0.2;
-               }
-               if(IS_REAL_CLIENT(other) || IS_BOT_CLIENT(other))
-               {
-                       bool found = false;
-                       for(int i = 0; i < other.jumppadcount && i < NUM_JUMPPADSUSED; ++i)
-                               if(other.(jumppadsused[i]) == self)
-                                       found = true;
-                       if(!found)
-                       {
-                               other.(jumppadsused[other.jumppadcount % NUM_JUMPPADSUSED]) = self;
-                               other.jumppadcount = other.jumppadcount + 1;
-                       }
-
-                       if(IS_REAL_CLIENT(other))
-                       {
-                               if(self.message)
-                                       centerprint(other, self.message);
-                       }
-                       else
-                               other.lastteleporttime = time;
-
-                       if (other.deadflag == DEAD_NO)
-                               animdecide_setaction(other, ANIMACTION_JUMP, true);
-               }
-               else
-                       other.jumppadcount = true;
-
-               // reset tracking of who pushed you into a hazard (for kill credit)
-               other.pushltime = 0;
-               other.istypefrag = 0;
-       }
-
-       if(self.enemy.target)
-       {
-               entity oldself;
-               oldself = self;
-               activator = other;
-               self = self.enemy;
-               SUB_UseTargets();
-               self = oldself;
-       }
-
-       if (other.flags & FL_PROJECTILE)
-       {
-               other.angles = vectoangles (other.velocity);
-               switch(other.movetype)
-               {
-                       case MOVETYPE_FLY:
-                               other.movetype = MOVETYPE_TOSS;
-                               other.gravity = 1;
-                               break;
-                       case MOVETYPE_BOUNCEMISSILE:
-                               other.movetype = MOVETYPE_BOUNCE;
-                               other.gravity = 1;
-                               break;
-               }
-               UpdateCSQCProjectile(other);
-       }
-
-       if (self.spawnflags & PUSH_ONCE)
-       {
-               self.touch = func_null;
-               self.think = SUB_Remove;
-               self.nextthink = time;
-       }
-}
-
-void trigger_push_findtarget()
-{
-       entity e, t;
-       vector org;
-
-       // first calculate a typical start point for the jump
-       org = (self.absmin + self.absmax) * 0.5;
-       org.z = self.absmax.z - PL_MIN_z;
-
-       if (self.target)
-       {
-               float n;
-               n = 0;
-               for(t = world; (t = find(t, targetname, self.target)); )
-               {
-                       ++n;
-                       e = spawn();
-                       setorigin(e, org);
-                       setsize(e, PL_MIN, PL_MAX);
-                       e.velocity = trigger_push_calculatevelocity(org, t, self.height);
-                       tracetoss(e, e);
-                       if(e.movetype == MOVETYPE_NONE)
-                               waypoint_spawnforteleporter(self, trace_endpos, vlen(trace_endpos - org) / vlen(e.velocity));
-                       remove(e);
-               }
-
-               if(n == 0)
-               {
-                       // no dest!
-                       objerror ("Jumppad with nonexistant target");
-                       return;
-               }
-               else if(n == 1)
-               {
-                       // exactly one dest - bots love that
-                       self.enemy = find(world, targetname, self.target);
-               }
-               else
-               {
-                       // have to use random selection every single time
-                       self.enemy = world;
-               }
-       }
-       else
-       {
-               e = spawn();
-               setorigin(e, org);
-               setsize(e, PL_MIN, PL_MAX);
-               e.velocity = self.movedir;
-               tracetoss(e, e);
-               waypoint_spawnforteleporter(self, trace_endpos, vlen(trace_endpos - org) / vlen(e.velocity));
-               remove(e);
-       }
-}
-
-/*
- * ENTITY PARAMETERS:
- *
- *   target:  target of jump
- *   height:  the absolute value is the height of the highest point of the jump
- *            trajectory above the higher one of the player and the target.
- *            the sign indicates whether the highest point is INSIDE (positive)
- *            or OUTSIDE (negative) of the jump trajectory. General rule: use
- *            positive values for targets mounted on the floor, and use negative
- *            values to target a point on the ceiling.
- *   movedir: if target is not set, this * speed * 10 is the velocity to be reached.
- */
-void spawnfunc_trigger_push()
-{
-       SetMovedir ();
-
-       EXACTTRIGGER_INIT;
-
-       self.active = ACTIVE_ACTIVE;
-       self.use = trigger_push_use;
-       self.touch = trigger_push_touch;
-
-       // normal push setup
-       if (!self.speed)
-               self.speed = 1000;
-       self.movedir = self.movedir * self.speed * 10;
-
-       if (!self.noise)
-               self.noise = "misc/jumppad.wav";
-       precache_sound (self.noise);
-
-       // this must be called to spawn the teleport waypoints for bots
-       InitializeEntity(self, trigger_push_findtarget, INITPRIO_FINDTARGET);
-}
-
-void spawnfunc_target_push() {}
-void spawnfunc_info_notnull() {}
-void spawnfunc_target_position() {}
diff --git a/qcsrc/server/t_jumppads.qh b/qcsrc/server/t_jumppads.qh
deleted file mode 100644 (file)
index 9d66e98..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-#ifndef T_JUMPPADS_H
-#define T_JUMPPADS_H
-
-const float PUSH_ONCE          = 1;
-const float PUSH_SILENT                = 2;
-
-.float pushltime;
-.float istypefrag;
-.float height;
-
-void() SUB_UseTargets;
-
-float trigger_push_calculatevelocity_flighttime;
-
-void trigger_push_use();
-
-/*
-       trigger_push_calculatevelocity
-
-       Arguments:
-         org - origin of the object which is to be pushed
-         tgt - target entity (can be either a point or a model entity; if it is
-               the latter, its midpoint is used)
-         ht  - jump height, measured from the higher one of org and tgt's midpoint
-
-       Returns: velocity for the jump
-       the global trigger_push_calculatevelocity_flighttime is set to the total
-       jump time
- */
-
-vector trigger_push_calculatevelocity(vector org, entity tgt, float ht);
-
-void trigger_push_touch();
-
-.vector dest;
-void trigger_push_findtarget();
-
-/*
- * ENTITY PARAMETERS:
- *
- *   target:  target of jump
- *   height:  the absolute value is the height of the highest point of the jump
- *            trajectory above the higher one of the player and the target.
- *            the sign indicates whether the highest point is INSIDE (positive)
- *            or OUTSIDE (negative) of the jump trajectory. General rule: use
- *            positive values for targets mounted on the floor, and use negative
- *            values to target a point on the ceiling.
- *   movedir: if target is not set, this * speed * 10 is the velocity to be reached.
- */
-void spawnfunc_trigger_push();
-
-void spawnfunc_target_push();
-void spawnfunc_info_notnull();
-void spawnfunc_target_position();
-#endif
index 5b9433af4f2aac3cd7c64f73840cf64a75a6c9e1..b93b1d57770c1748b392f496250180963fcd8030 100644 (file)
@@ -1,21 +1,26 @@
-#if defined(CSQC)
-#elif defined(MENUQC)
-#elif defined(SVQC)
-       #include "../dpdefs/progsdefs.qh"
-    #include "../dpdefs/dpextensions.qh"
-    #include "../warpzonelib/mathlib.qh"
-    #include "../warpzonelib/common.qh"
-    #include "../warpzonelib/util_server.qh"
-    #include "../common/constants.qh"
-    #include "../common/util.qh"
-    #include "../common/weapons/weapons.qh"
-    #include "constants.qh"
-    #include "defs.qh"
-    #include "../common/notifications.qh"
-    #include "../common/deathtypes.qh"
-    #include "command/common.qh"
-    #include "../csqcmodellib/sv_model.qh"
-#endif
+#include "_all.qh"
+
+#include "bot/bot.qh"
+
+#include "command/common.qh"
+
+#include "g_damage.qh"
+#include "item_key.qh"
+
+#include "../common/constants.qh"
+#include "../common/deathtypes.qh"
+#include "../common/notifications.qh"
+#include "../common/util.qh"
+
+#include "../common/weapons/all.qh"
+
+#include "../csqcmodellib/sv_model.qh"
+
+#include "../warpzonelib/common.qh"
+#include "../warpzonelib/mathlib.qh"
+#include "../warpzonelib/util_server.qh"
+
+.float height;
 
 .float dmgtime2;
 void generic_plat_blocked()
@@ -785,7 +790,7 @@ void button_touch()
        button_fire ();
 }
 
-void button_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
+void button_damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
 {
        if(self.spawnflags & DOOR_NOSPLASH)
                if(!(DEATH_ISSPECIAL(deathtype)) && (deathtype & HITTYPE_SPLASH))
@@ -1145,7 +1150,7 @@ void door_trigger_touch()
 }
 
 
-void door_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
+void door_damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
 {
        entity oself;
        if(self.spawnflags & DOOR_NOSPLASH)
@@ -1765,7 +1770,7 @@ void fd_secret_use()
                sound(self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTEN_NORM);
 }
 
-void fd_secret_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
+void fd_secret_damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
 {
        fd_secret_use();
 }
index 9b25c8860905440b3b724ec09c261a6fcfbbc14a..517b8808225f50773e2e9b303af7ff717ac33f3c 100644 (file)
@@ -1,4 +1,15 @@
-#include "../common/weapons/weapons.qc"
+#include "_all.qh"
+
+#include "../common/weapons/all.qh"
+
+void spawnfunc_weapon_electro();
+void spawnfunc_weapon_hagar();
+void spawnfunc_weapon_machinegun();
+void spawnfunc_item_bullets();
+void spawnfunc_item_armor_large();
+void spawnfunc_item_armor_large();
+void spawnfunc_item_health_mega();
+void spawnfunc_item_health_medium();
 
 //***********************
 //QUAKE 1 ENTITIES - So people can play quake1 maps with the xonotic weapons
index ed90bf054c0c1aeeed5668afd43c3b3e0eb09d26..6908b6dbf18500f2927971f6441f2cbd04602831 100644 (file)
@@ -1,4 +1,29 @@
-#include "../common/weapons/weapons.qc"
+#include "_all.qh"
+
+#include "../common/weapons/all.qh"
+#include "../common/buffs.qh"
+
+void spawnfunc_weapon_crylink();
+void spawnfunc_weapon_electro();
+void spawnfunc_weapon_hagar();
+void spawnfunc_weapon_machinegun();
+void spawnfunc_weapon_vortex();
+
+void spawnfunc_target_items();
+
+void spawnfunc_item_bullets();
+void spawnfunc_item_cells();
+void spawnfunc_item_rockets();
+void spawnfunc_item_shells();
+
+void spawnfunc_item_jetpack();
+
+void spawnfunc_item_armor_big();
+void spawnfunc_item_armor_large();
+void spawnfunc_item_armor_small();
+
+void spawnfunc_item_health_medium();
+void spawnfunc_item_health_mega();
 
 //***********************
 //QUAKE 3 ENTITIES - So people can play quake3 maps with the xonotic weapons
diff --git a/qcsrc/server/t_swamp.qc b/qcsrc/server/t_swamp.qc
deleted file mode 100644 (file)
index b63e7ff..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
-#if defined(CSQC)
-#elif defined(MENUQC)
-#elif defined(SVQC)
-       #include "../dpdefs/progsdefs.qh"
-    #include "../warpzonelib/util_server.qh"
-    #include "../common/weapons/weapons.qh"
-    #include "defs.qh"
-    #include "../common/deathtypes.qh"
-#endif
-
-/*
-*              t_swamp.c
-*              Adds spawnfunc_trigger_swamp and suppoart routines for xonotic 1.2.1+
-*              Author tZork (Jakob MG)
-*              jakob@games43.se
-*              2005 11 29
-*/
-
-.float swamp_interval; //Hurt players in swamp with this interval
-.float swamp_slowdown; //Players in swamp get slowd down by this mutch 0-1 is slowdown 1-~ is speedup (!?)
-.entity swampslug;
-
-void spawnfunc_trigger_swamp(void);
-void swamp_touch(void);
-void swampslug_think();
-
-
-/*
-* Uses a entity calld swampslug to handle players in the swamp
-* It works like this: When the plyer enters teh swamp the spawnfunc_trigger_swamp
-* attaches a new "swampslug" to the player. As long as the plyer is inside
-* the swamp the swamp gives the slug new health. But the slug slowly kills itself
-* so when the player goes outside the swamp, it dies and releases the player from the
-* swamps curses (dmg/slowdown)
-*
-* I do it this way becuz there is no "untouch" event.
-*
-* --NOTE--
-* THE ACCTUAL slowdown is done in cl_physics.c on line 57-60
-* --NOTE--
-*/
-void swampslug_think(void)
-{
-       //Slowly kill the slug
-       self.health = self.health - 1;
-
-       //Slug dead? then remove curses.
-       if(self.health <= 0) {
-               self.owner.in_swamp = 0;
-               remove(self);
-               //centerprint(self.owner,"Killing slug...\n");
-               return;
-       }
-
-       // Slug still alive, so we are still in the swamp
-       // Or we have exited it very recently.
-       // Do the damage and renew the timer.
-       Damage (self.owner, self, self, self.dmg, DEATH_SWAMP, other.origin, '0 0 0');
-
-       self.nextthink = time + self.swamp_interval;
-}
-
-void swamp_touch(void)
-{
-       // If whatever thats touching the swamp is not a player
-       // or if its a dead player, just dont care abt it.
-       if(!IS_PLAYER(other) || other.deadflag != DEAD_NO)
-               return;
-
-       EXACTTRIGGER_TOUCH;
-
-       // Chech if player alredy got a swampslug.
-       if(other.in_swamp != 1) {
-               // If not attach one.
-               //centerprint(other,"Entering swamp!\n");
-               other.swampslug = spawn();
-               other.swampslug.health = 2;
-               other.swampslug.think = swampslug_think;
-               other.swampslug.nextthink = time;
-               other.swampslug.owner = other;
-               other.swampslug.dmg = self.dmg;
-               other.swampslug.swamp_interval = self.swamp_interval;
-               other.swamp_slowdown = self.swamp_slowdown;
-               other.in_swamp = 1;
-               return;
-       }
-
-       //other.in_swamp = 1;
-
-       //Revitalize players swampslug
-       other.swampslug.health = 2;
-}
-
-/*QUAKED spawnfunc_trigger_swamp (.5 .5 .5) ?
-Players gettin into the swamp will
-get slowd down and damaged
-*/
-void spawnfunc_trigger_swamp(void)
-{
-       // Init stuff
-       EXACTTRIGGER_INIT;
-       self.touch = swamp_touch;
-
-       // Setup default keys, if missing
-       if(self.dmg <= 0)
-               self.dmg = 5;
-       if(self.swamp_interval <= 0)
-               self.swamp_interval = 1;
-       if(self.swamp_slowdown <= 0)
-               self.swamp_slowdown = 0.5;
-}
diff --git a/qcsrc/server/t_teleporters.qc b/qcsrc/server/t_teleporters.qc
deleted file mode 100644 (file)
index 46df0eb..0000000
+++ /dev/null
@@ -1,348 +0,0 @@
-#include "t_teleporters.qh"
-
-#if defined(CSQC)
-#elif defined(MENUQC)
-#elif defined(SVQC)
-    #include "../warpzonelib/common.qh"
-    #include "../warpzonelib/util_server.qh"
-    #include "../warpzonelib/server.qh"
-    #include "../common/constants.qh"
-    #include "../common/util.qh"
-    #include "weapons/csqcprojectile.qh"
-    #include "autocvars.qh"
-    #include "constants.qh"
-    #include "defs.qh"
-    #include "../common/deathtypes.qh"
-    #include "tturrets/include/turrets_early.qh"
-    #include "vehicles/vehicles_def.qh"
-    #include "../common/mapinfo.qh"
-    #include "anticheat.qh"
-#endif
-
-void trigger_teleport_use()
-{
-       if(teamplay)
-               self.team = activator.team;
-}
-
-float check_tdeath(entity player, vector org, vector telefragmin, vector telefragmax)
-{
-       if (IS_PLAYER(player) && player.health >= 1)
-       {
-               TDEATHLOOP(org)
-               {
-                       if (!(teamplay && autocvar_g_telefrags_teamplay && head.team == player.team))
-                               if(IS_PLAYER(head))
-                                       if(head.health >= 1)
-                                               return 1;
-               }
-       }
-       return 0;
-}
-
-void tdeath(entity player, entity teleporter, entity telefragger, vector telefragmin, vector telefragmax)
-{
-       TDEATHLOOP(player.origin)
-       {
-               if (IS_PLAYER(player) && player.health >= 1)
-               {
-                       if (!(teamplay && autocvar_g_telefrags_teamplay && head.team == player.team))
-                       {
-                               if(IS_PLAYER(head))
-                                       if(head.health >= 1)
-                                               ++tdeath_hit;
-                               Damage (head, teleporter, telefragger, 10000, DEATH_TELEFRAG, head.origin, '0 0 0');
-                       }
-               }
-               else // dead bodies and monsters gib themselves instead of telefragging
-                       Damage (telefragger, teleporter, telefragger, 10000, DEATH_TELEFRAG, telefragger.origin, '0 0 0');
-       }
-}
-
-void spawn_tdeath(vector v0, entity e, vector v)
-{
-       tdeath(e, e, e, '0 0 0', '0 0 0');
-}
-
-void TeleportPlayer(entity teleporter, entity player, vector to, vector to_angles, vector to_velocity, vector telefragmin, vector telefragmax, float tflags)
-{
-       entity telefragger;
-       vector from;
-
-       if(teleporter.owner)
-               telefragger = teleporter.owner;
-       else
-               telefragger = player;
-
-       makevectors (to_angles);
-
-       if(player.teleportable == TELEPORT_NORMAL) // don't play sounds or show particles for anything that isn't a player, maybe change later to block only observers
-       {
-               if(self.pushltime < time) // only show one teleport effect per teleporter per 0.2 seconds, for better fps
-               {
-                       if(tflags & TELEPORT_FLAG_SOUND)
-                               sound (player, CH_TRIGGER, "misc/teleport.wav", VOL_BASE, ATTEN_NORM);
-                       if(tflags & TELEPORT_FLAG_PARTICLES)
-                       {
-                               pointparticles(particleeffectnum("teleport"), player.origin, '0 0 0', 1);
-                               pointparticles(particleeffectnum("teleport"), to + v_forward * 32, '0 0 0', 1);
-                       }
-                       self.pushltime = time + 0.2;
-               }
-       }
-
-       // Relocate the player
-       // assuming to allows PL_MIN to PL_MAX box and some more
-       from = player.origin;
-       setorigin (player, to);
-       player.oldorigin = to; // don't undo the teleport by unsticking
-       player.angles = to_angles;
-       player.fixangle = true;
-       player.velocity = to_velocity;
-       BITXOR_ASSIGN(player.effects, EF_TELEPORT_BIT);
-
-       makevectors(player.angles);
-       Reset_ArcBeam(player, v_forward);
-       UpdateCSQCProjectileAfterTeleport(player);
-
-       if(IS_PLAYER(player))
-       {
-               if(tflags & TELEPORT_FLAG_TDEATH)
-                       if(player.takedamage && player.deadflag == DEAD_NO && !g_race && !g_cts && (autocvar_g_telefrags || (tflags & TELEPORT_FLAG_FORCE_TDEATH)))
-                               tdeath(player, teleporter, telefragger, telefragmin, telefragmax);
-
-               // player no longer is on ground
-               player.flags &= ~FL_ONGROUND;
-
-               // reset tracking of oldvelocity for impact damage (sudden velocity changes)
-               player.oldvelocity = player.velocity;
-
-               // reset tracking of who pushed you into a hazard (for kill credit)
-               if(teleporter.owner)
-               {
-                       player.pusher = teleporter.owner;
-                       player.pushltime = time + autocvar_g_maxpushtime;
-                       player.istypefrag = player.BUTTON_CHAT;
-               }
-               else
-               {
-                       player.pushltime = 0;
-                       player.istypefrag = 0;
-               }
-
-               player.lastteleporttime = time;
-       }
-}
-
-entity Simple_TeleportPlayer(entity teleporter, entity player)
-{
-       vector locout;
-       entity e;
-       float p;
-
-       // Find the output teleporter
-       if(teleporter.enemy)
-       {
-               e = teleporter.enemy;
-       }
-       else
-       {
-               RandomSelection_Init();
-               for(e = world; (e = find(e, targetname, teleporter.target)); )
-               {
-                       p = 1;
-                       if(autocvar_g_telefrags_avoid)
-                       {
-                               locout = e.origin + '0 0 1' * (1 - player.mins.z - 24);
-                               if(check_tdeath(player, locout, '0 0 0', '0 0 0'))
-                                       p = 0;
-                       }
-                       RandomSelection_Add(e, 0, string_null, (e.cnt ? e.cnt : 1), p);
-               }
-               e = RandomSelection_chosen_ent;
-       }
-
-       if(!e) { sprint(player, "Teleport destination vanished. Sorry... please complain to the mapper.\n"); }
-
-       makevectors(e.mangle);
-
-       if(e.speed)
-               if(vlen(player.velocity) > e.speed)
-                       player.velocity = normalize(player.velocity) * max(0, e.speed);
-
-       if(autocvar_g_teleport_maxspeed)
-               if(vlen(player.velocity) > autocvar_g_teleport_maxspeed)
-                       player.velocity = normalize(player.velocity) * max(0, autocvar_g_teleport_maxspeed);
-
-       locout = e.origin + '0 0 1' * (1 - player.mins.z - 24);
-       TeleportPlayer(teleporter, player, locout, e.mangle, v_forward * vlen(player.velocity), '0 0 0', '0 0 0', TELEPORT_FLAGS_TELEPORTER);
-
-       return e;
-}
-
-void Teleport_Touch (void)
-{
-       entity oldself;
-       string s;
-
-       if (self.active != ACTIVE_ACTIVE)
-               return;
-
-       if (!other.teleportable)
-               return;
-
-       if(other.vehicle)
-       if(!other.vehicle.teleportable)
-               return;
-
-       if(other.turrcaps_flags & TFL_TURRCAPS_ISTURRET)
-               return;
-
-       if(other.deadflag != DEAD_NO)
-               return;
-
-       if(self.team)
-               if(((self.spawnflags & 4) == 0) == (self.team != other.team))
-                       return;
-
-       EXACTTRIGGER_TOUCH;
-
-       if(IS_PLAYER(other))
-               RemoveGrapplingHook(other);
-
-       entity e;
-       e = Simple_TeleportPlayer(self, other);
-
-       activator = other;
-       s = self.target; self.target = string_null;
-       SUB_UseTargets();
-       if (!self.target) self.target = s;
-
-       oldself = self;
-       self = e;
-       SUB_UseTargets();
-       self = oldself;
-}
-
-void spawnfunc_info_teleport_destination (void)
-{
-       self.classname = "info_teleport_destination";
-
-       self.mangle = self.angles;
-       self.angles = '0 0 0';
-
-       //setorigin (self, self.origin + '0 0 27');     // To fix a mappers' habit as old as Quake
-       setorigin (self, self.origin);
-
-       IFTARGETED
-       {
-       }
-       else
-               objerror ("^3Teleport destination without a targetname");
-}
-
-void spawnfunc_misc_teleporter_dest (void)
-{
-       spawnfunc_info_teleport_destination();
-}
-
-void spawnfunc_target_teleporter (void)
-{
-       spawnfunc_info_teleport_destination();
-}
-
-void teleport_findtarget (void)
-{
-       entity e;
-       float n;
-
-       n = 0;
-       for(e = world; (e = find(e, targetname, self.target)); )
-       {
-               ++n;
-               if(e.movetype == MOVETYPE_NONE)
-                       waypoint_spawnforteleporter(self, e.origin, 0);
-               if(e.classname != "info_teleport_destination")
-                       print("^3MAPPER ERROR: teleporter does target an invalid teleport destination entity. Angles will not work.\n");
-       }
-
-       if(n == 0)
-       {
-               // no dest!
-               objerror ("Teleporter with nonexistant target");
-               return;
-       }
-       else if(n == 1)
-       {
-               // exactly one dest - bots love that
-               self.enemy = find(e, targetname, self.target);
-       }
-       else
-       {
-               // have to use random selection every single time
-               self.enemy = world;
-       }
-
-       // now enable touch
-       self.touch = Teleport_Touch;
-}
-
-entity Teleport_Find(vector mi, vector ma)
-{
-       entity e;
-       for(e = world; (e = find(e, classname, "trigger_teleport")); )
-               if(WarpZoneLib_BoxTouchesBrush(mi, ma, e, world))
-                       return e;
-       return world;
-}
-
-void spawnfunc_trigger_teleport (void)
-{
-       self.angles = '0 0 0';
-
-       EXACTTRIGGER_INIT;
-
-       self.active = ACTIVE_ACTIVE;
-
-       self.use = trigger_teleport_use;
-
-       // this must be called to spawn the teleport waypoints for bots
-       InitializeEntity(self, teleport_findtarget, INITPRIO_FINDTARGET);
-
-       if (self.target == "")
-       {
-               objerror ("Teleporter with no target");
-               return;
-       }
-
-       self.teleport_next = teleport_first;
-       teleport_first = self;
-}
-
-void WarpZone_PostTeleportPlayer_Callback(entity pl)
-{
-       makevectors(pl.angles);
-       Reset_ArcBeam(pl, v_forward);
-       UpdateCSQCProjectileAfterTeleport(pl);
-       {
-               entity oldself = self;
-               self = pl;
-               anticheat_fixangle();
-               self = oldself;
-       }
-       // "disown" projectiles after teleport
-       if(pl.owner)
-       if(pl.owner == pl.realowner)
-       {
-               if(!(pl.flags & FL_PROJECTILE))
-                       print("A non-projectile got through a warpzone and its owner cleared. It's a ", pl.classname, ".\n");
-               pl.owner = world;
-       }
-       if(IS_PLAYER(pl))
-       {
-               // reset tracking of oldvelocity for impact damage (sudden velocity changes)
-               pl.oldvelocity = pl.velocity;
-               // reset teleport time tracking too (or multijump can cause insane speeds)
-               pl.lastteleporttime = time;
-       }
-}
diff --git a/qcsrc/server/t_teleporters.qh b/qcsrc/server/t_teleporters.qh
deleted file mode 100644 (file)
index 03e3c3f..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-#ifndef T_TELEPORTERS_H
-#define T_TELEPORTERS_H
-
-void trigger_teleport_use();
-
-#define TDEATHLOOP(o) \
-       entity head; \
-       vector deathmin; \
-       vector deathmax; \
-       float deathradius; \
-       deathmin = (o) + player.mins; \
-       deathmax = (o) + player.maxs; \
-       if(telefragmin != telefragmax) \
-       { \
-               if(deathmin.x > telefragmin.x) deathmin.x = telefragmin.x; \
-               if(deathmin.y > telefragmin.y) deathmin.y = telefragmin.y; \
-               if(deathmin.z > telefragmin.z) deathmin.z = telefragmin.z; \
-               if(deathmax.x < telefragmax.x) deathmax.x = telefragmax.x; \
-               if(deathmax.y < telefragmax.y) deathmax.y = telefragmax.y; \
-               if(deathmax.z < telefragmax.z) deathmax.z = telefragmax.z; \
-       } \
-       deathradius = max(vlen(deathmin), vlen(deathmax)); \
-       for(head = findradius(o, deathradius); head; head = head.chain) \
-               if(head != player) \
-                       if(head.takedamage) \
-                               if(boxesoverlap(deathmin, deathmax, head.absmin, head.absmax))
-
-
-float check_tdeath(entity player, vector org, vector telefragmin, vector telefragmax);
-float tdeath_hit;
-void tdeath(entity player, entity teleporter, entity telefragger, vector telefragmin, vector telefragmax);
-
-void spawn_tdeath(vector v0, entity e, vector v);
-
-.entity pusher;
-const float TELEPORT_FLAG_SOUND = 1;
-const float TELEPORT_FLAG_PARTICLES = 2;
-const float TELEPORT_FLAG_TDEATH = 4;
-const float TELEPORT_FLAG_FORCE_TDEATH = 8;
-
-#define TELEPORT_FLAGS_WARPZONE   0
-#define TELEPORT_FLAGS_PORTAL     (TELEPORT_FLAG_SOUND | TELEPORT_FLAG_PARTICLES | TELEPORT_FLAG_TDEATH | TELEPORT_FLAG_FORCE_TDEATH)
-#define TELEPORT_FLAGS_TELEPORTER (TELEPORT_FLAG_SOUND | TELEPORT_FLAG_PARTICLES | TELEPORT_FLAG_TDEATH)
-
-// types for .teleportable entity setting
-const float TELEPORT_NORMAL = 1; // play sounds/effects etc
-const float TELEPORT_SIMPLE = 2; // only do teleport, nothing special
-
-void Reset_ArcBeam(entity player, vector forward);
-void TeleportPlayer(entity teleporter, entity player, vector to, vector to_angles, vector to_velocity, vector telefragmin, vector telefragmax, float tflags);
-
-entity Simple_TeleportPlayer(entity teleporter, entity player);
-
-void Teleport_Touch (void);
-
-void spawnfunc_info_teleport_destination (void);
-
-void spawnfunc_misc_teleporter_dest (void);
-
-void spawnfunc_target_teleporter (void);
-
-void teleport_findtarget (void);
-
-entity Teleport_Find(vector mi, vector ma);
-
-entity teleport_first;
-.entity teleport_next;
-void spawnfunc_trigger_teleport (void);
-
-void WarpZone_PostTeleportPlayer_Callback(entity pl);
-#endif
index 94bc92f69ceaed1d8af9775bf9de5a4d057269fc..681a4ca6d194bb1586447743c4ef8f70b8e48d01 100644 (file)
@@ -1,13 +1,6 @@
-#if defined(CSQC)
-#elif defined(MENUQC)
-#elif defined(SVQC)
-       #include "../dpdefs/progsdefs.qh"
-    #include "../dpdefs/dpextensions.qh"
-    #include "../common/constants.qh"
-    #include "constants.qh"
-    #include "defs.qh"
-#endif
+#include "_all.qh"
 
+.float volume;
 .float lifetime;
 // values:
 //   volume
@@ -75,7 +68,7 @@ void TargetMusic_RestoreGame()
 // spawnflags:
 //   1 = START_OFF
 // when triggered, it is disabled/enabled for everyone
-float trigger_music_SendEntity(entity to, float sf)
+float trigger_music_SendEntity(entity to, int sf)
 {
        WriteByte(MSG_ENTITY, ENT_CLIENT_TRIGGER_MUSIC);
        sf &= ~0x80;
diff --git a/qcsrc/server/target_spawn.qc b/qcsrc/server/target_spawn.qc
deleted file mode 100644 (file)
index b4b9b18..0000000
+++ /dev/null
@@ -1,367 +0,0 @@
-#if defined(CSQC)
-#elif defined(MENUQC)
-#elif defined(SVQC)
-       #include "../dpdefs/progsdefs.qh"
-    #include "../dpdefs/dpextensions.qh"
-    #include "../common/util.qh"
-    #include "defs.qh"
-#endif
-
-// spawner entity
-// "classname" "target_spawn"
-// "message" "fieldname value fieldname value ..."
-// "spawnflags"
-//   1 = call the spawn function
-//   2 = trigger on map load
-
-float target_spawn_initialized;
-.void() target_spawn_spawnfunc;
-float target_spawn_spawnfunc_field;
-.entity target_spawn_activator;
-.float target_spawn_id;
-float target_spawn_count;
-
-void target_spawn_helper_setmodel()
-{
-       setmodel(self, self.model);
-}
-
-void target_spawn_helper_setsize()
-{
-       setsize(self, self.mins, self.maxs);
-}
-
-void target_spawn_edit_entity(entity e, string msg, entity kt, entity t2, entity t3, entity t4, entity act)
-{
-       float i, n, valuefieldpos;
-       string key, value, valuefield, valueoffset, valueoffsetrandom;
-       entity valueent;
-       vector data, data2;
-       entity oldself;
-       entity oldactivator;
-
-       n = tokenize_console(msg);
-
-       for(i = 0; i < n-1; i += 2)
-       {
-               key = argv(i);
-               value = argv(i+1);
-               if(key == "$")
-               {
-                       data.x = -1;
-                       data.y = FIELD_STRING;
-               }
-               else
-               {
-                       data = stov(db_get(TemporaryDB, strcat("/target_spawn/field/", key)));
-                       if(data.y == 0) // undefined field, i.e., invalid type
-                       {
-                               print("target_spawn: invalid/unknown entity key ", key, " specified, ignored!\n");
-                               continue;
-                       }
-               }
-               if(substring(value, 0, 1) == "$")
-               {
-                       value = substring(value, 1, strlen(value) - 1);
-                       if(substring(value, 0, 1) == "$")
-                       {
-                               // deferred replacement
-                               // do nothing
-                               // useful for creating target_spawns with this!
-                       }
-                       else
-                       {
-                               // replace me!
-                               valuefieldpos = strstrofs(value, "+", 0);
-                               valueoffset = "";
-                               if(valuefieldpos != -1)
-                               {
-                                       valueoffset = substring(value, valuefieldpos + 1, strlen(value) - valuefieldpos - 1);
-                                       value = substring(value, 0, valuefieldpos);
-                               }
-
-                               valuefieldpos = strstrofs(valueoffset, "+", 0);
-                               valueoffsetrandom = "";
-                               if(valuefieldpos != -1)
-                               {
-                                       valueoffsetrandom = substring(valueoffset, valuefieldpos + 1, strlen(valueoffset) - valuefieldpos - 1);
-                                       valueoffset = substring(valueoffset, 0, valuefieldpos);
-                               }
-
-                               valuefieldpos = strstrofs(value, ".", 0);
-                               valuefield = "";
-                               if(valuefieldpos != -1)
-                               {
-                                       valuefield = substring(value, valuefieldpos + 1, strlen(value) - valuefieldpos - 1);
-                                       value = substring(value, 0, valuefieldpos);
-                               }
-
-                               if(value == "self")
-                               {
-                                       valueent = self;
-                                       value = "";
-                               }
-                               else if(value == "activator")
-                               {
-                                       valueent = act;
-                                       value = "";
-                               }
-                               else if(value == "other")
-                               {
-                                       valueent = other;
-                                       value = "";
-                               }
-                               else if(value == "pusher")
-                               {
-                                       if(time < act.pushltime)
-                                               valueent = act.pusher;
-                                       else
-                                               valueent = world;
-                                       value = "";
-                               }
-                               else if(value == "target")
-                               {
-                                       valueent = e;
-                                       value = "";
-                               }
-                               else if(value == "killtarget")
-                               {
-                                       valueent = kt;
-                                       value = "";
-                               }
-                               else if(value == "target2")
-                               {
-                                       valueent = t2;
-                                       value = "";
-                               }
-                               else if(value == "target3")
-                               {
-                                       valueent = t3;
-                                       value = "";
-                               }
-                               else if(value == "target4")
-                               {
-                                       valueent = t4;
-                                       value = "";
-                               }
-                               else if(value == "time")
-                               {
-                                       valueent = world;
-                                       value = ftos(time);
-                               }
-                               else
-                               {
-                                       print("target_spawn: invalid/unknown variable replacement ", value, " specified, ignored!\n");
-                                       continue;
-                               }
-
-                               if(valuefield == "")
-                               {
-                                       if(value == "")
-                                               value = ftos(num_for_edict(valueent));
-                               }
-                               else
-                               {
-                                       if(value != "")
-                                       {
-                                               print("target_spawn: try to get a field of a non-entity, ignored!\n");
-                                               continue;
-                                       }
-                                       data2 = stov(db_get(TemporaryDB, strcat("/target_spawn/field/", valuefield)));
-                                       if(data2_y == 0) // undefined field, i.e., invalid type
-                                       {
-                                               print("target_spawn: invalid/unknown entity key replacement ", valuefield, " specified, ignored!\n");
-                                               continue;
-                                       }
-                                       value = getentityfieldstring(data2_x, valueent);
-                               }
-
-                               if(valueoffset != "")
-                               {
-                                       switch(data.y)
-                                       {
-                                               case FIELD_STRING:
-                                                       value = strcat(value, valueoffset);
-                                                       break;
-                                               case FIELD_FLOAT:
-                                                       value = ftos(stof(value) + stof(valueoffset));
-                                                       break;
-                                               case FIELD_VECTOR:
-                                                       value = vtos(stov(value) + stov(valueoffset));
-                                                       break;
-                                               default:
-                                                       print("target_spawn: only string, float and vector fields can do calculations, calculation ignored!\n");
-                                                       break;
-                                       }
-                               }
-
-                               if(valueoffsetrandom != "")
-                               {
-                                       switch(data.y)
-                                       {
-                                               case FIELD_FLOAT:
-                                                       value = ftos(stof(value) + random() * stof(valueoffsetrandom));
-                                                       break;
-                                               case FIELD_VECTOR:
-                                                       data2 = stov(valueoffsetrandom);
-                                                       value = vtos(stov(value) + random() * data2_x * '1 0 0' + random() * data2_y * '0 1 0' + random() * data2_z * '0 0 1');
-                                                       break;
-                                               default:
-                                                       print("target_spawn: only float and vector fields can do random calculations, calculation ignored!\n");
-                                                       break;
-                                       }
-                               }
-                       }
-               }
-               if(key == "$")
-               {
-                       if(substring(value, 0, 1) == "_")
-                               value = strcat("target_spawn_helper", value);
-                       putentityfieldstring(target_spawn_spawnfunc_field, e, value);
-
-                       oldself = self;
-                       oldactivator = activator;
-
-                       self = e;
-                       activator = act;
-
-                       self.target_spawn_spawnfunc();
-
-                       self = oldself;
-                       activator = oldactivator;
-
-                       // We called an external function, so we have to re-tokenize msg.
-                       n = tokenize_console(msg);
-               }
-               else
-               {
-                       if(data.y == FIELD_VECTOR)
-                               value = strreplace("'", "", value); // why?!?
-                       putentityfieldstring(data.x, e, value);
-               }
-       }
-}
-
-void target_spawn_useon(entity e)
-{
-       self.target_spawn_activator = activator;
-       target_spawn_edit_entity(
-               e,
-               self.message,
-               find(world, targetname, self.killtarget),
-               find(world, targetname, self.target2),
-               find(world, targetname, self.target3),
-               find(world, targetname, self.target4),
-               activator
-       );
-}
-
-float target_spawn_cancreate()
-{
-       float c;
-       entity e;
-
-       c = self.count;
-       if(c == 0) // no limit?
-               return 1;
-
-       ++c; // increase count to not include MYSELF
-       for(e = world; (e = findfloat(e, target_spawn_id, self.target_spawn_id)); --c)
-               ;
-
-       // if c now is 0, we have AT LEAST the given count (maybe more), so don't spawn any more
-       if(c == 0)
-               return 0;
-       return 1;
-}
-
-void target_spawn_use()
-{
-       entity e;
-
-       if(self.target == "")
-       {
-               // spawn new entity
-               if(!target_spawn_cancreate())
-                       return;
-               e = spawn();
-               target_spawn_useon(e);
-               e.target_spawn_id = self.target_spawn_id;
-       }
-       else if(self.target == "*activator")
-       {
-               // edit entity
-               if(activator)
-                       target_spawn_useon(activator);
-       }
-       else
-       {
-               // edit entity
-               for(e = world; (e = find(e, targetname, self.target)); )
-                       target_spawn_useon(e);
-       }
-}
-
-void target_spawn_spawnfirst()
-{
-       activator = self.target_spawn_activator;
-       if(self.spawnflags & 2)
-               target_spawn_use();
-}
-
-void initialize_field_db()
-{
-       if(!target_spawn_initialized)
-       {
-               float n, i;
-               string fn;
-               vector prev, new;
-               float ft;
-
-               n = numentityfields();
-               for(i = 0; i < n; ++i)
-               {
-                       fn = entityfieldname(i);
-                       ft = entityfieldtype(i);
-                       new = i * '1 0 0' + ft * '0 1 0' + '0 0 1';
-                       prev = stov(db_get(TemporaryDB, strcat("/target_spawn/field/", fn)));
-                       if(prev.y == 0)
-                       {
-                               db_put(TemporaryDB, strcat("/target_spawn/field/", fn), vtos(new));
-                               if(fn == "target_spawn_spawnfunc")
-                                       target_spawn_spawnfunc_field = i;
-                       }
-               }
-
-               target_spawn_initialized = 1;
-       }
-}
-
-void spawnfunc_target_spawn()
-{
-       initialize_field_db();
-       self.use = target_spawn_use;
-       self.message = strzone(strreplace("'", "\"", self.message));
-       self.target_spawn_id = ++target_spawn_count;
-       InitializeEntity(self, target_spawn_spawnfirst, INITPRIO_LAST);
-}
-
-
-void trigger_relay_if_use()
-{
-       float n;
-       n = self.count;
-
-       // TODO make this generic AND faster than nextent()ing through all, if somehow possible
-       n = (cvar_string(self.netname) == cvar_string(self.message));
-       if(self.spawnflags & 1)
-               n = !n;
-
-       if(n)
-               SUB_UseTargets();
-}
-
-void spawnfunc_trigger_relay_if()
-{
-       self.use = trigger_relay_if_use;
-}
index ba1b4e6eedacb91412044bd0529c472ac3ffb977..7bd44fec82401c29a41533a9b50f85b224406db1 100644 (file)
@@ -1,4 +1,19 @@
 #include "teamplay.qh"
+#include "_all.qh"
+
+#include "cl_client.qh"
+#include "race.qh"
+#include "scores.qh"
+#include "scores_rules.qh"
+
+#include "bot/bot.qh"
+
+#include "command/vote.qh"
+
+#include "mutators/mutators_include.qh"
+
+#include "../common/deathtypes.qh"
+#include "../common/teams.qh"
 
 void TeamchangeFrags(entity e)
 {
index 4c5d95f9e3be472a062abdc3882ce73b1e12a6b5..1cb23e67be79c2a5238fad974e9f294d5b30f337 100644 (file)
@@ -417,7 +417,7 @@ vector turret_stdproc_aim_generic();
 void turret_stdproc_track();
 
 /// Generic damage handeling. blows up the turret when health <= 0
-void turret_stdproc_damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector vforce);
+void turret_stdproc_damage (entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector vforce);
 /// Spawns a explotion, does some damage & trows bits arround.
 void turret_stdproc_die();
 /// reassembles the turret.
index 45b2e9b3bba68550eb99a4cd59fac4f2c20b87e4..43567fcbfcb48c0442a8090bbd9d4178560c9830 100644 (file)
@@ -81,7 +81,7 @@ void turret_stdproc_respawn()
 /*
 * Standard damage proc.
 */
-void turret_stdproc_damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector vforce)
+void turret_stdproc_damage (entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector vforce)
 {
     // Enougth allready!
     if(self.deadflag == DEAD_DEAD)
index f2b0c56ce846d596cdd486772c89faa98d3b2160..694ff5d45c7d7ed26166c95f94238cf3c24c0f55 100644 (file)
@@ -1,3 +1,8 @@
+#include "../../_all.qh"
+
+#include "../../g_damage.qh"
+#include "../../bot/bot.qh"
+
 #define cvar_base "g_turrets_unit_"
 .float clientframe;
 void turrets_setframe(float _frame, float client_only)
@@ -15,7 +20,7 @@ void turrets_setframe(float _frame, float client_only)
 
 }
 
-float turret_send(entity to, float sf)
+float turret_send(entity to, int sf)
 {
 
        WriteByte(MSG_ENTITY, ENT_CLIENT_TURRET);
@@ -163,7 +168,7 @@ void turret_projectile_touch()
     turret_projectile_explode();
 }
 
-void turret_projectile_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector vforce)
+void turret_projectile_damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector vforce)
 {
     self.velocity  += vforce;
     self.health    -= damage;
@@ -931,7 +936,7 @@ void turret_think()
 
 void turret_fire()
 {
-    if (autocvar_g_turrets_nofire != 0)
+    if (autocvar_g_turrets_nofire)
         return;
 
     self.turret_firefunc();
@@ -991,7 +996,7 @@ void turrets_manager_think()
     self.nextthink = time + 1;
 
     entity e;
-    if (autocvar_g_turrets_reloadcvars == 1)
+    if (autocvar_g_turrets_reloadcvars)
     {
         e = nextent(world);
         while (e)
@@ -1041,19 +1046,6 @@ float turret_stdproc_init (string cvar_base_name, string base, string head, floa
     if (!(self.spawnflags & TSF_SUSPENDED))
         builtin_droptofloor(); // why can't we use regular droptofloor here?
 
-    // Terrainbase spawnflag. This puts a enlongated model
-    // under the turret, so it looks ok on uneaven surfaces.
-    /*  TODO: Handle this with CSQC
-    if (self.spawnflags & TSF_TERRAINBASE)
-    {
-        entity tb;
-        tb = spawn();
-        setmodel(tb,"models/turrets/terrainbase.md3");
-        setorigin(tb,self.origin);
-        tb.solid = SOLID_BBOX;
-    }
-    */
-
     self.cvar_basename = cvar_base_name;
     load_unit_settings(self, self.cvar_basename, 0);
 
index 787510694e9101eca0c0158564170fdf846b5d9f..1885f67c173a756d88ecc19afc289408feb51fc9 100644 (file)
@@ -133,7 +133,7 @@ float turret_tag_fire_update_s()
 * Railgun-like beam, but has thickness and suppots slowing of target
 */
 void FireImoBeam (vector start, vector end, vector smin, vector smax,
-                  float bforce, float f_dmg, float f_velfactor, float deathtype)
+                  float bforce, float f_dmg, float f_velfactor, int deathtype)
 
 {
     vector hitloc, force, endpoint, dir;
@@ -229,7 +229,6 @@ void turrets_precash()
 
 
 #ifdef TURRET_DEBUG
-void SUB_Remove();
 void marker_think()
 {
     if(self.cnt)
index 7eb1622baf102b80fd1aba8407559613c6b10bf5..4133ae97df5043fd277ede7d07fe17c5472a9e1f 100644 (file)
@@ -1,3 +1,5 @@
+#include "../../bot/navigation.qh"
+
 const float ewheel_amin_stop = 0;
 const float ewheel_amin_fwd_slow = 1;
 const float ewheel_amin_fwd_fast = 2;
index d235dfb32787124cdaf946b6bd59ff5178549db4..21c6acfccef7d55e25928e2a8111dc0717fda136 100644 (file)
@@ -1,3 +1,5 @@
+void W_MachineGun_MuzzleFlash(void);
+
 void spawnfunc_turret_machinegun();
 void turret_machinegun_std_init();
 void turret_machinegun_attack();
index a5aafda8f84d0589c112ff0d68950801f4a7ddec..dfda7a91341741fd3021320667b0acc619b8f6ea 100644 (file)
@@ -1,3 +1,5 @@
+#include "../../_all.qh"
+
 void spawnfunc_turret_phaser();
 void turret_phaser_dinit();
 void turret_phaser_attack();
index 4989b2445efc99808dab32b75b29935cdd46e95a..c95de1373ab7317ba979800ce6c58e03fb38b52d 100644 (file)
@@ -1,3 +1,5 @@
+#include "../../csqceffects.qh"
+
 void spawnfunc_turret_tesla();
 void turret_tesla_dinit();
 void turret_tesla_fire();
index 4b1c44c1541ca24b8f3da79738db8c1113731e09..f70f7ab26724a6eaa794d9fd917fa718f8b27901 100644 (file)
@@ -1,3 +1,8 @@
+#include "../../_all.qh"
+
+#include "../../movelib.qh"
+#include "../../steerlib.qh"
+
 const float ANIM_NO         = 0;
 const float ANIM_TURN       = 1;
 const float ANIM_WALK       = 2;
@@ -56,7 +61,7 @@ void walker_rocket_explode()
     remove (self);
 }
 
-void walker_rocket_damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector vforce)
+void walker_rocket_damage (entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector vforce)
 {
     self.health = self.health - damage;
     self.velocity = self.velocity + vforce;
diff --git a/qcsrc/server/vehicles/all.qc b/qcsrc/server/vehicles/all.qc
new file mode 100644 (file)
index 0000000..33e0c71
--- /dev/null
@@ -0,0 +1,11 @@
+#if VEHICLES_ENABLED
+#   include "vehicle.qc"
+
+#   include "racer.qc"
+#   include "raptor.qc"
+#   include "spiderbot.qc"
+
+#   ifndef VEHICLES_NO_UNSTABLE
+#       include "bumblebee.qc"
+#   endif
+#endif
diff --git a/qcsrc/server/vehicles/all.qh b/qcsrc/server/vehicles/all.qh
new file mode 100644 (file)
index 0000000..5203062
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef VEHICLES_ALL_H
+#define VEHICLES_ALL_H
+
+#if VEHICLES_ENABLED
+#   include "racer.qh"
+#   include "raptor.qh"
+#   include "spiderbot.qh"
+
+#   ifndef VEHICLES_NO_UNSTABLE
+#       include "bumblebee.qh"
+#   endif
+#endif
+
+#endif
index 9b3ae6c31d1b2a75cc5e05f00335150be11d68ee..79eac74bb393c8d38c839ac1c1d0f136c1405396 100644 (file)
@@ -1,6 +1,7 @@
 #include "bumblebee.qh"
 
 #ifdef SVQC
+#include "vehicle.qh"
 void bumb_fire_cannon(entity _gun, string _tagname, entity _owner)
 {
        vector v = gettaginfo(_gun, gettagindex(_gun, _tagname));
@@ -323,6 +324,7 @@ void bumb_regen()
 
 }
 
+.vector hook_start, hook_end;
 float bumb_pilot_frame()
 {
        entity pilot, vehic;
@@ -844,7 +846,7 @@ void spawnfunc_vehicle_bumblebee()
        }
 }
 
-float bumble_raygun_send(entity to, float sf)
+float bumble_raygun_send(entity to, int sf)
 {
        WriteByte(MSG_ENTITY, ENT_CLIENT_BUMBLE_RAYGUN);
 
index 727cbf2a6e5715851fa45a76e1816d68833669c0..16dba7ba2abf859bd1a0720ec185418a4e8e7920 100644 (file)
@@ -78,7 +78,7 @@ vector autocvar_g_vehicle_bumblebee_bouncepain;
 float autocvar_g_vehicle_bumblebee = 0;
 
 
-float bumble_raygun_send(entity to, float sf);
+float bumble_raygun_send(entity to, int sf);
 
 const vector BUMB_MIN = '-130 -130 -130';
 const vector BUMB_MAX = '130 130 130';
@@ -117,7 +117,7 @@ void bumb_spawn(float _f);
 
 void spawnfunc_vehicle_bumblebee();
 
-float bumble_raygun_send(entity to, float sf);
+float bumble_raygun_send(entity to, int sf);
 #endif // SVQC
 
 #ifdef CSQC
index 87dfe52a7e55f2d0a8b94dadbbb4dcacca51653a..8cecdfa84017ad25187fa9c55a7f5c6a3beaecd3 100644 (file)
@@ -1,7 +1,9 @@
-const vector RACER_MIN = '-120 -120 -40';
-const vector RACER_MAX = '120 120 40';
+#include "vehicle.qh"
+#include "racer.qh"
 
 #ifdef SVQC
+#include "../../common/triggers/trigger/impulse.qh"
+
 void racer_exit(float eject);
 void racer_enter();
 
@@ -239,7 +241,7 @@ void racer_rocket_tracker()
 void racer_fire_rocket(string tagname, entity trg)
 {
     vector v = gettaginfo(self, gettagindex(self, tagname));
-    entity rocket = rocket = vehicles_projectile("wakizashi_rocket_launch", "weapons/rocket_fire.wav",
+    entity rocket = vehicles_projectile("wakizashi_rocket_launch", "weapons/rocket_fire.wav",
                            v, v_forward * autocvar_g_vehicle_racer_rocket_speed,
                            autocvar_g_vehicle_racer_rocket_damage, autocvar_g_vehicle_racer_rocket_radius, autocvar_g_vehicle_racer_rocket_force, 3,
                            DEATH_VH_WAKI_ROCKET, PROJECTILE_WAKIROCKET, 20, false, false, self.owner);
@@ -448,6 +450,8 @@ float racer_frame()
     return 1;
 }
 
+.float lastpushtime;
+
 void racer_think()
 {
     self.nextthink = time;
diff --git a/qcsrc/server/vehicles/racer.qh b/qcsrc/server/vehicles/racer.qh
new file mode 100644 (file)
index 0000000..0051b77
--- /dev/null
@@ -0,0 +1,5 @@
+#ifndef RACER_H
+#define RACER_H
+const vector RACER_MIN = '-120 -120 -40';
+const vector RACER_MAX = '120 120 40';
+#endif
index 4533da6f3b212701e728cecc2709671df0c7c6ee..5c14fb7935d02f87fc9febfb287d1583f259a0f5 100644 (file)
@@ -1,10 +1,5 @@
-const float RSM_FIRST = 0;
-const float RSM_BOMB = 0;
-const float RSM_FLARE = 1;
-const float RSM_LAST = 1;
-
-const vector RAPTOR_MIN = '-80 -80 0';
-const vector RAPTOR_MAX = '80 80 70';
+#include "vehicle.qh"
+#include "raptor.qh"
 
 #ifdef SVQC
 float autocvar_g_vehicle_raptor;
@@ -345,7 +340,7 @@ void raptor_flare_touch()
     remove(self);
 }
 
-void raptor_flare_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
+void raptor_flare_damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
 {
     self.health -= damage;
     if(self.health <= 0)
diff --git a/qcsrc/server/vehicles/raptor.qh b/qcsrc/server/vehicles/raptor.qh
new file mode 100644 (file)
index 0000000..0043789
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef RAPTOR_H
+#define RAPTOR_H
+const float RSM_FIRST = 0;
+const float RSM_BOMB = 0;
+const float RSM_FLARE = 1;
+const float RSM_LAST = 1;
+
+const vector RAPTOR_MIN = '-80 -80 0';
+const vector RAPTOR_MAX = '80 80 70';
+
+#endif
index c969e225ebc3bc21a3d504dfa7c80c9f465c6700..c2a59fd18363c36d8aebb01d7ed3f920ce759016 100644 (file)
@@ -1,5 +1,5 @@
-const vector SPIDERBOT_MIN = '-75 -75 10';
-const vector SPIDERBOT_MAX  = '75 75 125';
+#include "vehicle.qh"
+#include "spiderbot.qh"
 
 #ifdef SVQC
 float autocvar_g_vehicle_spiderbot;
diff --git a/qcsrc/server/vehicles/spiderbot.qh b/qcsrc/server/vehicles/spiderbot.qh
new file mode 100644 (file)
index 0000000..ce96858
--- /dev/null
@@ -0,0 +1,5 @@
+#ifndef SPIDERBOT_H
+#define SPIDERBOT_H
+const vector SPIDERBOT_MIN = '-75 -75 10';
+const vector SPIDERBOT_MAX  = '75 75 125';
+#endif
diff --git a/qcsrc/server/vehicles/vehicle.qc b/qcsrc/server/vehicles/vehicle.qc
new file mode 100644 (file)
index 0000000..2622b52
--- /dev/null
@@ -0,0 +1,1434 @@
+#include "vehicle.qh"
+
+#include "../_all.qh"
+#include "../cl_player.qh"
+#include "../../common/constants.qh"
+#include "../waypointsprites.qh"
+
+#include "../bot/waypoints.qh"
+
+float autocvar_g_vehicles_crush_dmg;
+float autocvar_g_vehicles_crush_force;
+float autocvar_g_vehicles_delayspawn;
+float autocvar_g_vehicles_delayspawn_jitter;
+
+float autocvar_g_vehicles_vortex_damagerate = 0.5;
+float autocvar_g_vehicles_machinegun_damagerate = 0.5;
+float autocvar_g_vehicles_rifle_damagerate = 0.75;
+float autocvar_g_vehicles_vaporizer_damagerate = 0.001;
+float autocvar_g_vehicles_tag_damagerate = 5;
+
+float autocvar_g_vehicles;
+
+void vehicles_damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force);
+void vehicles_return();
+void vehicles_enter();
+void vehicles_reset_colors();
+void vehicles_clearreturn();
+void vehicles_setreturn();
+
+
+/** AuxiliaryXhair*
+    Send additional points of interest to be drawn, to vehicle owner
+**/
+const float MAX_AXH = 4;
+.entity AuxiliaryXhairs[MAX_AXH];
+
+float SendAuxiliaryXhair(entity to, int sf)
+{
+
+       WriteByte(MSG_ENTITY, ENT_CLIENT_AUXILIARYXHAIR);
+
+       WriteByte(MSG_ENTITY, self.cnt);
+
+       WriteCoord(MSG_ENTITY, self.origin.x);
+       WriteCoord(MSG_ENTITY, self.origin.y);
+       WriteCoord(MSG_ENTITY, self.origin.z);
+
+    WriteByte(MSG_ENTITY, rint(self.colormod.x * 255));
+    WriteByte(MSG_ENTITY, rint(self.colormod.y * 255));
+    WriteByte(MSG_ENTITY, rint(self.colormod.z * 255));
+
+    return true;
+}
+
+void UpdateAuxiliaryXhair(entity own, vector loc, vector clr, int axh_id)
+{
+    if (!IS_REAL_CLIENT(own))
+        return;
+
+    entity axh;
+
+    axh_id = bound(0, axh_id, MAX_AXH);
+    axh = own.(AuxiliaryXhairs[axh_id]);
+
+    if(axh == world || wasfreed(axh))  // MADNESS? THIS IS QQQQCCCCCCCCC (wasfreed, why do you exsist?)
+    {
+        axh                     = spawn();
+        axh.cnt                 = axh_id;
+        axh.drawonlytoclient    = own;
+        axh.owner               = own;
+        Net_LinkEntity(axh, false, 0, SendAuxiliaryXhair);
+    }
+
+    setorigin(axh, loc);
+    axh.colormod            = clr;
+    axh.SendFlags           = 0x01;
+    own.(AuxiliaryXhairs[axh_id]) = axh;
+}
+
+/*
+// SVC_TEMPENTITY based, horrible with even 50 ping. hm.
+// WriteByte(MSG_ONE, SVC_TEMPENTITY) uses reliable messagess, never use for thinsg that need continous updates.
+void SendAuxiliaryXhair2(entity own, vector loc, vector clr, float axh_id)
+{
+       msgexntity = own;
+
+       WriteByte(MSG_ONE, SVC_TEMPENTITY);
+       WriteByte(MSG_ONE, TE_CSQC_AUXILIARYXHAIR);
+
+       WriteByte(MSG_ONE, axh_id);
+
+       WriteCoord(MSG_ONE, loc_x);
+       WriteCoord(MSG_ONE, loc_y);
+       WriteCoord(MSG_ONE, loc_z);
+
+    WriteByte(MSG_ONE, rint(clr_x * 255));
+    WriteByte(MSG_ONE, rint(clr_y * 255));
+    WriteByte(MSG_ONE, rint(clr_z * 255));
+
+}
+*/
+// End AuxiliaryXhair
+
+/**
+    Notifies the client that he enterd a vehicle, and sends
+    realavent data.
+
+    only sends vehicle_id atm (wich is a HUD_* constant, ex. HUD_SPIDERBOT)
+**/
+void CSQCVehicleSetup(entity own, float vehicle_id)
+{
+    if (!IS_REAL_CLIENT(own))
+        return;
+
+       msg_entity = own;
+
+       WriteByte(MSG_ONE, SVC_TEMPENTITY);
+       WriteByte(MSG_ONE, TE_CSQC_VEHICLESETUP);
+       if(vehicle_id != 0)
+           WriteByte(MSG_ONE, vehicle_id);
+       else
+        WriteByte(MSG_ONE, 1 + own.vehicle.vehicle_weapon2mode + HUD_VEHICLE_LAST);
+}
+
+
+const float    DAMAGE_TARGETDRONE = 10;
+
+vector targetdrone_getnewspot()
+{
+
+       vector spot;
+       float i;
+       for(i = 0; i < 100; ++i)
+       {
+               spot = self.origin + randomvec() * 1024;
+               tracebox(spot, self.mins, self.maxs, spot, MOVE_NORMAL, self);
+               if(trace_fraction == 1.0 && trace_startsolid == 0 && trace_allsolid == 0)
+                       return spot;
+       }
+       return self.origin;
+}
+
+#if 0
+void targetdrone_think();
+void targetdrone_damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force);
+void targetdrone_renwe()
+{
+       self.think = targetdrone_think;
+       self.nextthink = time + 0.1;
+       setorigin(self, targetdrone_getnewspot());
+       self.health = 200;
+       self.takedamage = DAMAGE_TARGETDRONE;
+       self.event_damage = targetdrone_damage;
+       self.solid = SOLID_BBOX;
+       setmodel(self, "models/runematch/rune.mdl");
+       self.effects = EF_LOWPRECISION;
+       self.scale = 10;
+       self.movetype = MOVETYPE_BOUNCEMISSILE;
+       setsize(self, '-100 -100 -100', '100 100 100');
+
+}
+void targetdrone_damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
+{
+       self.health -= damage;
+       if(self.health <= 0)
+       {
+               pointparticles(particleeffectnum("explosion_medium"), self.origin, '0 0 0', 1);
+
+               if(!self.cnt)
+                       remove(self);
+               else
+               {
+                       self.think = targetdrone_renwe;
+                       self.nextthink = time + 1 + random() * 2;
+                       self.solid = SOLID_NOT;
+                       setmodel(self, "");
+               }
+       }
+}
+entity targetdrone_getfear()
+{
+       entity fear;
+       float i;
+
+       for(i = 64; i <= 1024; i += 64)
+       {
+               fear = findradius(self.origin, i);
+               while(fear)
+               {
+                       if(fear.bot_dodge)
+                               return fear;
+
+                       fear = fear.chain;
+               }
+       }
+
+       return world;
+}
+void targetdrone_think()
+{
+       self.nextthink = time + 0.1;
+
+       if(self.wp00)
+       if(self.wp00.deadflag != DEAD_NO)
+               self.wp00 = targetdrone_getfear();
+
+       if(!self.wp00)
+               self.wp00 = targetdrone_getfear();
+
+       vector newdir;
+
+       if(self.wp00)
+               newdir = steerlib_push(self.wp00.origin) + randomvec() * 0.75;
+       else
+               newdir = randomvec() * 0.75;
+
+       newdir = newdir * 0.5 + normalize(self.velocity) * 0.5;
+
+       if(self.wp00)
+               self.velocity = normalize(newdir) * (500 + (1024 / min(vlen(self.wp00.origin - self.origin), 1024)) * 700);
+       else
+               self.velocity = normalize(newdir) * 750;
+
+       tracebox(self.origin, self.mins, self.maxs, self.origin + self.velocity * 2, MOVE_NORMAL, self);
+       if(trace_fraction != 1.0)
+               self.velocity = self.velocity * -1;
+
+       //normalize((normalize(self.velocity) * 0.5 + newdir * 0.5)) * 750;
+}
+
+void targetdrone_spawn(vector _where, float _autorenew)
+{
+       entity drone = spawn();
+       setorigin(drone, _where);
+       drone.think = targetdrone_renwe;
+       drone.nextthink = time + 0.1;
+       drone.cnt = _autorenew;
+}
+#endif
+
+void vehicles_locktarget(float incr, float decr, float _lock_time)
+{
+    if(self.lock_target && self.lock_target.deadflag != DEAD_NO)
+    {
+        self.lock_target    = world;
+        self.lock_strength  = 0;
+        self.lock_time      = 0;
+    }
+
+    if(self.lock_time > time)
+    {
+        if(self.lock_target)
+        if(self.lock_soundtime < time)
+        {
+            self.lock_soundtime = time + 0.5;
+            play2(self.owner, "vehicles/locked.wav");
+        }
+
+        return;
+    }
+
+    if(trace_ent != world)
+    {
+        if(teamplay && trace_ent.team == self.team)
+            trace_ent = world;
+
+        if(trace_ent.deadflag != DEAD_NO)
+            trace_ent = world;
+        if(!(
+            (trace_ent.vehicle_flags & VHF_ISVEHICLE) || 
+            (trace_ent.turrcaps_flags & TFL_TURRCAPS_ISTURRET) || 
+            (trace_ent.takedamage == DAMAGE_TARGETDRONE)
+            )) { trace_ent = world; }
+    }
+
+    if(self.lock_target == world && trace_ent != world)
+        self.lock_target = trace_ent;
+
+    if(self.lock_target && trace_ent == self.lock_target)
+    {
+        if(self.lock_strength != 1 && self.lock_strength + incr >= 1)
+        {
+            play2(self.owner, "vehicles/lock.wav");
+            self.lock_soundtime = time + 0.8;
+        }
+        else if (self.lock_strength != 1 && self.lock_soundtime < time)
+        {
+            play2(self.owner, "vehicles/locking.wav");
+            self.lock_soundtime = time + 0.3;
+        }
+
+    }
+
+    // Have a locking target
+    // Trace hit current target
+    if(trace_ent == self.lock_target && trace_ent != world)
+    {
+        self.lock_strength = min(self.lock_strength + incr, 1);
+        if(self.lock_strength == 1)
+            self.lock_time = time + _lock_time;
+    }
+    else
+    {
+        if(trace_ent)
+            self.lock_strength = max(self.lock_strength - decr * 2, 0);
+        else
+            self.lock_strength = max(self.lock_strength - decr, 0);
+
+        if(self.lock_strength == 0)
+            self.lock_target = world;
+    }
+}
+
+
+#define vehicles_sweap_collision(orig,vel,dt,acm,mult) \
+traceline(orig, orig + vel * dt, MOVE_NORMAL, self); \
+if(trace_fraction != 1) \
+    acm += normalize(self.origin - trace_endpos) * (vlen(vel) * mult)
+
+// Hover movement support
+float  force_fromtag_power;
+vector force_fromtag_origin;
+vector vehicles_force_fromtag_hover(string tag_name, float spring_length, float max_power)
+{
+    force_fromtag_origin = gettaginfo(self, gettagindex(self, tag_name));
+    v_forward  = normalize(v_forward) * -1;
+    traceline(force_fromtag_origin, force_fromtag_origin - (v_forward  * spring_length), MOVE_NORMAL, self);
+
+    force_fromtag_power = (1 - trace_fraction) * max_power;
+    force_fromtag_normpower = force_fromtag_power / max_power;
+
+    return v_forward  * force_fromtag_power;
+}
+
+// Experimental hovermode wich uses attraction/repulstion from surface insted of gravity/repulsion
+// Can possibly be use to move abt any surface (inclusing walls/celings)
+vector vehicles_force_fromtag_maglev(string tag_name, float spring_length, float max_power)
+{
+
+    force_fromtag_origin = gettaginfo(self, gettagindex(self, tag_name));
+    v_forward  = normalize(v_forward) * -1;
+    traceline(force_fromtag_origin, force_fromtag_origin - (v_forward  * spring_length), MOVE_NORMAL, self);
+
+    // TODO - this may NOT be compatible with wall/celing movement, unhardcode 0.25 (engine count multiplier)
+    if(trace_fraction == 1.0)
+    {
+        force_fromtag_normpower = -0.25;
+        return '0 0 -200';
+    }
+
+    force_fromtag_power = ((1 - trace_fraction) - trace_fraction) * max_power;
+    force_fromtag_normpower = force_fromtag_power / max_power;
+
+    return v_forward  * force_fromtag_power;
+}
+
+// Generic vehile projectile system
+void vehicles_projectile_damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
+{
+    // Ignore damage from oterh projectiles from my owner (dont mess up volly's)
+    if(inflictor.owner == self.owner)
+        return;
+
+    self.health -= damage;
+    self.velocity += force;
+    if(self.health < 1)
+    {
+        self.takedamage = DAMAGE_NO;
+        self.event_damage = func_null;
+        self.think = self.use;
+        self.nextthink = time;
+    }
+}
+
+void vehicles_projectile_explode()
+{
+    if(self.owner && other != world)
+    {
+        if(other == self.owner.vehicle)
+            return;
+
+        if(other == self.owner.vehicle.tur_head)
+            return;
+    }
+
+       PROJECTILE_TOUCH;
+
+       self.event_damage = func_null;
+    RadiusDamage (self, self.realowner, self.shot_dmg, 0, self.shot_radius, self, world, self.shot_force, self.totalfrags, other);
+
+    remove (self);
+}
+
+entity vehicles_projectile(string _mzlfx, string _mzlsound,
+                           vector _org, vector _vel,
+                           float _dmg, float _radi, float _force,  float _size,
+                           float _deahtype, float _projtype, float _health,
+                           float _cull, float _clianim, entity _owner)
+{
+    entity proj;
+
+    proj = spawn();
+
+    PROJECTILE_MAKETRIGGER(proj);
+    setorigin(proj, _org);
+
+    proj.shot_dmg         = _dmg;
+    proj.shot_radius      = _radi;
+    proj.shot_force       = _force;
+    proj.totalfrags       = _deahtype;
+    proj.solid            = SOLID_BBOX;
+    proj.movetype         = MOVETYPE_FLYMISSILE;
+    proj.flags            = FL_PROJECTILE;
+    proj.bot_dodge        = true;
+    proj.bot_dodgerating  = _dmg;
+    proj.velocity         = _vel;
+    proj.touch            = vehicles_projectile_explode;
+    proj.use              = vehicles_projectile_explode;
+    proj.owner            = self;
+    proj.realowner        = _owner;
+    proj.think            = SUB_Remove;
+    proj.nextthink        = time + 30;
+
+    if(_health)
+    {
+        proj.takedamage       = DAMAGE_AIM;
+        proj.event_damage     = vehicles_projectile_damage;
+        proj.health           = _health;
+    }
+    else
+        proj.flags           = FL_PROJECTILE | FL_NOTARGET;
+
+    if(_mzlsound)
+        sound (self, CH_WEAPON_A, _mzlsound, VOL_BASE, ATTEN_NORM);
+
+    if(_mzlfx)
+        pointparticles(particleeffectnum(_mzlfx), proj.origin, proj.velocity, 1);
+
+
+    setsize (proj, '-1 -1 -1' * _size, '1 1 1' * _size);
+
+    CSQCProjectile(proj, _clianim, _projtype, _cull);
+
+    return proj;
+}
+// End generic vehile projectile system
+
+void vehicles_reset()
+{
+       if(self.owner)
+       {
+               entity oldself = self;
+               self = self.owner;
+               vehicles_exit(VHEF_RELESE);
+               self = oldself;
+       }
+       self.alpha      = -1;
+       self.movetype   = MOVETYPE_NONE;
+       self.effects    = EF_NODRAW;
+       self.colormod  = '0 0 0';
+       self.avelocity = '0 0 0';
+       self.velocity  = '0 0 0';
+       self.event_damage = func_null;
+       self.solid = SOLID_NOT;
+       self.deadflag = DEAD_NO;
+
+       self.touch = func_null;
+       self.nextthink = 0;
+       vehicles_setreturn();
+}
+
+/** vehicles_spawn
+    Exetuted for all vehicles on (re)spawn.
+    Sets defaults for newly spawned units.
+**/
+void vehicles_spawn()
+{
+    dprint("Spawning vehicle: ", self.netname, "\n");
+
+    // De-own & reset
+    self.vehicle_hudmodel.viewmodelforclient = self;
+
+    self.owner              = world;
+    self.touch              = vehicles_touch;
+    self.event_damage       = vehicles_damage;
+    self.reset              = vehicles_reset;
+    self.iscreature         = true;
+    self.teleportable       = false; // no teleporting for vehicles, too buggy
+    self.damagedbycontents     = true;
+    self.movetype           = MOVETYPE_WALK;
+    self.solid              = SOLID_SLIDEBOX;
+    self.takedamage         = DAMAGE_AIM;
+       self.deadflag           = DEAD_NO;
+    self.bot_attack         = true;
+    self.flags              = FL_NOTARGET;
+    self.avelocity          = '0 0 0';
+    self.velocity           = '0 0 0';
+
+    // Reset locking
+    self.lock_strength      = 0;
+    self.lock_target        = world;
+    self.misc_bulletcounter = 0;
+
+    // Return to spawn
+    self.angles             = self.pos2;
+    setorigin(self, self.pos1 + '0 0 0');
+    // Show it
+    pointparticles(particleeffectnum("teleport"), self.origin + '0 0 64', '0 0 0', 1);
+
+    if(self.vehicle_controller)
+        self.team = self.vehicle_controller.team;
+
+    vehicles_reset_colors();
+    self.vehicle_spawn(VHSF_NORMAL);
+}
+
+// Better way of determening whats crushable needed! (fl_crushable?)
+float vehicles_crushable(entity e)
+{
+    if(IS_PLAYER(e))
+        return true;
+
+    if(e.flags & FL_MONSTER)
+        return true;
+
+    return false;
+}
+
+void vehicles_impact(float _minspeed, float _speedfac, float _maxpain)
+{
+    if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
+        return;
+
+    if(self.play_time < time)
+    {
+        float wc = vlen(self.velocity - self.oldvelocity);
+        //dprint("oldvel: ", vtos(self.oldvelocity), "\n");
+        //dprint("vel: ", vtos(self.velocity), "\n");
+        if(_minspeed < wc)
+        {
+            float take = min(_speedfac * wc, _maxpain);
+            Damage (self, world, world, take, DEATH_FALL, self.origin, '0 0 0');
+            self.play_time = time + 0.25;
+
+            //dprint("wc: ", ftos(wc), "\n");
+            //dprint("take: ", ftos(take), "\n");
+        }
+    }
+}
+
+void vehicles_touch()
+{
+       if(MUTATOR_CALLHOOK(VehicleTouch))
+               return;
+
+    // Vehicle currently in use
+    if(self.owner)
+    {
+        if(other != world)
+        if(vehicles_crushable(other))
+        {
+            if(vlen(self.velocity) != 0)
+                Damage(other, self, self.owner, autocvar_g_vehicles_crush_dmg, DEATH_VH_CRUSH, '0 0 0', normalize(other.origin - self.origin) * autocvar_g_vehicles_crush_force);
+
+            return; // Dont do selfdamage when hitting "soft targets".
+        }
+
+        if(self.play_time < time)
+        if(self.vehicle_impact)
+            self.vehicle_impact();
+
+        return;
+    }
+
+    if (!IS_PLAYER(other))
+        return;
+
+    if(other.deadflag != DEAD_NO)
+        return;
+
+    if(other.vehicle != world)
+        return;
+
+    vehicles_enter();
+}
+.float monster_attack;
+void vehicles_enter()
+{
+   // Remove this when bots know how to use vehicles
+
+    if (IS_BOT_CLIENT(other))
+        if (autocvar_g_vehicles_allow_bots)
+            dprint("Bot enters vehicle\n"); // This is where we need to disconnect (some, all?) normal bot AI and hand over to vehicle's _aiframe()
+        else
+            return;
+
+    if(self.phase > time)
+        return;
+    if(other.frozen)
+        return;
+    if(other.vehicle)
+        return;
+    if(other.deadflag != DEAD_NO)
+        return;
+
+    if(teamplay)
+    if(self.team)
+    if(self.team != other.team)
+        return;
+
+    RemoveGrapplingHook(other);
+
+    self.vehicle_ammo1   = 0;
+    self.vehicle_ammo2   = 0;
+    self.vehicle_reload1 = 0;
+    self.vehicle_reload2 = 0;
+    self.vehicle_energy  = 0;
+
+    self.owner          = other;
+    self.switchweapon   = other.switchweapon;
+
+    // .viewmodelforclient works better.
+    //self.vehicle_hudmodel.drawonlytoclient = self.owner;
+
+    self.vehicle_hudmodel.viewmodelforclient = self.owner;
+
+    self.event_damage         = vehicles_damage;
+    self.nextthink            = 0;
+    self.owner.angles         = self.angles;
+    self.owner.takedamage     = DAMAGE_NO;
+    self.owner.solid          = SOLID_NOT;
+    self.owner.movetype       = MOVETYPE_NOCLIP;
+    self.owner.alpha          = -1;
+    self.owner.vehicle        = self;
+    self.owner.event_damage   = func_null;
+    self.owner.view_ofs       = '0 0 0';
+    self.colormap             = self.owner.colormap;
+    if(self.tur_head)
+        self.tur_head.colormap    = self.owner.colormap;
+
+    self.owner.hud            = self.hud;
+    self.owner.PlayerPhysplug = self.PlayerPhysplug;
+
+    self.owner.vehicle_ammo1    = self.vehicle_ammo1;
+    self.owner.vehicle_ammo2    = self.vehicle_ammo2;
+    self.owner.vehicle_reload1  = self.vehicle_reload1;
+    self.owner.vehicle_reload2  = self.vehicle_reload2;
+
+    // Cant do this, hides attached objects too.
+    //self.exteriormodeltoclient = self.owner;
+    //self.tur_head.exteriormodeltoclient = self.owner;
+
+    other.flags &= ~FL_ONGROUND;
+    self.flags  &= ~FL_ONGROUND;
+
+    self.team                 = self.owner.team;
+    self.flags               -= FL_NOTARGET;
+    self.monster_attack       = true;
+
+    if (IS_REAL_CLIENT(other))
+    {
+        msg_entity = other;
+        WriteByte (MSG_ONE, SVC_SETVIEWPORT);
+        WriteEntity(MSG_ONE, self.vehicle_viewport);
+
+        WriteByte (MSG_ONE, SVC_SETVIEWANGLES);
+        if(self.tur_head)
+        {
+            WriteAngle(MSG_ONE, self.tur_head.angles.x + self.angles.x); // tilt
+            WriteAngle(MSG_ONE, self.tur_head.angles.y + self.angles.y); // yaw
+            WriteAngle(MSG_ONE, 0);                                      // roll
+        }
+        else
+        {
+            WriteAngle(MSG_ONE,  self.angles.x * -1); // tilt
+            WriteAngle(MSG_ONE,  self.angles.y);      // yaw
+            WriteAngle(MSG_ONE,  0);                  // roll
+        }
+    }
+
+    vehicles_clearreturn();
+
+    CSQCVehicleSetup(self.owner, self.hud);
+
+    vh_player = other;
+    vh_vehicle = self;
+    MUTATOR_CALLHOOK(VehicleEnter);
+    other = vh_player;
+    self = vh_vehicle;
+
+    self.vehicle_enter();
+    antilag_clear(other);
+}
+
+/** vehicles_findgoodexit
+    Locates a valid location for the player to exit the vehicle.
+    Will first try prefer_spot, then up 100 random spots arround the vehicle
+    wich are in direct line of sight and empty enougth to hold a players bbox
+**/
+vector vehicles_findgoodexit(vector prefer_spot)
+{
+    //vector exitspot;
+    float mysize;
+
+    tracebox(self.origin + '0 0 32', PL_MIN, PL_MAX, prefer_spot, MOVE_NORMAL, self.owner);
+    if(trace_fraction == 1.0 && !trace_startsolid && !trace_allsolid)
+        return prefer_spot;
+
+    mysize = 1.5 * vlen(self.maxs - self.mins);
+    float i;
+    vector v, v2;
+    v2 = 0.5 * (self.absmin + self.absmax);
+    for(i = 0; i < 100; ++i)
+    {
+        v = randomvec();
+        v.z = 0;
+        v = v2 + normalize(v) * mysize;
+        tracebox(v2, PL_MIN, PL_MAX, v, MOVE_NORMAL, self.owner);
+        if(trace_fraction == 1.0 && !trace_startsolid && !trace_allsolid)
+            return v;
+    }
+
+    /*
+    exitspot = (self.origin + '0 0 48') + v_forward * mysize;
+    tracebox(self.origin + '0 0 32', PL_MIN, PL_MAX, exitspot, MOVE_NORMAL, self.owner);
+    if(trace_fraction == 1.0 && !trace_startsolid && !trace_allsolid)
+        return exitspot;
+
+    exitspot = (self.origin + '0 0 48') - v_forward * mysize;
+    tracebox(self.origin + '0 0 32', PL_MIN, PL_MAX, exitspot, MOVE_NORMAL, self.owner);
+    if(trace_fraction == 1.0 && !trace_startsolid && !trace_allsolid)
+        return exitspot;
+
+    exitspot = (self.origin + '0 0 48') + v_right * mysize;
+    tracebox(self.origin + '0 0 32', PL_MIN, PL_MAX, exitspot, MOVE_NORMAL, self.owner);
+    if(trace_fraction == 1.0 && !trace_startsolid && !trace_allsolid)
+        return exitspot;
+
+    exitspot = (self.origin + '0 0 48') - v_right * mysize;
+    tracebox(self.origin + '0 0 32', PL_MIN, PL_MAX, exitspot, MOVE_NORMAL, self.owner);
+    if(trace_fraction == 1.0 && !trace_startsolid && !trace_allsolid)
+        return exitspot;
+    */
+
+    return self.origin;
+}
+
+/** vehicles_exit
+    Standarrd vehicle release fucntion.
+    custom code goes in self.vehicle_exit
+**/
+float vehicles_exit_running;
+void vehicles_exit(float eject)
+{
+    entity _vehicle;
+    entity _player;
+    entity _oldself = self;
+
+    if(vehicles_exit_running)
+    {
+        dprint("^1vehicles_exit allready running! this is not good..\n");
+        return;
+    }
+
+    vehicles_exit_running = true;
+    if(IS_CLIENT(self))
+    {
+        _vehicle = self.vehicle;
+
+        if (_vehicle.vehicle_flags & VHF_PLAYERSLOT)
+        {
+            _vehicle.vehicle_exit(eject);
+            self = _oldself;
+            vehicles_exit_running = false;
+            return;
+        }
+    }
+    else
+        _vehicle = self;
+
+    _player = _vehicle.owner;
+
+    self = _vehicle;
+
+    if (_player)
+    {
+        if (IS_REAL_CLIENT(_player))
+        {
+            msg_entity = _player;
+            WriteByte (MSG_ONE, SVC_SETVIEWPORT);
+            WriteEntity( MSG_ONE, _player);
+
+            WriteByte (MSG_ONE, SVC_SETVIEWANGLES);
+            WriteAngle(MSG_ONE, 0);
+            WriteAngle(MSG_ONE, _vehicle.angles.y);
+            WriteAngle(MSG_ONE, 0);
+        }
+
+        setsize(_player, PL_MIN,PL_MAX);
+
+        _player.takedamage     = DAMAGE_AIM;
+        _player.solid          = SOLID_SLIDEBOX;
+        _player.movetype       = MOVETYPE_WALK;
+        _player.effects        &= ~EF_NODRAW;
+        _player.alpha          = 1;
+        _player.PlayerPhysplug = func_null;
+        _player.vehicle        = world;
+        _player.view_ofs       = PL_VIEW_OFS;
+        _player.event_damage   = PlayerDamage;
+        _player.hud            = HUD_NORMAL;
+        _player.switchweapon   = _vehicle.switchweapon;
+
+        CSQCVehicleSetup(_player, HUD_NORMAL);
+    }
+    _vehicle.flags |= FL_NOTARGET;
+
+    if(_vehicle.deadflag == DEAD_NO)
+        _vehicle.avelocity          = '0 0 0';
+
+    _vehicle.tur_head.nodrawtoclient             = world;
+
+    if(!teamplay)
+        _vehicle.team = 0;
+
+    vh_player = _player;
+    vh_vehicle = _vehicle;
+    MUTATOR_CALLHOOK(VehicleExit);
+    _player = vh_player;
+    _vehicle = vh_vehicle;
+
+    _vehicle.team = _vehicle.tur_head.team;
+
+    sound (_vehicle, CH_TRIGGER_SINGLE, "misc/null.wav", 1, ATTEN_NORM);
+    _vehicle.vehicle_hudmodel.viewmodelforclient = _vehicle;
+    _vehicle.phase = time + 1;
+    _vehicle.monster_attack = false;
+
+    _vehicle.vehicle_exit(eject);
+
+    vehicles_setreturn();
+    vehicles_reset_colors();
+    _vehicle.owner = world;
+    self = _oldself;
+
+    vehicles_exit_running = false;
+}
+
+
+void vehicles_regen(float timer, .float regen_field, float field_max, float rpause, float regen, float delta_time, float _healthscale)
+{
+    if (self.(regen_field) < field_max)
+    if (timer + rpause < time)
+    {
+        if (_healthscale)
+            regen = regen * (self.vehicle_health / self.tur_health);
+
+        self.(regen_field) = min(self.(regen_field) + regen * delta_time, field_max);
+
+        if (self.owner)
+            self.owner.(regen_field) = (self.(regen_field) / field_max) * 100;
+    }
+}
+
+void shieldhit_think()
+{
+    self.alpha -= 0.1;
+    if (self.alpha <= 0)
+    {
+        //setmodel(self, "");
+        self.alpha = -1;
+        self.effects |= EF_NODRAW;
+    }
+    else
+    {
+        self.nextthink = time + 0.1;
+    }
+}
+
+void vehicles_painframe()
+{
+    if(self.owner.vehicle_health <= 50)
+    if(self.pain_frame < time)
+    {
+        float _ftmp;
+        _ftmp = self.owner.vehicle_health / 50;
+        self.pain_frame = time + 0.1 + (random() * 0.5 * _ftmp);
+        pointparticles(particleeffectnum("smoke_small"), (self.origin + (randomvec() * 80)), '0 0 0', 1);
+
+        if(self.vehicle_flags & VHF_DMGSHAKE)
+            self.velocity += randomvec() * 30;
+
+        if(self.vehicle_flags & VHF_DMGROLL)
+            if(self.vehicle_flags & VHF_DMGHEADROLL)
+                self.tur_head.angles += randomvec();
+            else
+                self.angles += randomvec();
+
+    }
+}
+
+void vehicles_damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
+{
+    self.dmg_time = time;
+
+       // WEAPONTODO
+    if(DEATH_ISWEAPON(deathtype, WEP_VORTEX))
+        damage *= autocvar_g_vehicles_vortex_damagerate;
+
+    if(DEATH_ISWEAPON(deathtype, WEP_MACHINEGUN))
+        damage *= autocvar_g_vehicles_machinegun_damagerate;
+
+    if(DEATH_ISWEAPON(deathtype, WEP_RIFLE))
+        damage *= autocvar_g_vehicles_rifle_damagerate;
+
+    if(DEATH_ISWEAPON(deathtype, WEP_VAPORIZER))
+        damage *= autocvar_g_vehicles_vaporizer_damagerate;
+
+    if(DEATH_ISWEAPON(deathtype, WEP_SEEKER))
+        damage *= autocvar_g_vehicles_tag_damagerate;
+
+    self.enemy = attacker;
+
+    if((self.vehicle_flags & VHF_HASSHIELD) && (self.vehicle_shield > 0))
+    {
+        if (wasfreed(self.vehicle_shieldent) || self.vehicle_shieldent == world)
+        {
+            self.vehicle_shieldent = spawn();
+            self.vehicle_shieldent.effects = EF_LOWPRECISION;
+
+            setmodel(self.vehicle_shieldent, "models/vhshield.md3");
+            setattachment(self.vehicle_shieldent, self, "");
+            setorigin(self.vehicle_shieldent, real_origin(self) - self.origin);
+            self.vehicle_shieldent.scale       = 256 / vlen(self.maxs - self.mins);
+            self.vehicle_shieldent.think       = shieldhit_think;
+        }
+
+        self.vehicle_shieldent.colormod    = '1 1 1';
+        self.vehicle_shieldent.alpha       = 0.45;
+        self.vehicle_shieldent.angles      = vectoangles(normalize(hitloc - (self.origin + self.vehicle_shieldent.origin))) - self.angles;
+        self.vehicle_shieldent.nextthink   = time;
+        self.vehicle_shieldent.effects &= ~EF_NODRAW;
+
+        self.vehicle_shield -= damage;
+
+        if(self.vehicle_shield < 0)
+        {
+            self.vehicle_health            -= fabs(self.vehicle_shield);
+            self.vehicle_shieldent.colormod = '2 0 0';
+            self.vehicle_shield             = 0;
+            self.vehicle_shieldent.alpha    = 0.75;
+
+               if(sound_allowed(MSG_BROADCAST, attacker))
+                spamsound (self, CH_PAIN, "onslaught/ons_hit2.wav", VOL_BASE, ATTEN_NORM);   // FIXME: PLACEHOLDER
+        }
+        else
+               if(sound_allowed(MSG_BROADCAST, attacker))
+                spamsound (self, CH_PAIN, "onslaught/electricity_explode.wav", VOL_BASE, ATTEN_NORM);  // FIXME: PLACEHOLDER
+
+    }
+    else
+    {
+        self.vehicle_health -= damage;
+
+        if(sound_allowed(MSG_BROADCAST, attacker))
+            spamsound (self, CH_PAIN, "onslaught/ons_hit2.wav", VOL_BASE, ATTEN_NORM);  // FIXME: PLACEHOLDER
+    }
+
+       if(self.damageforcescale < 1 && self.damageforcescale > 0)
+               self.velocity += force * self.damageforcescale;
+       else
+               self.velocity += force;
+
+    if(self.vehicle_health <= 0)
+    {
+        if(self.owner)
+            if(self.vehicle_flags & VHF_DEATHEJECT)
+                vehicles_exit(VHEF_EJECT);
+            else
+                vehicles_exit(VHEF_RELESE);
+
+
+        antilag_clear(self);
+
+        self.vehicle_die();
+        vehicles_setreturn();
+    }
+}
+
+void vehicles_clearreturn()
+{
+    entity ret;
+    // Remove "return helper", if any.
+    ret = findchain(classname, "vehicle_return");
+    while(ret)
+    {
+        if(ret.wp00 == self)
+        {
+            ret.classname   = "";
+            ret.think       = SUB_Remove;
+            ret.nextthink   = time + 0.1;
+
+            if(ret.waypointsprite_attached)
+                WaypointSprite_Kill(ret.waypointsprite_attached);
+
+            return;
+        }
+        ret = ret.chain;
+    }
+}
+
+void vehicles_return()
+{
+    pointparticles(particleeffectnum("teleport"), self.wp00.origin + '0 0 64', '0 0 0', 1);
+
+    self.wp00.think     = vehicles_spawn;
+    self.wp00.nextthink = time;
+
+    if(self.waypointsprite_attached)
+        WaypointSprite_Kill(self.waypointsprite_attached);
+
+    remove(self);
+}
+
+void vehicles_showwp_goaway()
+{
+    if(self.waypointsprite_attached)
+        WaypointSprite_Kill(self.waypointsprite_attached);
+
+    remove(self);
+
+}
+
+void vehicles_showwp()
+{
+    entity oldself = world;
+    vector rgb;
+
+    if(self.cnt)
+    {
+        self.think      = vehicles_return;
+        self.nextthink  = self.cnt;
+    }
+    else
+    {
+        self.think      = vehicles_return;
+        self.nextthink  = time +1;
+
+        oldself = self;
+        self = spawn();
+        setmodel(self, "null");
+        self.team = oldself.wp00.team;
+        self.wp00 = oldself.wp00;
+        setorigin(self, oldself.wp00.pos1);
+
+        self.nextthink = time + 5;
+        self.think = vehicles_showwp_goaway;
+    }
+
+    if(teamplay && self.team)
+           rgb = Team_ColorRGB(self.team);
+    else
+           rgb = '1 1 1';
+    WaypointSprite_Spawn("vehicle", 0, 0, self, '0 0 64', world, 0, self, waypointsprite_attached, true, RADARICON_POWERUP, rgb);
+    if(self.waypointsprite_attached)
+    {
+        WaypointSprite_UpdateRule(self.waypointsprite_attached, self.wp00.team, SPRITERULE_DEFAULT);
+        if(oldself == world)
+            WaypointSprite_UpdateBuildFinished(self.waypointsprite_attached, self.nextthink);
+        WaypointSprite_Ping(self.waypointsprite_attached);
+    }
+
+    if(oldself != world)
+        self = oldself;
+}
+
+void vehicles_setreturn()
+{
+    entity ret;
+
+    vehicles_clearreturn();
+
+    ret = spawn();
+    ret.classname   = "vehicle_return";
+    ret.wp00       = self;
+    ret.team        = self.team;
+    ret.think       = vehicles_showwp;
+
+       if(self.deadflag != DEAD_NO)
+       {
+               ret.cnt = max(game_starttime, time) + self.vehicle_respawntime;
+               ret.nextthink = max(game_starttime, time) + max(0, self.vehicle_respawntime - 5);
+       }
+       else
+               ret.nextthink = max(game_starttime, time) + max(0, self.vehicle_respawntime - 1);
+
+    setmodel(ret, "null");
+    setorigin(ret, self.pos1 + '0 0 96');
+}
+
+void vehicles_reset_colors()
+{
+    entity e;
+    float _effects = 0, _colormap;
+    vector _glowmod, _colormod;
+
+    if(autocvar_g_nodepthtestplayers)
+        _effects |= EF_NODEPTHTEST;
+
+    if(autocvar_g_fullbrightplayers)
+        _effects |= EF_FULLBRIGHT;
+
+    if(self.team)
+        _colormap = 1024 + (self.team - 1) * 17;
+    else
+        _colormap = 1024;
+
+    _glowmod  = '0 0 0';
+    _colormod = '0 0 0';
+
+    // Find all ents attacked to main model and setup effects, colormod etc.
+    e = findchainentity(tag_entity, self);
+    while(e)
+    {
+        if(e != self.vehicle_shieldent)
+        {
+            e.effects   = _effects; //  | EF_LOWPRECISION;
+            e.colormod  = _colormod;
+            e.colormap  = _colormap;
+            e.alpha     = 1;
+        }
+        e = e.chain;
+    }
+
+    self.vehicle_hudmodel.effects  = self.effects  = _effects; // | EF_LOWPRECISION;
+    self.vehicle_hudmodel.colormod = self.colormod = _colormod;
+    self.vehicle_hudmodel.colormap = self.colormap = _colormap;
+    self.vehicle_viewport.effects = (EF_ADDITIVE | EF_DOUBLESIDED | EF_FULLBRIGHT | EF_NODEPTHTEST | EF_NOGUNBOB | EF_NOSHADOW | EF_LOWPRECISION | EF_SELECTABLE | EF_TELEPORT_BIT);
+
+    self.alpha     = 1;
+    self.avelocity = '0 0 0';
+    self.velocity  = '0 0 0';
+    self.effects   = _effects;
+}
+
+void vehicle_use()
+{
+    dprint("vehicle ",self.netname, " used by ", activator.classname, "\n");
+
+    self.tur_head.team = activator.team;
+
+    if(self.tur_head.team == 0)
+        self.active = ACTIVE_NOT;
+    else
+        self.active = ACTIVE_ACTIVE;
+
+    if(self.active == ACTIVE_ACTIVE && self.deadflag == DEAD_NO)
+    {
+        dprint("^3Eat shit yall!\n");
+        vehicles_setreturn();
+        vehicles_reset_colors();
+    }
+    else if(self.active == ACTIVE_NOT && self.deadflag != DEAD_NO)
+    {
+
+    }
+}
+
+float vehicle_addplayerslot(    entity _owner,
+                                entity _slot,
+                                float _hud,
+                                string _hud_model,
+                                float() _framefunc,
+                                void(float) _exitfunc)
+{
+    if (!(_owner.vehicle_flags & VHF_MULTISLOT))
+        _owner.vehicle_flags |= VHF_MULTISLOT;
+
+    _slot.PlayerPhysplug = _framefunc;
+    _slot.vehicle_exit = _exitfunc;
+    _slot.hud = _hud;
+    _slot.vehicle_flags = VHF_PLAYERSLOT;
+    _slot.vehicle_viewport = spawn();
+    _slot.vehicle_hudmodel = spawn();
+    _slot.vehicle_hudmodel.viewmodelforclient = _slot;
+    _slot.vehicle_viewport.effects = (EF_ADDITIVE | EF_DOUBLESIDED | EF_FULLBRIGHT | EF_NODEPTHTEST | EF_NOGUNBOB | EF_NOSHADOW | EF_LOWPRECISION | EF_SELECTABLE | EF_TELEPORT_BIT);
+
+    setmodel(_slot.vehicle_hudmodel, _hud_model);
+    setmodel(_slot.vehicle_viewport, "null");
+
+    setattachment(_slot.vehicle_hudmodel, _slot, "");
+    setattachment(_slot.vehicle_viewport, _slot.vehicle_hudmodel, "");
+
+    return true;
+}
+
+float vehicle_initialize(string  net_name,
+                         string  bodymodel,
+                         string  topmodel,
+                         string  hudmodel,
+                         string  toptag,
+                         string  hudtag,
+                         string  viewtag,
+                         float   vhud,
+                         vector  min_s,
+                         vector  max_s,
+                         float   nodrop,
+                         void(float _spawnflag)  spawnproc,
+                         float   _respawntime,
+                         float() physproc,
+                         void()  enterproc,
+                         void(float extflag) exitfunc,
+                         void() dieproc,
+                         void() thinkproc,
+                         float  use_csqc,
+                         float _max_health,
+                         float _max_shield)
+{
+       if(!autocvar_g_vehicles)
+               return false;
+
+    if(self.targetname)
+    {
+        self.vehicle_controller = find(world, target, self.targetname);
+        if(!self.vehicle_controller)
+        {
+            bprint("^1WARNING: ^7Vehicle with invalid .targetname\n");
+        }
+        else
+        {
+            self.team = self.vehicle_controller.team;
+            self.use = vehicle_use;
+
+            if(teamplay)
+            {
+                if(self.vehicle_controller.team == 0)
+                    self.active = ACTIVE_NOT;
+                else
+                    self.active = ACTIVE_ACTIVE;
+            }
+        }
+    }
+
+    precache_sound("onslaught/ons_hit2.wav");
+    precache_sound("onslaught/electricity_explode.wav");
+
+
+    addstat(STAT_HUD, AS_INT,  hud);
+       addstat(STAT_VEHICLESTAT_HEALTH,  AS_INT, vehicle_health);
+       addstat(STAT_VEHICLESTAT_SHIELD,  AS_INT, vehicle_shield);
+       addstat(STAT_VEHICLESTAT_ENERGY,  AS_INT, vehicle_energy);
+
+       addstat(STAT_VEHICLESTAT_AMMO1,   AS_INT, vehicle_ammo1);
+       addstat(STAT_VEHICLESTAT_RELOAD1, AS_INT, vehicle_reload1);
+
+       addstat(STAT_VEHICLESTAT_AMMO2,   AS_INT, vehicle_ammo2);
+       addstat(STAT_VEHICLESTAT_RELOAD2, AS_INT, vehicle_reload2);
+
+    if(bodymodel == "")
+        error("vehicles: missing bodymodel!");
+
+    if(hudmodel == "")
+        error("vehicles: missing hudmodel!");
+
+    if(net_name == "")
+        self.netname = self.classname;
+    else
+        self.netname = net_name;
+
+    if(self.team && !teamplay)
+        self.team = 0;
+
+    self.vehicle_flags |= VHF_ISVEHICLE;
+
+    setmodel(self, bodymodel);
+
+    self.vehicle_viewport   = spawn();
+    self.vehicle_hudmodel   = spawn();
+    self.tur_head           = spawn();
+    self.tur_head.owner     = self;
+    self.takedamage         = DAMAGE_AIM;
+    self.bot_attack         = true;
+    self.iscreature         = true;
+    self.teleportable       = false; // no teleporting for vehicles, too buggy
+    self.damagedbycontents     = true;
+    self.hud                = vhud;
+    self.tur_health          = _max_health;
+    self.tur_head.tur_health = _max_shield;
+    self.vehicle_die         = dieproc;
+    self.vehicle_exit        = exitfunc;
+    self.vehicle_enter       = enterproc;
+    self.PlayerPhysplug      = physproc;
+    self.event_damage        = func_null;
+    self.touch               = vehicles_touch;
+    self.think               = vehicles_spawn;
+    self.vehicle_spawn       = spawnproc;
+       self.vehicle_respawntime = max(0, _respawntime);
+    self.effects             = EF_NODRAW;
+       self.dphitcontentsmask   = DPCONTENTS_BODY | DPCONTENTS_SOLID;
+       if(!autocvar_g_vehicles_delayspawn || !self.vehicle_respawntime)
+               self.nextthink = time;
+       else
+               self.nextthink = max(time, game_starttime) + max(0, self.vehicle_respawntime + ((random() * 2 - 1) * autocvar_g_vehicles_delayspawn_jitter));
+
+       if(autocvar_g_playerclip_collisions)
+               self.dphitcontentsmask |= DPCONTENTS_PLAYERCLIP;
+
+    if(autocvar_g_nodepthtestplayers)
+        self.effects = self.effects | EF_NODEPTHTEST;
+
+    if(autocvar_g_fullbrightplayers)
+        self.effects = self.effects | EF_FULLBRIGHT;
+
+    setmodel(self.vehicle_hudmodel, hudmodel);
+    setmodel(self.vehicle_viewport, "null");
+
+    if(topmodel != "")
+    {
+        setmodel(self.tur_head, topmodel);
+        setattachment(self.tur_head, self, toptag);
+        setattachment(self.vehicle_hudmodel, self.tur_head, hudtag);
+        setattachment(self.vehicle_viewport, self.vehicle_hudmodel, viewtag);
+    }
+    else
+    {
+        setattachment(self.tur_head, self, "");
+        setattachment(self.vehicle_hudmodel, self, hudtag);
+        setattachment(self.vehicle_viewport, self.vehicle_hudmodel, viewtag);
+    }
+
+    setsize(self, min_s, max_s);
+    if (!nodrop)
+    {
+        setorigin(self, self.origin);
+        tracebox(self.origin + '0 0 100', min_s, max_s, self.origin - '0 0 10000', MOVE_WORLDONLY, self);
+        setorigin(self, trace_endpos);
+    }
+
+    self.pos1 = self.origin;
+    self.pos2 = self.angles;
+    self.tur_head.team = self.team;
+
+       if(MUTATOR_CALLHOOK(VehicleSpawn))
+               return false;
+
+    return true;
+}
+
+vector vehicle_aimturret(entity _vehic, vector _target, entity _turrret, string _tagname,
+                         float _pichlimit_min, float _pichlimit_max,
+                         float _rotlimit_min, float _rotlimit_max, float _aimspeed)
+{
+    vector vtmp, vtag;
+    float ftmp;
+    vtag = gettaginfo(_turrret, gettagindex(_turrret, _tagname));
+    vtmp = vectoangles(normalize(_target - vtag));
+    vtmp = AnglesTransform_ToAngles(AnglesTransform_LeftDivide(AnglesTransform_FromAngles(_vehic.angles), AnglesTransform_FromAngles(vtmp))) - _turrret.angles;
+    vtmp = AnglesTransform_Normalize(vtmp, true);
+    ftmp = _aimspeed * frametime;
+    vtmp.y = bound(-ftmp, vtmp.y, ftmp);
+    vtmp.x = bound(-ftmp, vtmp.x, ftmp);
+    _turrret.angles_y = bound(_rotlimit_min, _turrret.angles.y + vtmp.y, _rotlimit_max);
+    _turrret.angles_x = bound(_pichlimit_min, _turrret.angles.x + vtmp.x, _pichlimit_max);
+    return vtag;
+}
+
+void vehicles_gib_explode()
+{
+       sound (self, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTEN_NORM);
+       pointparticles(particleeffectnum("explosion_small"), randomvec() * 80 + (self.origin + '0 0 100'), '0 0 0', 1);
+       remove(self);
+}
+
+void vehicles_gib_think()
+{
+       self.alpha -= 0.1;
+       if(self.cnt >= time)
+               remove(self);
+       else
+               self.nextthink = time + 0.1;
+}
+
+entity vehicle_tossgib(entity _template, vector _vel, string _tag, float _burn, float _explode, float _maxtime, vector _rot)
+{
+       entity _gib = spawn();
+       setmodel(_gib, _template.model);
+       setorigin(_gib, gettaginfo(self, gettagindex(self, _tag)));
+       _gib.velocity = _vel;
+       _gib.movetype = MOVETYPE_TOSS;
+       _gib.solid = SOLID_CORPSE;
+       _gib.colormod = '-0.5 -0.5 -0.5';
+       _gib.effects = EF_LOWPRECISION;
+       _gib.avelocity = _rot;
+
+       if(_burn)
+               _gib.effects |= EF_FLAME;
+
+       if(_explode)
+       {
+               _gib.think = vehicles_gib_explode;
+               _gib.nextthink = time + random() * _explode;
+               _gib.touch = vehicles_gib_explode;
+       }
+       else
+       {
+               _gib.cnt = time + _maxtime;
+               _gib.think = vehicles_gib_think;
+               _gib.nextthink = time + _maxtime - 1;
+               _gib.alpha = 1;
+       }
+       return _gib;
+}
+
+/*
+vector predict_target(entity _targ, vector _from, float _shot_speed)
+{
+    float i;                // loop
+    float _distance;        // How far to target
+    float _impact_time;     // How long untill projectile impacts
+    vector _predict_pos;    // Predicted enemy location
+    vector _original_origin;// Where target is before predicted
+
+     _original_origin = real_origin(_targ); // Typicaly center of target BBOX
+
+    _predict_pos = _original_origin;
+    for(i = 0; i < 4; ++i)  // Loop a few times to increase prediction accuracy (increase loop count if accuracy is to low)
+    {
+        _distance = vlen(_predict_pos - _from); // Get distance to previos predicted location
+        _impact_time = _distance / _shot_speed; // Calculate impact time
+        _predict_pos = _original_origin + _targ.velocity * _impact_time; // Calculate new predicted location
+    }
+
+    return _predict_pos;
+}
+*/
diff --git a/qcsrc/server/vehicles/vehicle.qh b/qcsrc/server/vehicles/vehicle.qh
new file mode 100644 (file)
index 0000000..59d9ef7
--- /dev/null
@@ -0,0 +1,196 @@
+#ifndef VEHICLE_H
+#define VEHICLE_H
+
+#include "../_all.qh"
+
+#include "../antilag.qh"
+#include "../cl_player.qh"
+#include "../g_damage.qh"
+#include "../g_hook.qh"
+#include "../movelib.qh"
+
+#include "../bot/bot.qh"
+
+#include "../command/common.qh"
+
+#include "../tturrets/include/turrets_early.qh"
+
+#include "../weapons/tracing.qh"
+
+#include "../../common/deathtypes.qh"
+#include "../../common/stats.qh"
+
+#include "../../warpzonelib/anglestransform.qh"
+#include "../../warpzonelib/server.qh"
+
+entity vehicles_projectile(string _mzlfx, string _mzlsound,
+                           vector _org, vector _vel,
+                           float _dmg, float _radi, float _force,  float _size,
+                           float _deahtype, float _projtype, float _health,
+                           float _cull, float _clianim, entity _owner);
+
+vector vehicles_findgoodexit(vector prefer_spot);
+
+
+
+/** vehicles_locktarget
+
+    Generic target locking.
+
+    Figure out if what target is "locked" (if any), for missile tracking as such.
+
+    after calling, "if(self.lock_target != world && self.lock_strength == 1)" mean
+    you have a locked in target.
+
+    Exspects a crosshair_trace() or equivalent to be
+    dont before calling.
+
+**/
+.entity lock_target;
+.float  lock_strength;
+.float  lock_time;
+.float  lock_soundtime;
+
+void UpdateAuxiliaryXhair(entity own, vector loc, vector clr, int axh_id);
+
+vector vehicle_aimturret(entity _vehic, vector _target, entity _turrret, string _tagname,
+                         float _pichlimit_min, float _pichlimit_max,
+                         float _rotlimit_min, float _rotlimit_max, float _aimspeed);
+
+#define VEHICLE_UPDATE_PLAYER(ply,fld,vhname) \
+ply.vehicle_##fld = (self.vehicle_##fld / autocvar_g_vehicle_##vhname##_##fld) * 100
+
+void CSQCVehicleSetup(entity own, float vehicle_id);
+
+.float() PlayerPhysplug;
+
+float autocvar_g_vehicles_allow_bots = 0;
+
+void vehicles_touch();
+
+void vehicles_regen(float timer, .float regen_field, float field_max, float rpause, float regen, float delta_time, float _healthscale);
+
+float shortangle_f(float ang1, float ang2);
+float anglemods(float v);
+
+entity vehicle_tossgib(entity _template, vector _vel, string _tag, float _burn, float _explode, float _maxtime, vector _rot);
+
+void vehicles_impact(float _minspeed, float _speedfac, float _maxpain);
+
+void shieldhit_think();
+
+float vehicle_addplayerslot(    entity _owner,
+                                entity _slot,
+                                float _hud,
+                                string _hud_model,
+                                float() _framefunc,
+                                void(float) _exitfunc);
+
+.void() vehicle_impact;
+
+float vehicle_initialize(string  net_name,
+                         string  bodymodel,
+                         string  topmodel,
+                         string  hudmodel,
+                         string  toptag,
+                         string  hudtag,
+                         string  viewtag,
+                         float   vhud,
+                         vector  min_s,
+                         vector  max_s,
+                         float   nodrop,
+                         void(float _spawnflag)  spawnproc,
+                         float   _respawntime,
+                         float() physproc,
+                         void()  enterproc,
+                         void(float extflag) exitfunc,
+                         void() dieproc,
+                         void() thinkproc,
+                         float  use_csqc,
+                         float _max_health,
+                         float _max_shield);
+
+float  force_fromtag_normpower;
+
+void vehicles_painframe();
+
+void vehicles_locktarget(float incr, float decr, float _lock_time);
+
+vector vehicles_force_fromtag_maglev(string tag_name, float spring_length, float max_power);
+
+vector vehicles_force_fromtag_hover(string tag_name, float spring_length, float max_power);
+
+void vehicles_projectile_explode();
+
+#if VEHICLES_ENABLED
+
+.int vehicle_flags;
+const int VHF_ISVEHICLE     = 2;    /// Indicates vehicle
+const int VHF_HASSHIELD     = 4;    /// Vehicle has shileding
+const int VHF_SHIELDREGEN   = 8;    /// Vehicles shield regenerates
+const int VHF_HEALTHREGEN   = 16;   /// Vehicles health regenerates
+const int VHF_ENERGYREGEN   = 32;   /// Vehicles energy regenerates
+const int VHF_DEATHEJECT    = 64;   /// Vehicle ejects pilot upon fatal damage
+const int VHF_MOVE_GROUND   = 128;  /// Vehicle moves on gound
+const int VHF_MOVE_HOVER    = 256;  /// Vehicle hover close to gound
+const int VHF_MOVE_FLY      = 512;  /// Vehicle is airborn
+const int VHF_DMGSHAKE      = 1024; /// Add random velocity each frame if health < 50%
+const int VHF_DMGROLL       = 2048; /// Add random angles each frame if health < 50%
+const int VHF_DMGHEADROLL   = 4096; /// Add random head angles each frame if health < 50%
+const int VHF_MULTISLOT     = 8192; /// Vehicle has multiple player slots
+const int VHF_PLAYERSLOT    = 16384;    /// This ent is a player slot on a multi-person vehicle
+
+.entity gun1;
+.entity gun2;
+.entity gun3;
+.entity vehicle_shieldent;  /// Entity to disply the shild effect on damage
+.entity vehicle;
+.entity vehicle_viewport;
+.entity vehicle_hudmodel;
+.entity vehicle_controller;
+
+.entity gunner1;
+.entity gunner2;
+
+.float vehicle_health;      /// If self is player this is 0..100 indicating precentage of health left on vehicle. If self is vehile, this is the real health value.
+.float vehicle_energy;      /// If self is player this is 0..100 indicating precentage of energy left on vehicle. If self is vehile, this is the real energy value.
+.float vehicle_shield;      /// If self is player this is 0..100 indicating precentage of shield left on vehicle. If self is vehile, this is the real shield value.
+
+.float vehicle_ammo1;   /// If self is player this field's use depends on the individual vehile. If self is vehile, this is the real ammo1 value.
+.float vehicle_reload1; /// If self is player this field's use depends on the individual vehile. If self is vehile, this is the real reload1 value.
+.float vehicle_ammo2;   /// If self is player this field's use depends on the individual vehile. If self is vehile, this is the real ammo2 value.
+.float vehicle_reload2; /// If self is player this field's use depends on the individual vehile. If self is vehile, this is the real reload2 value.
+
+.float sound_nexttime;
+const float VOL_VEHICLEENGINE = 1;
+
+.float hud;
+.float dmg_time;
+.float  vehicle_respawntime;
+//.void() vehicle_spawn;
+
+void vehicles_exit(float eject);
+.void(float exit_flags) vehicle_exit;
+const float VHEF_NORMAL = 0;  /// User pressed exit key
+const float VHEF_EJECT  = 1;  /// User pressed exit key 3 times fast (not implemented) or vehile is dying
+const float VHEF_RELESE = 2;  /// Release ownership, client possibly allready dissconnected / went spec / changed team / used "kill" (not implemented)
+
+const float SVC_SETVIEWPORT   = 5;   // Net.Protocol 0x05
+const float SVC_SETVIEWANGLES = 10;  // Net.Protocol 0x0A
+const float SVC_UPDATEENTITY  = 128; // Net.Protocol 0x80
+
+.void() vehicle_enter;  /// Vehicles custom funciton to be executed when owner exit it
+.void() vehicle_die;    /// Vehicles custom function to be executed when vehile die
+const float VHSF_NORMAL = 0;
+const float VHSF_FACTORY = 2;
+.void(float _spawnflag) vehicle_spawn;  /// Vehicles custom fucntion to be efecuted when vehicle (re)spawns
+.float(float _imp) vehicles_impulse;
+.float vehicle_weapon2mode;
+
+#if VEHICLES_USE_ODE
+void(entity e, float physics_enabled) physics_enable = #540; // enable or disable physics on object
+void(entity e, vector force, vector force_pos) physics_addforce = #541; // apply a force from certain origin, length of force vector is power of force
+void(entity e, vector torque) physics_addtorque = #542; // add relative torque
+#endif  // VEHICLES_USE_ODE
+#endif  // VEHICLES_ENABLED
+#endif
diff --git a/qcsrc/server/vehicles/vehicles.qc b/qcsrc/server/vehicles/vehicles.qc
deleted file mode 100644 (file)
index 96d54e3..0000000
+++ /dev/null
@@ -1,1446 +0,0 @@
-float autocvar_g_vehicles_crush_dmg;
-float autocvar_g_vehicles_crush_force;
-float autocvar_g_vehicles_delayspawn;
-float autocvar_g_vehicles_delayspawn_jitter;
-
-float autocvar_g_vehicles_vortex_damagerate = 0.5;
-float autocvar_g_vehicles_machinegun_damagerate = 0.5;
-float autocvar_g_vehicles_rifle_damagerate = 0.75;
-float autocvar_g_vehicles_vaporizer_damagerate = 0.001;
-float autocvar_g_vehicles_tag_damagerate = 5;
-
-float autocvar_g_vehicles;
-
-void vehicles_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force);
-void vehicles_return();
-void vehicles_enter();
-void vehicles_touch();
-void vehicles_reset_colors();
-void vehicles_clearreturn();
-void vehicles_setreturn();
-
-
-/** AuxiliaryXhair*
-    Send additional points of interest to be drawn, to vehicle owner
-**/
-const float MAX_AXH = 4;
-.entity AuxiliaryXhair[MAX_AXH];
-
-float SendAuxiliaryXhair(entity to, float sf)
-{
-
-       WriteByte(MSG_ENTITY, ENT_CLIENT_AUXILIARYXHAIR);
-
-       WriteByte(MSG_ENTITY, self.cnt);
-
-       WriteCoord(MSG_ENTITY, self.origin.x);
-       WriteCoord(MSG_ENTITY, self.origin.y);
-       WriteCoord(MSG_ENTITY, self.origin.z);
-
-    WriteByte(MSG_ENTITY, rint(self.colormod.x * 255));
-    WriteByte(MSG_ENTITY, rint(self.colormod.y * 255));
-    WriteByte(MSG_ENTITY, rint(self.colormod.z * 255));
-
-    return true;
-}
-
-void UpdateAuxiliaryXhair(entity own, vector loc, vector clr, float axh_id)
-{
-    if (!IS_REAL_CLIENT(own))
-        return;
-
-    entity axh;
-
-    axh_id = bound(0, axh_id, MAX_AXH);
-    axh = own.(AuxiliaryXhair[axh_id]);
-
-    if(axh == world || wasfreed(axh))  // MADNESS? THIS IS QQQQCCCCCCCCC (wasfreed, why do you exsist?)
-    {
-        axh                     = spawn();
-        axh.cnt                 = axh_id;
-        axh.drawonlytoclient    = own;
-        axh.owner               = own;
-        Net_LinkEntity(axh, false, 0, SendAuxiliaryXhair);
-    }
-
-    setorigin(axh, loc);
-    axh.colormod            = clr;
-    axh.SendFlags           = 0x01;
-    own.(AuxiliaryXhair[axh_id]) = axh;
-}
-
-/*
-// SVC_TEMPENTITY based, horrible with even 50 ping. hm.
-// WriteByte(MSG_ONE, SVC_TEMPENTITY) uses reliable messagess, never use for thinsg that need continous updates.
-void SendAuxiliaryXhair2(entity own, vector loc, vector clr, float axh_id)
-{
-       msgexntity = own;
-
-       WriteByte(MSG_ONE, SVC_TEMPENTITY);
-       WriteByte(MSG_ONE, TE_CSQC_AUXILIARYXHAIR);
-
-       WriteByte(MSG_ONE, axh_id);
-
-       WriteCoord(MSG_ONE, loc_x);
-       WriteCoord(MSG_ONE, loc_y);
-       WriteCoord(MSG_ONE, loc_z);
-
-    WriteByte(MSG_ONE, rint(clr_x * 255));
-    WriteByte(MSG_ONE, rint(clr_y * 255));
-    WriteByte(MSG_ONE, rint(clr_z * 255));
-
-}
-*/
-// End AuxiliaryXhair
-
-/**
-    Notifies the client that he enterd a vehicle, and sends
-    realavent data.
-
-    only sends vehicle_id atm (wich is a HUD_* constant, ex. HUD_SPIDERBOT)
-**/
-void CSQCVehicleSetup(entity own, float vehicle_id)
-{
-    if (!IS_REAL_CLIENT(own))
-        return;
-
-       msg_entity = own;
-
-       WriteByte(MSG_ONE, SVC_TEMPENTITY);
-       WriteByte(MSG_ONE, TE_CSQC_VEHICLESETUP);
-       if(vehicle_id != 0)
-           WriteByte(MSG_ONE, vehicle_id);
-       else
-        WriteByte(MSG_ONE, 1 + own.vehicle.vehicle_weapon2mode + HUD_VEHICLE_LAST);
-}
-
-/** vehicles_locktarget
-
-    Generic target locking.
-
-    Figure out if what target is "locked" (if any), for missile tracking as such.
-
-    after calling, "if(self.lock_target != world && self.lock_strength == 1)" mean
-    you have a locked in target.
-
-    Exspects a crosshair_trace() or equivalent to be
-    dont before calling.
-
-**/
-.entity lock_target;
-.float  lock_strength;
-.float  lock_time;
-.float  lock_soundtime;
-const float    DAMAGE_TARGETDRONE = 10;
-
-vector targetdrone_getnewspot()
-{
-
-       vector spot;
-       float i;
-       for(i = 0; i < 100; ++i)
-       {
-               spot = self.origin + randomvec() * 1024;
-               tracebox(spot, self.mins, self.maxs, spot, MOVE_NORMAL, self);
-               if(trace_fraction == 1.0 && trace_startsolid == 0 && trace_allsolid == 0)
-                       return spot;
-       }
-       return self.origin;
-}
-
-#if 0
-void targetdrone_think();
-void targetdrone_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force);
-void targetdrone_renwe()
-{
-       self.think = targetdrone_think;
-       self.nextthink = time + 0.1;
-       setorigin(self, targetdrone_getnewspot());
-       self.health = 200;
-       self.takedamage = DAMAGE_TARGETDRONE;
-       self.event_damage = targetdrone_damage;
-       self.solid = SOLID_BBOX;
-       setmodel(self, "models/runematch/rune.mdl");
-       self.effects = EF_LOWPRECISION;
-       self.scale = 10;
-       self.movetype = MOVETYPE_BOUNCEMISSILE;
-       setsize(self, '-100 -100 -100', '100 100 100');
-
-}
-void targetdrone_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
-{
-       self.health -= damage;
-       if(self.health <= 0)
-       {
-               pointparticles(particleeffectnum("explosion_medium"), self.origin, '0 0 0', 1);
-
-               if(!self.cnt)
-                       remove(self);
-               else
-               {
-                       self.think = targetdrone_renwe;
-                       self.nextthink = time + 1 + random() * 2;
-                       self.solid = SOLID_NOT;
-                       setmodel(self, "");
-               }
-       }
-}
-entity targetdrone_getfear()
-{
-       entity fear;
-       float i;
-
-       for(i = 64; i <= 1024; i += 64)
-       {
-               fear = findradius(self.origin, i);
-               while(fear)
-               {
-                       if(fear.bot_dodge)
-                               return fear;
-
-                       fear = fear.chain;
-               }
-       }
-
-       return world;
-}
-void targetdrone_think()
-{
-       self.nextthink = time + 0.1;
-
-       if(self.wp00)
-       if(self.wp00.deadflag != DEAD_NO)
-               self.wp00 = targetdrone_getfear();
-
-       if(!self.wp00)
-               self.wp00 = targetdrone_getfear();
-
-       vector newdir;
-
-       if(self.wp00)
-               newdir = steerlib_push(self.wp00.origin) + randomvec() * 0.75;
-       else
-               newdir = randomvec() * 0.75;
-
-       newdir = newdir * 0.5 + normalize(self.velocity) * 0.5;
-
-       if(self.wp00)
-               self.velocity = normalize(newdir) * (500 + (1024 / min(vlen(self.wp00.origin - self.origin), 1024)) * 700);
-       else
-               self.velocity = normalize(newdir) * 750;
-
-       tracebox(self.origin, self.mins, self.maxs, self.origin + self.velocity * 2, MOVE_NORMAL, self);
-       if(trace_fraction != 1.0)
-               self.velocity = self.velocity * -1;
-
-       //normalize((normalize(self.velocity) * 0.5 + newdir * 0.5)) * 750;
-}
-
-void targetdrone_spawn(vector _where, float _autorenew)
-{
-       entity drone = spawn();
-       setorigin(drone, _where);
-       drone.think = targetdrone_renwe;
-       drone.nextthink = time + 0.1;
-       drone.cnt = _autorenew;
-}
-#endif
-
-void vehicles_locktarget(float incr, float decr, float _lock_time)
-{
-    if(self.lock_target && self.lock_target.deadflag != DEAD_NO)
-    {
-        self.lock_target    = world;
-        self.lock_strength  = 0;
-        self.lock_time      = 0;
-    }
-
-    if(self.lock_time > time)
-    {
-        if(self.lock_target)
-        if(self.lock_soundtime < time)
-        {
-            self.lock_soundtime = time + 0.5;
-            play2(self.owner, "vehicles/locked.wav");
-        }
-
-        return;
-    }
-
-    if(trace_ent != world)
-    {
-        if(teamplay && trace_ent.team == self.team)
-            trace_ent = world;
-
-        if(trace_ent.deadflag != DEAD_NO)
-            trace_ent = world;
-
-        if(!trace_ent.vehicle_flags & VHF_ISVEHICLE ||
-                               trace_ent.turrcaps_flags & TFL_TURRCAPS_ISTURRET ||
-                               trace_ent.takedamage == DAMAGE_TARGETDRONE)
-            trace_ent = world;
-    }
-
-    if(self.lock_target == world && trace_ent != world)
-        self.lock_target = trace_ent;
-
-    if(self.lock_target && trace_ent == self.lock_target)
-    {
-        if(self.lock_strength != 1 && self.lock_strength + incr >= 1)
-        {
-            play2(self.owner, "vehicles/lock.wav");
-            self.lock_soundtime = time + 0.8;
-        }
-        else if (self.lock_strength != 1 && self.lock_soundtime < time)
-        {
-            play2(self.owner, "vehicles/locking.wav");
-            self.lock_soundtime = time + 0.3;
-        }
-
-    }
-
-    // Have a locking target
-    // Trace hit current target
-    if(trace_ent == self.lock_target && trace_ent != world)
-    {
-        self.lock_strength = min(self.lock_strength + incr, 1);
-        if(self.lock_strength == 1)
-            self.lock_time = time + _lock_time;
-    }
-    else
-    {
-        if(trace_ent)
-            self.lock_strength = max(self.lock_strength - decr * 2, 0);
-        else
-            self.lock_strength = max(self.lock_strength - decr, 0);
-
-        if(self.lock_strength == 0)
-            self.lock_target = world;
-    }
-}
-
-#define VEHICLE_UPDATE_PLAYER(ply,fld,vhname) \
-ply.vehicle_##fld = (self.vehicle_##fld / autocvar_g_vehicle_##vhname##_##fld) * 100
-
-#define vehicles_sweap_collision(orig,vel,dt,acm,mult) \
-traceline(orig, orig + vel * dt, MOVE_NORMAL, self); \
-if(trace_fraction != 1) \
-    acm += normalize(self.origin - trace_endpos) * (vlen(vel) * mult)
-
-// Hover movement support
-float  force_fromtag_power;
-float  force_fromtag_normpower;
-vector force_fromtag_origin;
-vector vehicles_force_fromtag_hover(string tag_name, float spring_length, float max_power)
-{
-    force_fromtag_origin = gettaginfo(self, gettagindex(self, tag_name));
-    v_forward  = normalize(v_forward) * -1;
-    traceline(force_fromtag_origin, force_fromtag_origin - (v_forward  * spring_length), MOVE_NORMAL, self);
-
-    force_fromtag_power = (1 - trace_fraction) * max_power;
-    force_fromtag_normpower = force_fromtag_power / max_power;
-
-    return v_forward  * force_fromtag_power;
-}
-
-// Experimental hovermode wich uses attraction/repulstion from surface insted of gravity/repulsion
-// Can possibly be use to move abt any surface (inclusing walls/celings)
-vector vehicles_force_fromtag_maglev(string tag_name, float spring_length, float max_power)
-{
-
-    force_fromtag_origin = gettaginfo(self, gettagindex(self, tag_name));
-    v_forward  = normalize(v_forward) * -1;
-    traceline(force_fromtag_origin, force_fromtag_origin - (v_forward  * spring_length), MOVE_NORMAL, self);
-
-    // TODO - this may NOT be compatible with wall/celing movement, unhardcode 0.25 (engine count multiplier)
-    if(trace_fraction == 1.0)
-    {
-        force_fromtag_normpower = -0.25;
-        return '0 0 -200';
-    }
-
-    force_fromtag_power = ((1 - trace_fraction) - trace_fraction) * max_power;
-    force_fromtag_normpower = force_fromtag_power / max_power;
-
-    return v_forward  * force_fromtag_power;
-}
-
-// Generic vehile projectile system
-void vehicles_projectile_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
-{
-    // Ignore damage from oterh projectiles from my owner (dont mess up volly's)
-    if(inflictor.owner == self.owner)
-        return;
-
-    self.health -= damage;
-    self.velocity += force;
-    if(self.health < 1)
-    {
-        self.takedamage = DAMAGE_NO;
-        self.event_damage = func_null;
-        self.think = self.use;
-        self.nextthink = time;
-    }
-}
-
-void vehicles_projectile_explode()
-{
-    if(self.owner && other != world)
-    {
-        if(other == self.owner.vehicle)
-            return;
-
-        if(other == self.owner.vehicle.tur_head)
-            return;
-    }
-
-       PROJECTILE_TOUCH;
-
-       self.event_damage = func_null;
-    RadiusDamage (self, self.realowner, self.shot_dmg, 0, self.shot_radius, self, world, self.shot_force, self.totalfrags, other);
-
-    remove (self);
-}
-
-entity vehicles_projectile(string _mzlfx, string _mzlsound,
-                           vector _org, vector _vel,
-                           float _dmg, float _radi, float _force,  float _size,
-                           float _deahtype, float _projtype, float _health,
-                           float _cull, float _clianim, entity _owner)
-{
-    entity proj;
-
-    proj = spawn();
-
-    PROJECTILE_MAKETRIGGER(proj);
-    setorigin(proj, _org);
-
-    proj.shot_dmg         = _dmg;
-    proj.shot_radius      = _radi;
-    proj.shot_force       = _force;
-    proj.totalfrags       = _deahtype;
-    proj.solid            = SOLID_BBOX;
-    proj.movetype         = MOVETYPE_FLYMISSILE;
-    proj.flags            = FL_PROJECTILE;
-    proj.bot_dodge        = true;
-    proj.bot_dodgerating  = _dmg;
-    proj.velocity         = _vel;
-    proj.touch            = vehicles_projectile_explode;
-    proj.use              = vehicles_projectile_explode;
-    proj.owner            = self;
-    proj.realowner        = _owner;
-    proj.think            = SUB_Remove;
-    proj.nextthink        = time + 30;
-
-    if(_health)
-    {
-        proj.takedamage       = DAMAGE_AIM;
-        proj.event_damage     = vehicles_projectile_damage;
-        proj.health           = _health;
-    }
-    else
-        proj.flags           = FL_PROJECTILE | FL_NOTARGET;
-
-    if(_mzlsound)
-        sound (self, CH_WEAPON_A, _mzlsound, VOL_BASE, ATTEN_NORM);
-
-    if(_mzlfx)
-        pointparticles(particleeffectnum(_mzlfx), proj.origin, proj.velocity, 1);
-
-
-    setsize (proj, '-1 -1 -1' * _size, '1 1 1' * _size);
-
-    CSQCProjectile(proj, _clianim, _projtype, _cull);
-
-    return proj;
-}
-// End generic vehile projectile system
-
-void vehicles_reset()
-{
-       if(self.owner)
-       {
-               entity oldself = self;
-               self = self.owner;
-               vehicles_exit(VHEF_RELESE);
-               self = oldself;
-       }
-       self.alpha      = -1;
-       self.movetype   = MOVETYPE_NONE;
-       self.effects    = EF_NODRAW;
-       self.colormod  = '0 0 0';
-       self.avelocity = '0 0 0';
-       self.velocity  = '0 0 0';
-       self.event_damage = func_null;
-       self.solid = SOLID_NOT;
-       self.deadflag = DEAD_NO;
-
-       self.touch = func_null;
-       self.nextthink = 0;
-       vehicles_setreturn();
-}
-
-/** vehicles_spawn
-    Exetuted for all vehicles on (re)spawn.
-    Sets defaults for newly spawned units.
-**/
-void vehicles_spawn()
-{
-    dprint("Spawning vehicle: ", self.netname, "\n");
-
-    // De-own & reset
-    self.vehicle_hudmodel.viewmodelforclient = self;
-
-    self.owner              = world;
-    self.touch              = vehicles_touch;
-    self.event_damage       = vehicles_damage;
-    self.reset              = vehicles_reset;
-    self.iscreature         = true;
-    self.teleportable       = false; // no teleporting for vehicles, too buggy
-    self.damagedbycontents     = true;
-    self.movetype           = MOVETYPE_WALK;
-    self.solid              = SOLID_SLIDEBOX;
-    self.takedamage         = DAMAGE_AIM;
-       self.deadflag           = DEAD_NO;
-    self.bot_attack         = true;
-    self.flags              = FL_NOTARGET;
-    self.avelocity          = '0 0 0';
-    self.velocity           = '0 0 0';
-
-    // Reset locking
-    self.lock_strength      = 0;
-    self.lock_target        = world;
-    self.misc_bulletcounter = 0;
-
-    // Return to spawn
-    self.angles             = self.pos2;
-    setorigin(self, self.pos1 + '0 0 0');
-    // Show it
-    pointparticles(particleeffectnum("teleport"), self.origin + '0 0 64', '0 0 0', 1);
-
-    if(self.vehicle_controller)
-        self.team = self.vehicle_controller.team;
-
-    vehicles_reset_colors();
-    self.vehicle_spawn(VHSF_NORMAL);
-}
-
-// Better way of determening whats crushable needed! (fl_crushable?)
-float vehicles_crushable(entity e)
-{
-    if(IS_PLAYER(e))
-        return true;
-
-    if(e.flags & FL_MONSTER)
-        return true;
-
-    return false;
-}
-
-void vehicles_impact(float _minspeed, float _speedfac, float _maxpain)
-{
-    if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
-        return;
-
-    if(self.play_time < time)
-    {
-        float wc = vlen(self.velocity - self.oldvelocity);
-        //dprint("oldvel: ", vtos(self.oldvelocity), "\n");
-        //dprint("vel: ", vtos(self.velocity), "\n");
-        if(_minspeed < wc)
-        {
-            float take = min(_speedfac * wc, _maxpain);
-            Damage (self, world, world, take, DEATH_FALL, self.origin, '0 0 0');
-            self.play_time = time + 0.25;
-
-            //dprint("wc: ", ftos(wc), "\n");
-            //dprint("take: ", ftos(take), "\n");
-        }
-    }
-}
-
-.void() vehicle_impact;
-void vehicles_touch()
-{
-       if(MUTATOR_CALLHOOK(VehicleTouch))
-               return;
-
-    // Vehicle currently in use
-    if(self.owner)
-    {
-        if(other != world)
-        if(vehicles_crushable(other))
-        {
-            if(vlen(self.velocity) != 0)
-                Damage(other, self, self.owner, autocvar_g_vehicles_crush_dmg, DEATH_VH_CRUSH, '0 0 0', normalize(other.origin - self.origin) * autocvar_g_vehicles_crush_force);
-
-            return; // Dont do selfdamage when hitting "soft targets".
-        }
-
-        if(self.play_time < time)
-        if(self.vehicle_impact)
-            self.vehicle_impact();
-
-        return;
-    }
-
-    if (!IS_PLAYER(other))
-        return;
-
-    if(other.deadflag != DEAD_NO)
-        return;
-
-    if(other.vehicle != world)
-        return;
-
-    vehicles_enter();
-}
-float autocvar_g_vehicles_allow_bots = 0;
-void vehicles_enter()
-{
-   // Remove this when bots know how to use vehicles
-
-    if (IS_BOT_CLIENT(other))
-        if (autocvar_g_vehicles_allow_bots)
-            dprint("Bot enters vehicle\n"); // This is where we need to disconnect (some, all?) normal bot AI and hand over to vehicle's _aiframe()
-        else
-            return;
-
-    if(self.phase > time)
-        return;
-    if(other.frozen)
-        return;
-    if(other.vehicle)
-        return;
-    if(other.deadflag != DEAD_NO)
-        return;
-
-    if(teamplay)
-    if(self.team)
-    if(self.team != other.team)
-        return;
-
-    RemoveGrapplingHook(other);
-
-    self.vehicle_ammo1   = 0;
-    self.vehicle_ammo2   = 0;
-    self.vehicle_reload1 = 0;
-    self.vehicle_reload2 = 0;
-    self.vehicle_energy  = 0;
-
-    self.owner          = other;
-    self.switchweapon   = other.switchweapon;
-
-    // .viewmodelforclient works better.
-    //self.vehicle_hudmodel.drawonlytoclient = self.owner;
-
-    self.vehicle_hudmodel.viewmodelforclient = self.owner;
-
-    self.event_damage         = vehicles_damage;
-    self.nextthink            = 0;
-    self.owner.angles         = self.angles;
-    self.owner.takedamage     = DAMAGE_NO;
-    self.owner.solid          = SOLID_NOT;
-    self.owner.movetype       = MOVETYPE_NOCLIP;
-    self.owner.alpha          = -1;
-    self.owner.vehicle        = self;
-    self.owner.event_damage   = func_null;
-    self.owner.view_ofs       = '0 0 0';
-    self.colormap             = self.owner.colormap;
-    if(self.tur_head)
-        self.tur_head.colormap    = self.owner.colormap;
-
-    self.owner.hud            = self.hud;
-    self.owner.PlayerPhysplug = self.PlayerPhysplug;
-
-    self.owner.vehicle_ammo1    = self.vehicle_ammo1;
-    self.owner.vehicle_ammo2    = self.vehicle_ammo2;
-    self.owner.vehicle_reload1  = self.vehicle_reload1;
-    self.owner.vehicle_reload2  = self.vehicle_reload2;
-
-    // Cant do this, hides attached objects too.
-    //self.exteriormodeltoclient = self.owner;
-    //self.tur_head.exteriormodeltoclient = self.owner;
-
-    other.flags &= ~FL_ONGROUND;
-    self.flags  &= ~FL_ONGROUND;
-
-    self.team                 = self.owner.team;
-    self.flags               -= FL_NOTARGET;
-    self.monster_attack       = true;
-
-    if (IS_REAL_CLIENT(other))
-    {
-        msg_entity = other;
-        WriteByte (MSG_ONE, SVC_SETVIEWPORT);
-        WriteEntity(MSG_ONE, self.vehicle_viewport);
-
-        WriteByte (MSG_ONE, SVC_SETVIEWANGLES);
-        if(self.tur_head)
-        {
-            WriteAngle(MSG_ONE, self.tur_head.angles.x + self.angles.x); // tilt
-            WriteAngle(MSG_ONE, self.tur_head.angles.y + self.angles.y); // yaw
-            WriteAngle(MSG_ONE, 0);                                      // roll
-        }
-        else
-        {
-            WriteAngle(MSG_ONE,  self.angles.x * -1); // tilt
-            WriteAngle(MSG_ONE,  self.angles.y);      // yaw
-            WriteAngle(MSG_ONE,  0);                  // roll
-        }
-    }
-
-    vehicles_clearreturn();
-
-    CSQCVehicleSetup(self.owner, self.hud);
-
-    vh_player = other;
-    vh_vehicle = self;
-    MUTATOR_CALLHOOK(VehicleEnter);
-    other = vh_player;
-    self = vh_vehicle;
-
-    self.vehicle_enter();
-    antilag_clear(other);
-}
-
-/** vehicles_findgoodexit
-    Locates a valid location for the player to exit the vehicle.
-    Will first try prefer_spot, then up 100 random spots arround the vehicle
-    wich are in direct line of sight and empty enougth to hold a players bbox
-**/
-vector vehicles_findgoodexit(vector prefer_spot)
-{
-    //vector exitspot;
-    float mysize;
-
-    tracebox(self.origin + '0 0 32', PL_MIN, PL_MAX, prefer_spot, MOVE_NORMAL, self.owner);
-    if(trace_fraction == 1.0 && !trace_startsolid && !trace_allsolid)
-        return prefer_spot;
-
-    mysize = 1.5 * vlen(self.maxs - self.mins);
-    float i;
-    vector v, v2;
-    v2 = 0.5 * (self.absmin + self.absmax);
-    for(i = 0; i < 100; ++i)
-    {
-        v = randomvec();
-        v.z = 0;
-        v = v2 + normalize(v) * mysize;
-        tracebox(v2, PL_MIN, PL_MAX, v, MOVE_NORMAL, self.owner);
-        if(trace_fraction == 1.0 && !trace_startsolid && !trace_allsolid)
-            return v;
-    }
-
-    /*
-    exitspot = (self.origin + '0 0 48') + v_forward * mysize;
-    tracebox(self.origin + '0 0 32', PL_MIN, PL_MAX, exitspot, MOVE_NORMAL, self.owner);
-    if(trace_fraction == 1.0 && !trace_startsolid && !trace_allsolid)
-        return exitspot;
-
-    exitspot = (self.origin + '0 0 48') - v_forward * mysize;
-    tracebox(self.origin + '0 0 32', PL_MIN, PL_MAX, exitspot, MOVE_NORMAL, self.owner);
-    if(trace_fraction == 1.0 && !trace_startsolid && !trace_allsolid)
-        return exitspot;
-
-    exitspot = (self.origin + '0 0 48') + v_right * mysize;
-    tracebox(self.origin + '0 0 32', PL_MIN, PL_MAX, exitspot, MOVE_NORMAL, self.owner);
-    if(trace_fraction == 1.0 && !trace_startsolid && !trace_allsolid)
-        return exitspot;
-
-    exitspot = (self.origin + '0 0 48') - v_right * mysize;
-    tracebox(self.origin + '0 0 32', PL_MIN, PL_MAX, exitspot, MOVE_NORMAL, self.owner);
-    if(trace_fraction == 1.0 && !trace_startsolid && !trace_allsolid)
-        return exitspot;
-    */
-
-    return self.origin;
-}
-
-/** vehicles_exit
-    Standarrd vehicle release fucntion.
-    custom code goes in self.vehicle_exit
-**/
-float vehicles_exit_running;
-void vehicles_exit(float eject)
-{
-    entity _vehicle;
-    entity _player;
-    entity _oldself = self;
-
-    if(vehicles_exit_running)
-    {
-        dprint("^1vehicles_exit allready running! this is not good..\n");
-        return;
-    }
-
-    vehicles_exit_running = true;
-    if(IS_CLIENT(self))
-    {
-        _vehicle = self.vehicle;
-
-        if (_vehicle.vehicle_flags & VHF_PLAYERSLOT)
-        {
-            _vehicle.vehicle_exit(eject);
-            self = _oldself;
-            vehicles_exit_running = false;
-            return;
-        }
-    }
-    else
-        _vehicle = self;
-
-    _player = _vehicle.owner;
-
-    self = _vehicle;
-
-    if (_player)
-    {
-        if (IS_REAL_CLIENT(_player))
-        {
-            msg_entity = _player;
-            WriteByte (MSG_ONE, SVC_SETVIEWPORT);
-            WriteEntity( MSG_ONE, _player);
-
-            WriteByte (MSG_ONE, SVC_SETVIEWANGLES);
-            WriteAngle(MSG_ONE, 0);
-            WriteAngle(MSG_ONE, _vehicle.angles.y);
-            WriteAngle(MSG_ONE, 0);
-        }
-
-        setsize(_player, PL_MIN,PL_MAX);
-
-        _player.takedamage     = DAMAGE_AIM;
-        _player.solid          = SOLID_SLIDEBOX;
-        _player.movetype       = MOVETYPE_WALK;
-        _player.effects        &= ~EF_NODRAW;
-        _player.alpha          = 1;
-        _player.PlayerPhysplug = func_null;
-        _player.vehicle        = world;
-        _player.view_ofs       = PL_VIEW_OFS;
-        _player.event_damage   = PlayerDamage;
-        _player.hud            = HUD_NORMAL;
-        _player.switchweapon   = _vehicle.switchweapon;
-
-        CSQCVehicleSetup(_player, HUD_NORMAL);
-    }
-    _vehicle.flags |= FL_NOTARGET;
-
-    if(_vehicle.deadflag == DEAD_NO)
-        _vehicle.avelocity          = '0 0 0';
-
-    _vehicle.tur_head.nodrawtoclient             = world;
-
-    if(!teamplay)
-        _vehicle.team = 0;
-
-    vh_player = _player;
-    vh_vehicle = _vehicle;
-    MUTATOR_CALLHOOK(VehicleExit);
-    _player = vh_player;
-    _vehicle = vh_vehicle;
-
-    _vehicle.team = _vehicle.tur_head.team;
-
-    sound (_vehicle, CH_TRIGGER_SINGLE, "misc/null.wav", 1, ATTEN_NORM);
-    _vehicle.vehicle_hudmodel.viewmodelforclient = _vehicle;
-    _vehicle.phase = time + 1;
-    _vehicle.monster_attack = false;
-
-    _vehicle.vehicle_exit(eject);
-
-    vehicles_setreturn();
-    vehicles_reset_colors();
-    _vehicle.owner = world;
-    self = _oldself;
-
-    vehicles_exit_running = false;
-}
-
-
-void vehicles_regen(float timer, .float regen_field, float field_max, float rpause, float regen, float delta_time, float _healthscale)
-{
-    if(self.regen_field < field_max)
-    if(timer + rpause < time)
-    {
-        if(_healthscale)
-            regen = regen * (self.vehicle_health / self.tur_health);
-
-        self.regen_field = min(self.regen_field + regen * delta_time, field_max);
-
-        if(self.owner)
-            self.owner.regen_field = (self.regen_field / field_max) * 100;
-    }
-}
-
-void shieldhit_think()
-{
-    self.alpha -= 0.1;
-    if (self.alpha <= 0)
-    {
-        //setmodel(self, "");
-        self.alpha = -1;
-        self.effects |= EF_NODRAW;
-    }
-    else
-    {
-        self.nextthink = time + 0.1;
-    }
-}
-
-void vehicles_painframe()
-{
-    if(self.owner.vehicle_health <= 50)
-    if(self.pain_frame < time)
-    {
-        float _ftmp;
-        _ftmp = self.owner.vehicle_health / 50;
-        self.pain_frame = time + 0.1 + (random() * 0.5 * _ftmp);
-        pointparticles(particleeffectnum("smoke_small"), (self.origin + (randomvec() * 80)), '0 0 0', 1);
-
-        if(self.vehicle_flags & VHF_DMGSHAKE)
-            self.velocity += randomvec() * 30;
-
-        if(self.vehicle_flags & VHF_DMGROLL)
-            if(self.vehicle_flags & VHF_DMGHEADROLL)
-                self.tur_head.angles += randomvec();
-            else
-                self.angles += randomvec();
-
-    }
-}
-
-void vehicles_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
-{
-    self.dmg_time = time;
-
-       // WEAPONTODO
-    if(DEATH_ISWEAPON(deathtype, WEP_VORTEX))
-        damage *= autocvar_g_vehicles_vortex_damagerate;
-
-    if(DEATH_ISWEAPON(deathtype, WEP_MACHINEGUN))
-        damage *= autocvar_g_vehicles_machinegun_damagerate;
-
-    if(DEATH_ISWEAPON(deathtype, WEP_RIFLE))
-        damage *= autocvar_g_vehicles_rifle_damagerate;
-
-    if(DEATH_ISWEAPON(deathtype, WEP_VAPORIZER))
-        damage *= autocvar_g_vehicles_vaporizer_damagerate;
-
-    if(DEATH_ISWEAPON(deathtype, WEP_SEEKER))
-        damage *= autocvar_g_vehicles_tag_damagerate;
-
-    self.enemy = attacker;
-
-    if((self.vehicle_flags & VHF_HASSHIELD) && (self.vehicle_shield > 0))
-    {
-        if (wasfreed(self.vehicle_shieldent) || self.vehicle_shieldent == world)
-        {
-            self.vehicle_shieldent = spawn();
-            self.vehicle_shieldent.effects = EF_LOWPRECISION;
-
-            setmodel(self.vehicle_shieldent, "models/vhshield.md3");
-            setattachment(self.vehicle_shieldent, self, "");
-            setorigin(self.vehicle_shieldent, real_origin(self) - self.origin);
-            self.vehicle_shieldent.scale       = 256 / vlen(self.maxs - self.mins);
-            self.vehicle_shieldent.think       = shieldhit_think;
-        }
-
-        self.vehicle_shieldent.colormod    = '1 1 1';
-        self.vehicle_shieldent.alpha       = 0.45;
-        self.vehicle_shieldent.angles      = vectoangles(normalize(hitloc - (self.origin + self.vehicle_shieldent.origin))) - self.angles;
-        self.vehicle_shieldent.nextthink   = time;
-        self.vehicle_shieldent.effects &= ~EF_NODRAW;
-
-        self.vehicle_shield -= damage;
-
-        if(self.vehicle_shield < 0)
-        {
-            self.vehicle_health            -= fabs(self.vehicle_shield);
-            self.vehicle_shieldent.colormod = '2 0 0';
-            self.vehicle_shield             = 0;
-            self.vehicle_shieldent.alpha    = 0.75;
-
-               if(sound_allowed(MSG_BROADCAST, attacker))
-                spamsound (self, CH_PAIN, "onslaught/ons_hit2.wav", VOL_BASE, ATTEN_NORM);   // FIXME: PLACEHOLDER
-        }
-        else
-               if(sound_allowed(MSG_BROADCAST, attacker))
-                spamsound (self, CH_PAIN, "onslaught/electricity_explode.wav", VOL_BASE, ATTEN_NORM);  // FIXME: PLACEHOLDER
-
-    }
-    else
-    {
-        self.vehicle_health -= damage;
-
-        if(sound_allowed(MSG_BROADCAST, attacker))
-            spamsound (self, CH_PAIN, "onslaught/ons_hit2.wav", VOL_BASE, ATTEN_NORM);  // FIXME: PLACEHOLDER
-    }
-
-       if(self.damageforcescale < 1 && self.damageforcescale > 0)
-               self.velocity += force * self.damageforcescale;
-       else
-               self.velocity += force;
-
-    if(self.vehicle_health <= 0)
-    {
-        if(self.owner)
-            if(self.vehicle_flags & VHF_DEATHEJECT)
-                vehicles_exit(VHEF_EJECT);
-            else
-                vehicles_exit(VHEF_RELESE);
-
-
-        antilag_clear(self);
-
-        self.vehicle_die();
-        vehicles_setreturn();
-    }
-}
-
-void vehicles_clearreturn()
-{
-    entity ret;
-    // Remove "return helper", if any.
-    ret = findchain(classname, "vehicle_return");
-    while(ret)
-    {
-        if(ret.wp00 == self)
-        {
-            ret.classname   = "";
-            ret.think       = SUB_Remove;
-            ret.nextthink   = time + 0.1;
-
-            if(ret.waypointsprite_attached)
-                WaypointSprite_Kill(ret.waypointsprite_attached);
-
-            return;
-        }
-        ret = ret.chain;
-    }
-}
-
-void vehicles_return()
-{
-    pointparticles(particleeffectnum("teleport"), self.wp00.origin + '0 0 64', '0 0 0', 1);
-
-    self.wp00.think     = vehicles_spawn;
-    self.wp00.nextthink = time;
-
-    if(self.waypointsprite_attached)
-        WaypointSprite_Kill(self.waypointsprite_attached);
-
-    remove(self);
-}
-
-void vehicles_showwp_goaway()
-{
-    if(self.waypointsprite_attached)
-        WaypointSprite_Kill(self.waypointsprite_attached);
-
-    remove(self);
-
-}
-
-void vehicles_showwp()
-{
-    entity oldself = world;
-    vector rgb;
-
-    if(self.cnt)
-    {
-        self.think      = vehicles_return;
-        self.nextthink  = self.cnt;
-    }
-    else
-    {
-        self.think      = vehicles_return;
-        self.nextthink  = time +1;
-
-        oldself = self;
-        self = spawn();
-        setmodel(self, "null");
-        self.team = oldself.wp00.team;
-        self.wp00 = oldself.wp00;
-        setorigin(self, oldself.wp00.pos1);
-
-        self.nextthink = time + 5;
-        self.think = vehicles_showwp_goaway;
-    }
-
-    if(teamplay && self.team)
-           rgb = Team_ColorRGB(self.team);
-    else
-           rgb = '1 1 1';
-    WaypointSprite_Spawn("vehicle", 0, 0, self, '0 0 64', world, 0, self, waypointsprite_attached, true, RADARICON_POWERUP, rgb);
-    if(self.waypointsprite_attached)
-    {
-        WaypointSprite_UpdateRule(self.waypointsprite_attached, self.wp00.team, SPRITERULE_DEFAULT);
-        if(oldself == world)
-            WaypointSprite_UpdateBuildFinished(self.waypointsprite_attached, self.nextthink);
-        WaypointSprite_Ping(self.waypointsprite_attached);
-    }
-
-    if(oldself != world)
-        self = oldself;
-}
-
-void vehicles_setreturn()
-{
-    entity ret;
-
-    vehicles_clearreturn();
-
-    ret = spawn();
-    ret.classname   = "vehicle_return";
-    ret.wp00       = self;
-    ret.team        = self.team;
-    ret.think       = vehicles_showwp;
-
-       if(self.deadflag != DEAD_NO)
-       {
-               ret.cnt = max(game_starttime, time) + self.vehicle_respawntime;
-               ret.nextthink = max(game_starttime, time) + max(0, self.vehicle_respawntime - 5);
-       }
-       else
-               ret.nextthink = max(game_starttime, time) + max(0, self.vehicle_respawntime - 1);
-
-    setmodel(ret, "null");
-    setorigin(ret, self.pos1 + '0 0 96');
-}
-
-void vehicles_reset_colors()
-{
-    entity e;
-    float _effects = 0, _colormap;
-    vector _glowmod, _colormod;
-
-    if(autocvar_g_nodepthtestplayers)
-        _effects |= EF_NODEPTHTEST;
-
-    if(autocvar_g_fullbrightplayers)
-        _effects |= EF_FULLBRIGHT;
-
-    if(self.team)
-        _colormap = 1024 + (self.team - 1) * 17;
-    else
-        _colormap = 1024;
-
-    _glowmod  = '0 0 0';
-    _colormod = '0 0 0';
-
-    // Find all ents attacked to main model and setup effects, colormod etc.
-    e = findchainentity(tag_entity, self);
-    while(e)
-    {
-        if(e != self.vehicle_shieldent)
-        {
-            e.effects   = _effects; //  | EF_LOWPRECISION;
-            e.colormod  = _colormod;
-            e.colormap  = _colormap;
-            e.alpha     = 1;
-        }
-        e = e.chain;
-    }
-
-    self.vehicle_hudmodel.effects  = self.effects  = _effects; // | EF_LOWPRECISION;
-    self.vehicle_hudmodel.colormod = self.colormod = _colormod;
-    self.vehicle_hudmodel.colormap = self.colormap = _colormap;
-    self.vehicle_viewport.effects = (EF_ADDITIVE | EF_DOUBLESIDED | EF_FULLBRIGHT | EF_NODEPTHTEST | EF_NOGUNBOB | EF_NOSHADOW | EF_LOWPRECISION | EF_SELECTABLE | EF_TELEPORT_BIT);
-
-    self.alpha     = 1;
-    self.avelocity = '0 0 0';
-    self.velocity  = '0 0 0';
-    self.effects   = _effects;
-}
-
-void vehicle_use()
-{
-    dprint("vehicle ",self.netname, " used by ", activator.classname, "\n");
-
-    self.tur_head.team = activator.team;
-
-    if(self.tur_head.team == 0)
-        self.active = ACTIVE_NOT;
-    else
-        self.active = ACTIVE_ACTIVE;
-
-    if(self.active == ACTIVE_ACTIVE && self.deadflag == DEAD_NO)
-    {
-        dprint("^3Eat shit yall!\n");
-        vehicles_setreturn();
-        vehicles_reset_colors();
-    }
-    else if(self.active == ACTIVE_NOT && self.deadflag != DEAD_NO)
-    {
-
-    }
-}
-
-float vehicle_addplayerslot(    entity _owner,
-                                entity _slot,
-                                float _hud,
-                                string _hud_model,
-                                float() _framefunc,
-                                void(float) _exitfunc)
-{
-    if (!(_owner.vehicle_flags & VHF_MULTISLOT))
-        _owner.vehicle_flags |= VHF_MULTISLOT;
-
-    _slot.PlayerPhysplug = _framefunc;
-    _slot.vehicle_exit = _exitfunc;
-    _slot.hud = _hud;
-    _slot.vehicle_flags = VHF_PLAYERSLOT;
-    _slot.vehicle_viewport = spawn();
-    _slot.vehicle_hudmodel = spawn();
-    _slot.vehicle_hudmodel.viewmodelforclient = _slot;
-    _slot.vehicle_viewport.effects = (EF_ADDITIVE | EF_DOUBLESIDED | EF_FULLBRIGHT | EF_NODEPTHTEST | EF_NOGUNBOB | EF_NOSHADOW | EF_LOWPRECISION | EF_SELECTABLE | EF_TELEPORT_BIT);
-
-    setmodel(_slot.vehicle_hudmodel, _hud_model);
-    setmodel(_slot.vehicle_viewport, "null");
-
-    setattachment(_slot.vehicle_hudmodel, _slot, "");
-    setattachment(_slot.vehicle_viewport, _slot.vehicle_hudmodel, "");
-
-    return true;
-}
-
-float vehicle_initialize(string  net_name,
-                         string  bodymodel,
-                         string  topmodel,
-                         string  hudmodel,
-                         string  toptag,
-                         string  hudtag,
-                         string  viewtag,
-                         float   vhud,
-                         vector  min_s,
-                         vector  max_s,
-                         float   nodrop,
-                         void(float _spawnflag)  spawnproc,
-                         float   _respawntime,
-                         float() physproc,
-                         void()  enterproc,
-                         void(float extflag) exitfunc,
-                         void() dieproc,
-                         void() thinkproc,
-                         float  use_csqc,
-                         float _max_health,
-                         float _max_shield)
-{
-       if(!autocvar_g_vehicles)
-               return false;
-
-    if(self.targetname)
-    {
-        self.vehicle_controller = find(world, target, self.targetname);
-        if(!self.vehicle_controller)
-        {
-            bprint("^1WARNING: ^7Vehicle with invalid .targetname\n");
-        }
-        else
-        {
-            self.team = self.vehicle_controller.team;
-            self.use = vehicle_use;
-
-            if(teamplay)
-            {
-                if(self.vehicle_controller.team == 0)
-                    self.active = ACTIVE_NOT;
-                else
-                    self.active = ACTIVE_ACTIVE;
-            }
-        }
-    }
-
-    precache_sound("onslaught/ons_hit2.wav");
-    precache_sound("onslaught/electricity_explode.wav");
-
-
-    addstat(STAT_HUD, AS_INT,  hud);
-       addstat(STAT_VEHICLESTAT_HEALTH,  AS_INT, vehicle_health);
-       addstat(STAT_VEHICLESTAT_SHIELD,  AS_INT, vehicle_shield);
-       addstat(STAT_VEHICLESTAT_ENERGY,  AS_INT, vehicle_energy);
-
-       addstat(STAT_VEHICLESTAT_AMMO1,   AS_INT, vehicle_ammo1);
-       addstat(STAT_VEHICLESTAT_RELOAD1, AS_INT, vehicle_reload1);
-
-       addstat(STAT_VEHICLESTAT_AMMO2,   AS_INT, vehicle_ammo2);
-       addstat(STAT_VEHICLESTAT_RELOAD2, AS_INT, vehicle_reload2);
-
-    if(bodymodel == "")
-        error("vehicles: missing bodymodel!");
-
-    if(hudmodel == "")
-        error("vehicles: missing hudmodel!");
-
-    if(net_name == "")
-        self.netname = self.classname;
-    else
-        self.netname = net_name;
-
-    if(self.team && !teamplay)
-        self.team = 0;
-
-    self.vehicle_flags |= VHF_ISVEHICLE;
-
-    setmodel(self, bodymodel);
-
-    self.vehicle_viewport   = spawn();
-    self.vehicle_hudmodel   = spawn();
-    self.tur_head           = spawn();
-    self.tur_head.owner     = self;
-    self.takedamage         = DAMAGE_AIM;
-    self.bot_attack         = true;
-    self.iscreature         = true;
-    self.teleportable       = false; // no teleporting for vehicles, too buggy
-    self.damagedbycontents     = true;
-    self.hud                = vhud;
-    self.tur_health          = _max_health;
-    self.tur_head.tur_health = _max_shield;
-    self.vehicle_die         = dieproc;
-    self.vehicle_exit        = exitfunc;
-    self.vehicle_enter       = enterproc;
-    self.PlayerPhysplug      = physproc;
-    self.event_damage        = func_null;
-    self.touch               = vehicles_touch;
-    self.think               = vehicles_spawn;
-    self.vehicle_spawn       = spawnproc;
-       self.vehicle_respawntime = max(0, _respawntime);
-    self.effects             = EF_NODRAW;
-       self.dphitcontentsmask   = DPCONTENTS_BODY | DPCONTENTS_SOLID;
-       if(!autocvar_g_vehicles_delayspawn || !self.vehicle_respawntime)
-               self.nextthink = time;
-       else
-               self.nextthink = max(time, game_starttime) + max(0, self.vehicle_respawntime + ((random() * 2 - 1) * autocvar_g_vehicles_delayspawn_jitter));
-
-       if(autocvar_g_playerclip_collisions)
-               self.dphitcontentsmask |= DPCONTENTS_PLAYERCLIP;
-
-    if(autocvar_g_nodepthtestplayers)
-        self.effects = self.effects | EF_NODEPTHTEST;
-
-    if(autocvar_g_fullbrightplayers)
-        self.effects = self.effects | EF_FULLBRIGHT;
-
-    setmodel(self.vehicle_hudmodel, hudmodel);
-    setmodel(self.vehicle_viewport, "null");
-
-    if(topmodel != "")
-    {
-        setmodel(self.tur_head, topmodel);
-        setattachment(self.tur_head, self, toptag);
-        setattachment(self.vehicle_hudmodel, self.tur_head, hudtag);
-        setattachment(self.vehicle_viewport, self.vehicle_hudmodel, viewtag);
-    }
-    else
-    {
-        setattachment(self.tur_head, self, "");
-        setattachment(self.vehicle_hudmodel, self, hudtag);
-        setattachment(self.vehicle_viewport, self.vehicle_hudmodel, viewtag);
-    }
-
-    setsize(self, min_s, max_s);
-    if (!nodrop)
-    {
-        setorigin(self, self.origin);
-        tracebox(self.origin + '0 0 100', min_s, max_s, self.origin - '0 0 10000', MOVE_WORLDONLY, self);
-        setorigin(self, trace_endpos);
-    }
-
-    self.pos1 = self.origin;
-    self.pos2 = self.angles;
-    self.tur_head.team = self.team;
-
-       if(MUTATOR_CALLHOOK(VehicleSpawn))
-               return false;
-
-    return true;
-}
-
-vector vehicle_aimturret(entity _vehic, vector _target, entity _turrret, string _tagname,
-                         float _pichlimit_min, float _pichlimit_max,
-                         float _rotlimit_min, float _rotlimit_max, float _aimspeed)
-{
-    vector vtmp, vtag;
-    float ftmp;
-    vtag = gettaginfo(_turrret, gettagindex(_turrret, _tagname));
-    vtmp = vectoangles(normalize(_target - vtag));
-    vtmp = AnglesTransform_ToAngles(AnglesTransform_LeftDivide(AnglesTransform_FromAngles(_vehic.angles), AnglesTransform_FromAngles(vtmp))) - _turrret.angles;
-    vtmp = AnglesTransform_Normalize(vtmp, true);
-    ftmp = _aimspeed * frametime;
-    vtmp.y = bound(-ftmp, vtmp.y, ftmp);
-    vtmp.x = bound(-ftmp, vtmp.x, ftmp);
-    _turrret.angles_y = bound(_rotlimit_min, _turrret.angles.y + vtmp.y, _rotlimit_max);
-    _turrret.angles_x = bound(_pichlimit_min, _turrret.angles.x + vtmp.x, _pichlimit_max);
-    return vtag;
-}
-
-void vehicles_gib_explode()
-{
-       sound (self, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTEN_NORM);
-       pointparticles(particleeffectnum("explosion_small"), randomvec() * 80 + (self.origin + '0 0 100'), '0 0 0', 1);
-       remove(self);
-}
-
-void vehicles_gib_think()
-{
-       self.alpha -= 0.1;
-       if(self.cnt >= time)
-               remove(self);
-       else
-               self.nextthink = time + 0.1;
-}
-
-entity vehicle_tossgib(entity _template, vector _vel, string _tag, float _burn, float _explode, float _maxtime, vector _rot)
-{
-       entity _gib = spawn();
-       setmodel(_gib, _template.model);
-       setorigin(_gib, gettaginfo(self, gettagindex(self, _tag)));
-       _gib.velocity = _vel;
-       _gib.movetype = MOVETYPE_TOSS;
-       _gib.solid = SOLID_CORPSE;
-       _gib.colormod = '-0.5 -0.5 -0.5';
-       _gib.effects = EF_LOWPRECISION;
-       _gib.avelocity = _rot;
-
-       if(_burn)
-               _gib.effects |= EF_FLAME;
-
-       if(_explode)
-       {
-               _gib.think = vehicles_gib_explode;
-               _gib.nextthink = time + random() * _explode;
-               _gib.touch = vehicles_gib_explode;
-       }
-       else
-       {
-               _gib.cnt = time + _maxtime;
-               _gib.think = vehicles_gib_think;
-               _gib.nextthink = time + _maxtime - 1;
-               _gib.alpha = 1;
-       }
-       return _gib;
-}
-
-/*
-vector predict_target(entity _targ, vector _from, float _shot_speed)
-{
-    float i;                // loop
-    float _distance;        // How far to target
-    float _impact_time;     // How long untill projectile impacts
-    vector _predict_pos;    // Predicted enemy location
-    vector _original_origin;// Where target is before predicted
-
-     _original_origin = real_origin(_targ); // Typicaly center of target BBOX
-
-    _predict_pos = _original_origin;
-    for(i = 0; i < 4; ++i)  // Loop a few times to increase prediction accuracy (increase loop count if accuracy is to low)
-    {
-        _distance = vlen(_predict_pos - _from); // Get distance to previos predicted location
-        _impact_time = _distance / _shot_speed; // Calculate impact time
-        _predict_pos = _original_origin + _targ.velocity * _impact_time; // Calculate new predicted location
-    }
-
-    return _predict_pos;
-}
-*/
diff --git a/qcsrc/server/vehicles/vehicles.qh b/qcsrc/server/vehicles/vehicles.qh
deleted file mode 100644 (file)
index e6b9760..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-#ifndef VEHICLES_H
-#define VEHICLES_H
-
-#ifdef VEHICLES_ENABLED
-#include "vehicles.qc"
-
-#include "racer.qc"
-#include "spiderbot.qc"
-#include "raptor.qc"
-#ifndef VEHICLES_NO_UNSTABLE
-#include "bumblebee.qc"
-#endif
-#endif
-#endif
diff --git a/qcsrc/server/vehicles/vehicles_def.qh b/qcsrc/server/vehicles/vehicles_def.qh
deleted file mode 100644 (file)
index 080f891..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-#ifndef VEHICLES_DEF_H
-#define VEHICLES_DEF_H
-
-#include "../tturrets/include/turrets_early.qh"
-
-// #define VEHICLES_USE_ODE
-#define VEHICLES_ENABLED
-#ifdef VEHICLES_ENABLED
-
-.int vehicle_flags;
-const int VHF_ISVEHICLE     = 2;    /// Indicates vehicle
-const int VHF_HASSHIELD     = 4;    /// Vehicle has shileding
-const int VHF_SHIELDREGEN   = 8;    /// Vehicles shield regenerates
-const int VHF_HEALTHREGEN   = 16;   /// Vehicles health regenerates
-const int VHF_ENERGYREGEN   = 32;   /// Vehicles energy regenerates
-const int VHF_DEATHEJECT    = 64;   /// Vehicle ejects pilot upon fatal damage
-const int VHF_MOVE_GROUND   = 128;  /// Vehicle moves on gound
-const int VHF_MOVE_HOVER    = 256;  /// Vehicle hover close to gound
-const int VHF_MOVE_FLY      = 512;  /// Vehicle is airborn
-const int VHF_DMGSHAKE      = 1024; /// Add random velocity each frame if health < 50%
-const int VHF_DMGROLL       = 2048; /// Add random angles each frame if health < 50%
-const int VHF_DMGHEADROLL   = 4096; /// Add random head angles each frame if health < 50%
-const int VHF_MULTISLOT     = 8192; /// Vehicle has multiple player slots
-const int VHF_PLAYERSLOT    = 16384;    /// This ent is a player slot on a multi-person vehicle
-
-.entity gun1;
-.entity gun2;
-.entity gun3;
-.entity vehicle_shieldent;  /// Entity to disply the shild effect on damage
-.entity vehicle;
-.entity vehicle_viewport;
-.entity vehicle_hudmodel;
-.entity vehicle_controller;
-
-.entity gunner1;
-.entity gunner2;
-
-.float vehicle_health;      /// If self is player this is 0..100 indicating precentage of health left on vehicle. If self is vehile, this is the real health value.
-.float vehicle_energy;      /// If self is player this is 0..100 indicating precentage of energy left on vehicle. If self is vehile, this is the real energy value.
-.float vehicle_shield;      /// If self is player this is 0..100 indicating precentage of shield left on vehicle. If self is vehile, this is the real shield value.
-
-.float vehicle_ammo1;   /// If self is player this field's use depends on the individual vehile. If self is vehile, this is the real ammo1 value.
-.float vehicle_reload1; /// If self is player this field's use depends on the individual vehile. If self is vehile, this is the real reload1 value.
-.float vehicle_ammo2;   /// If self is player this field's use depends on the individual vehile. If self is vehile, this is the real ammo2 value.
-.float vehicle_reload2; /// If self is player this field's use depends on the individual vehile. If self is vehile, this is the real reload2 value.
-
-.float sound_nexttime;
-const float VOL_VEHICLEENGINE = 1;
-
-.float hud;
-.float dmg_time;
-.float  vehicle_respawntime;
-//.void() vehicle_spawn;
-
-void vehicles_exit(float eject);
-.void(float exit_flags) vehicle_exit;
-const float VHEF_NORMAL = 0;  /// User pressed exit key
-const float VHEF_EJECT  = 1;  /// User pressed exit key 3 times fast (not implemented) or vehile is dying
-const float VHEF_RELESE = 2;  /// Release ownership, client possibly allready dissconnected / went spec / changed team / used "kill" (not implemented)
-
-const float SVC_SETVIEWPORT   = 5;   // Net.Protocol 0x05
-const float SVC_SETVIEWANGLES = 10;  // Net.Protocol 0x0A
-const float SVC_UPDATEENTITY  = 128; // Net.Protocol 0x80
-
-.void() vehicle_enter;  /// Vehicles custom funciton to be executed when owner exit it
-.void() vehicle_die;    /// Vehicles custom function to be executed when vehile die
-const float VHSF_NORMAL = 0;
-const float VHSF_FACTORY = 2;
-.void(float _spawnflag) vehicle_spawn;  /// Vehicles custom fucntion to be efecuted when vehicle (re)spawns
-.float(float _imp) vehicles_impulse;
-.float vehicle_weapon2mode = volly_counter;
-
-#ifdef VEHICLES_USE_ODE
-void(entity e, float physics_enabled) physics_enable = #540; // enable or disable physics on object
-void(entity e, vector force, vector force_pos) physics_addforce = #541; // apply a force from certain origin, length of force vector is power of force
-void(entity e, vector torque) physics_addtorque = #542; // add relative torque
-#endif  // VEHICLES_USE_ODE
-#endif  // VEHICLES_ENABLED
-#endif
index 02ebdec920562847fb780067d94da3a9c36267df..d7b637d0ce03fcefaabe35d6fbce6a6441b3d997 100644 (file)
@@ -374,11 +374,11 @@ entity WaypointSprite_Spawn(
        wp.team = t;
        wp.owner = own;
        wp.currentammo = hideable;
-       if(own)
+       if (own)
        {
-               if(own.ownfield)
-                       remove(own.ownfield);
-               own.ownfield = wp;
+               if (own.(ownfield))
+                       remove(own.(ownfield));
+               own.(ownfield) = wp;
                wp.owned_by_field = ownfield;
        }
        wp.fade_rate = maxdistance;
index 2557d10d1599d1a3eec2a32457387b4f84048841..1ef81a409eaae283ed2a456deb748a7d851e24eb 100644 (file)
@@ -1,17 +1,11 @@
-#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/weapons/weapons.qh"
-    #include "accuracy.qh"
-    #include "../autocvars.qh"
-    #include "../constants.qh"
-    #include "../defs.qh"
-    #include "../mutators/mutators_include.qh"
-#endif
+#include "accuracy.qh"
+#include "../_all.qh"
+
+#include "../mutators/mutators_include.qh"
+#include "../../common/constants.qh"
+#include "../../common/teams.qh"
+#include "../../common/util.qh"
+#include "../../common/weapons/all.qh"
 
 float accuracy_byte(float n, float d)
 {
index c37fce0ab878a2af37b1963a4c42f1cef229398e..cf49b54f8b0b169e5702d4e0a010a64af51e6fc5 100644 (file)
@@ -1,17 +1,12 @@
-#if defined(CSQC)
-#elif defined(MENUQC)
-#elif defined(SVQC)
-       #include "../../dpdefs/progsdefs.qh"
-    #include "../../common/constants.qh"
-    #include "../../common/util.qh"
-    #include "../../common/weapons/weapons.qh"
-    #include "common.qh"
-    #include "../t_items.qh"
-    #include "../autocvars.qh"
-    #include "../defs.qh"
-    #include "../../common/notifications.qh"
-    #include "../../common/deathtypes.qh"
-#endif
+#include "common.qh"
+#include "../_all.qh"
+
+#include "../t_items.qh"
+#include "../../common/constants.qh"
+#include "../../common/deathtypes.qh"
+#include "../../common/notifications.qh"
+#include "../../common/util.qh"
+#include "../../common/weapons/all.qh"
 
 void W_GiveWeapon (entity e, float wep)
 {
@@ -43,7 +38,7 @@ void W_PlayStrengthSound(entity player) // void W_PlayStrengthSound
                player.prevstrengthsoundattempt = time;
 }
 
-float W_CheckProjectileDamage(entity inflictor, entity projowner, float deathtype, float exception)
+float W_CheckProjectileDamage(entity inflictor, entity projowner, int deathtype, float exception)
 {
        float is_from_contents = (deathtype == DEATH_SLIME || deathtype == DEATH_LAVA);
        float is_from_owner = (inflictor == projowner);
index 341f4ff354b44816b7079be2007da282c01fb441..b97457ad99697c017846226b10730a3466e0c6f2 100644 (file)
@@ -5,6 +5,6 @@ void W_GiveWeapon (entity e, float wep);
 .float prevstrengthsound;
 .float prevstrengthsoundattempt;
 void W_PlayStrengthSound(entity player);
-float W_CheckProjectileDamage(entity inflictor, entity projowner, float deathtype, float exception);
+float W_CheckProjectileDamage(entity inflictor, entity projowner, int deathtype, float exception);
 void W_PrepareExplosionByDamage(entity attacker, void() explode);
 #endif
index 773b7f085bea4e9c275501429895d251d176fca6..507fc4a413b792d6d5450d3591c6442c6d438036 100644 (file)
@@ -1,19 +1,16 @@
-#if defined(CSQC)
-#elif defined(MENUQC)
-#elif defined(SVQC)
-       #include "../../dpdefs/progsdefs.qh"
-    #include "../../common/constants.qh"
-    #include "../../common/weapons/weapons.qh"
-    #include "csqcprojectile.qh"
-    #include "../t_items.qh"
-    #include "../constants.qh"
-    #include "../defs.qh"
-    #include "../command/common.qh"
-#endif
+#include "csqcprojectile.qh"
+#include "../_all.qh"
+
+#include "../t_items.qh"
+
+#include "../command/common.qh"
+
+#include "../../common/constants.qh"
+#include "../../common/weapons/all.qh"
 
 .float csqcprojectile_type;
 
-float CSQCProjectile_SendEntity(entity to, int sf)
+bool CSQCProjectile_SendEntity(entity to, int sf)
 {
        float ft, fr;
 
@@ -68,7 +65,7 @@ float CSQCProjectile_SendEntity(entity to, int sf)
        if(sf & 2)
                WriteByte(MSG_ENTITY, self.csqcprojectile_type); // TODO maybe put this into sf?
 
-       return 1;
+       return true;
 }
 
 .vector csqcprojectile_oldorigin;
index ec1004cd1dfc2c57d24545332853b7e030954499..0564bdc76243dcb9674e1ac209957fa8b8f7838c 100644 (file)
@@ -1,14 +1,8 @@
-#if defined(CSQC)
-#elif defined(MENUQC)
-#elif defined(SVQC)
-       #include "../../dpdefs/progsdefs.qh"
-    #include "../../dpdefs/dpextensions.qh"
-    #include "../../common/weapons/weapons.qh"
-    #include "hitplot.qh"
-    #include "../autocvars.qh"
-    #include "../defs.qh"
-    #include "../antilag.qh"
-#endif
+#include "hitplot.qh"
+#include "../_all.qh"
+
+#include "../antilag.qh"
+#include "../../common/weapons/all.qh"
 
 vector W_HitPlotUnnormalizedUntransform(vector screenforward, vector screenright, vector screenup, vector v)
 {
index 5ea0a5d9d842c8690cdf979cd7a9c717e5439477..89c4253a13f125d6a0e4c0d97aa6920de1c2a9db 100644 (file)
@@ -1,17 +1,12 @@
-#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/weapons/weapons.qh"
-    #include "selection.qh"
-    #include "weaponsystem.qh"
-    #include "../t_items.qh"
-    #include "../autocvars.qh"
-    #include "../defs.qh"
-#endif
+#include "selection.qh"
+#include "../_all.qh"
+
+#include "weaponsystem.qh"
+#include "../t_items.qh"
+#include "../waypointsprites.qh"
+#include "../../common/constants.qh"
+#include "../../common/util.qh"
+#include "../../common/weapons/all.qh"
 
 // switch between weapons
 void Send_WeaponComplain(entity e, float wpn, float type)
index ea62fcf19eba9c05d08169e827357b879ef3ba9a..9096b2f9c72d9ff3e54063ec33a1d0be7cbcd0bb 100644 (file)
@@ -1,17 +1,10 @@
-#if defined(CSQC)
-#elif defined(MENUQC)
-#elif defined(SVQC)
-       #include "../../dpdefs/progsdefs.qh"
-    #include "../../dpdefs/dpextensions.qh"
-    #include "../../common/weapons/weapons.qh"
-    #include "spawning.qh"
-    #include "weaponsystem.qh"
-    #include "../t_items.qh"
-    #include "../autocvars.qh"
-    #include "../constants.qh"
-    #include "../defs.qh"
-    #include "../mutators/mutators_include.qh"
-#endif
+#include "spawning.qh"
+#include "../_all.qh"
+
+#include "weaponsystem.qh"
+#include "../mutators/mutators_include.qh"
+#include "../t_items.qh"
+#include "../../common/weapons/all.qh"
 
 string W_Apply_Weaponreplace(string in)
 {
index 6b47a88227fb65a344588de7a96a3459e5e76c73..d14bcfd1cfdec2d48aacdef8a572f0af9b0b0dd8 100644 (file)
@@ -1,20 +1,14 @@
-#if defined(CSQC)
-#elif defined(MENUQC)
-#elif defined(SVQC)
-       #include "../../dpdefs/progsdefs.qh"
-    #include "../../dpdefs/dpextensions.qh"
-    #include "../../common/util.qh"
-    #include "../../common/weapons/weapons.qh"
-    #include "throwing.qh"
-    #include "weaponsystem.qh"
-    #include "../t_items.qh"
-    #include "../autocvars.qh"
-    #include "../constants.qh"
-    #include "../defs.qh"
-    #include "../../common/notifications.qh"
-    #include "../mutators/mutators_include.qh"
-    #include "../../common/mapinfo.qh"
-#endif
+#include "throwing.qh"
+#include "../_all.qh"
+
+#include "weaponsystem.qh"
+#include "../mutators/mutators_include.qh"
+#include "../t_items.qh"
+#include "../g_damage.qh"
+#include "../../common/mapinfo.qh"
+#include "../../common/notifications.qh"
+#include "../../common/util.qh"
+#include "../../common/weapons/all.qh"
 
 void thrown_wep_think()
 {
@@ -40,7 +34,7 @@ string W_ThrowNewWeapon(entity own, float wpn, float doreduce, vector org, vecto
        entity oldself, wep;
        float thisammo, i;
        string s;
-       var .float ammotype = (get_weaponinfo(wpn)).ammo_field;
+       var .int ammotype = (get_weaponinfo(wpn)).ammo_field;
 
        wep = spawn();
 
@@ -107,24 +101,24 @@ string W_ThrowNewWeapon(entity own, float wpn, float doreduce, vector org, vecto
                        // if our weapon is loaded, give its load back to the player
                        if(self.(weapon_load[self.weapon]) > 0)
                        {
-                               own.ammotype += self.(weapon_load[self.weapon]);
+                               own.(ammotype) += self.(weapon_load[self.weapon]);
                                self.(weapon_load[self.weapon]) = -1; // schedule the weapon for reloading
                        }
 
-                       wep.ammotype = 0;
+                       wep.(ammotype) = 0;
                }
                else if(doreduce)
                {
                        // if our weapon is loaded, give its load back to the player
                        if(self.(weapon_load[self.weapon]) > 0)
                        {
-                               own.ammotype += self.(weapon_load[self.weapon]);
+                               own.(ammotype) += self.(weapon_load[self.weapon]);
                                self.(weapon_load[self.weapon]) = -1; // schedule the weapon for reloading
                        }
 
-                       thisammo = min(own.ammotype, wep.ammotype);
-                       wep.ammotype = thisammo;
-                       own.ammotype -= thisammo;
+                       thisammo = min(own.(ammotype), wep.(ammotype));
+                       wep.(ammotype) = thisammo;
+                       own.(ammotype) -= thisammo;
 
                        switch(ammotype)
                        {
index 1f0c363b1aec364723c8f535800b5fbf03d07d6f..98cbb2ba872a10794dc057693612c108163ec23e 100644 (file)
@@ -1,17 +1,20 @@
-#if defined(CSQC)
-#elif defined(MENUQC)
-#elif defined(SVQC)
-       #include "../../dpdefs/progsdefs.qh"
-    #include "../../dpdefs/dpextensions.qh"
-    #include "../../warpzonelib/common.qh"
-    #include "../../common/constants.qh"
-    #include "../../common/util.qh"
-    #include "../../common/weapons/weapons.qh"
-    #include "tracing.qh"
-    #include "../autocvars.qh"
-    #include "../defs.qh"
-    #include "../antilag.qh"
-#endif
+#include "tracing.qh"
+#include "../_all.qh"
+
+#include "accuracy.qh"
+#include "common.qh"
+#include "hitplot.qh"
+
+#include "../g_damage.qh"
+#include "../g_subs.qh"
+#include "../antilag.qh"
+
+#include "../../common/constants.qh"
+#include "../../common/util.qh"
+
+#include "../../common/weapons/all.qh"
+
+#include "../../warpzonelib/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.
@@ -190,7 +193,7 @@ void W_SetupProjVelocity_Explicit(entity proj, vector dir, vector upDir, float p
 //  Ballistics Tracing
 // ====================
 
-void FireRailgunBullet (vector start, vector end, float bdamage, float bforce, float mindist, float maxdist, float halflifedist, float forcehalflifedist, float deathtype)
+void FireRailgunBullet (vector start, vector end, float bdamage, float bforce, float mindist, float maxdist, float halflifedist, float forcehalflifedist, int deathtype)
 {
        vector hitloc, force, endpoint, dir;
        entity ent, endent;
index 1cab448cb087da8bd89bff9243cd6aebdcf78f37..b2ab7d08222d64b81be935e746e31fab99844766 100644 (file)
@@ -50,7 +50,7 @@ void W_SetupProjVelocity_Explicit(entity proj, vector dir, vector upDir, float p
 
 .float railgundistance;
 .vector railgunforce;
-void FireRailgunBullet (vector start, vector end, float bdamage, float bforce, float mindist, float maxdist, float halflifedist, float forcehalflifedist, float deathtype);
+void FireRailgunBullet (vector start, vector end, float bdamage, float bforce, float mindist, float maxdist, float halflifedist, float forcehalflifedist, int deathtype);
 
 float fireBullet_trace_callback_eff;
 entity fireBullet_last_hit;
index 64fdc5bb30faddb767064c406780ec6758dcdd13..a84969904a300fbe57bbeba78039b967141eea25 100644 (file)
@@ -1,14 +1,10 @@
-#if defined(CSQC)
-#elif defined(MENUQC)
-#elif defined(SVQC)
-       #include "../../dpdefs/progsdefs.qh"
-       #include "../../dpdefs/dpextensions.qh"
-       #include "../../common/urllib.qh"
-       #include "../../common/weapons/weapons.qh"
-       #include "weaponstats.qh"
-       #include "../autocvars.qh"
-       #include "../defs.qh"
-#endif
+#include "weaponstats.qh"
+#include "../_all.qh"
+
+#include "../g_world.qh"
+
+#include "../../common/urllib.qh"
+#include "../../common/weapons/all.qh"
 
 void WeaponStats_Init()
 {
index 72ec7f53926dfd2d7c92cc1bf661af64185fc5c0..4f072c4c085bb7e829c6355da495a14c0ad33888 100644 (file)
@@ -1,23 +1,19 @@
-#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 "../../common/monsters/monsters.qh"
-    #include "../../common/weapons/weapons.qh"
-    #include "weaponsystem.qh"
-    #include "../t_items.qh"
-    #include "../autocvars.qh"
-    #include "../defs.qh"
-    #include "../../common/notifications.qh"
-    #include "../mutators/mutators_include.qh"
-    #include "../command/common.qh"
-    #include "../../csqcmodellib/sv_model.qh"
-    #include "../round_handler.qh"
-#endif
+#include "weaponsystem.qh"
+#include "../_all.qh"
+
+#include "selection.qh"
+
+#include "../command/common.qh"
+#include "../mutators/mutators_include.qh"
+#include "../round_handler.qh"
+#include "../t_items.qh"
+#include "../../common/animdecide.qh"
+#include "../../common/constants.qh"
+#include "../../common/monsters/all.qh"
+#include "../../common/notifications.qh"
+#include "../../common/util.qh"
+#include "../../common/weapons/all.qh"
+#include "../../csqcmodellib/sv_model.qh"
 
 /*
 ===========================================================================
diff --git a/qcsrc/test/compilationunit.sh b/qcsrc/test/compilationunit.sh
new file mode 100755 (executable)
index 0000000..e4f3878
--- /dev/null
@@ -0,0 +1,33 @@
+#!/bin/bash
+set -eu
+cd "$(dirname "$0")"
+cd ..
+
+declare -a NOWARN=(
+  '-Wno-field-redeclared'
+  '-Wno-unused-variable'
+  '-Wno-implicit-function-pointer'
+)
+declare -a FEATURES=(
+  '-DVEHICLES_ENABLED=1'
+  '-DVEHICLES_USE_ODE=0'
+)
+declare QCC=../../../gmqcc/gmqcc
+
+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
+    echo "$file"
+    ${QCC} -std=gmqcc -fftepp -fftepp-predefs -Werror -Wall "${NOWARN[@]}" "${FEATURES[@]}" -futf8 -O3 "${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[@]
index e8a455b6ee25548bf67e22c68c15fd3e1626089d..079ceaa7d1a5577a4e5326b873da4788842430b0 100644 (file)
@@ -1,11 +1,11 @@
+#include "anglestransform.qh"
+
 #if defined(CSQC)
        #include "../dpdefs/csprogsdefs.qh"
-       #include "anglestransform.qh"
 #elif defined(MENUQC)
 #elif defined(SVQC)
        #include "../dpdefs/progsdefs.qh"
     #include "../dpdefs/dpextensions.qh"
-    #include "anglestransform.qh"
 #endif
 
 #ifdef POSITIVE_PITCH_IS_DOWN
index 5c2609a7dfbd388d8cb1b1172974b74fd8dbbd5a..e0bb6434584efb034b554b9985febc3ff39a8280 100644 (file)
@@ -1,9 +1,10 @@
+#include "client.qh"
+#include "common.qh"
+
 #if defined(CSQC)
-       #include "../dpdefs/csprogsdefs.qh"
-       #include "common.qh"
-       #include "client.qh"
        #include "../client/autocvars.qh"
        #include "../csqcmodellib/cl_model.qh"
+       #include "../dpdefs/csprogsdefs.qh"
 #elif defined(MENUQC)
 #elif defined(SVQC)
 #endif
index aa0de911963a9bc700e6aa3167b2181633d7b7b6..706acde4448aef1d6bad8eb039570cbecabc6129 100644 (file)
@@ -1,13 +1,13 @@
+#include "common.qh"
+
 #if defined(CSQC)
        #include "../dpdefs/csprogsdefs.qh"
-    #include "common.qh"
     #include "../server/t_items.qh"
 #elif defined(MENUQC)
 #elif defined(SVQC)
-       #include "../dpdefs/progsdefs.qh"
+    #include "../common/weapons/all.qh"
     #include "../dpdefs/dpextensions.qh"
-    #include "common.qh"
-    #include "../common/weapons/weapons.qh"
+       #include "../dpdefs/progsdefs.qh"
 #endif
 
 void WarpZone_Accumulator_Clear(entity acc)
@@ -573,6 +573,45 @@ vector WarpZoneLib_NearestPointOnBox(vector mi, vector ma, vector org)
        return nearest;
 }
 
+float WarpZoneLib_BadClassname(string myclassname)
+{
+       switch(myclassname)
+       {
+               case "weapon_info":
+               case "monster_info":
+               case "deathtype":
+               case "callback":
+               case "callbackchain":
+               case "weaponentity":
+               case "exteriorweaponentity":
+               case "csqc_score_team":
+               case "pingplreport":
+               case "ent_client_scoreinfo":
+               case "saved_cvar_value":
+               case "accuracy":
+               case "entcs_sender_v2":
+               case "entcs_receiver_v2":
+               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)
@@ -591,6 +630,8 @@ void WarpZone_FindRadius_Recurse(vector org, float rad,        vector org0,
 
        for(e = e0; e; e = e.chain)
        {
+               if(WarpZoneLib_BadClassname(e.classname))
+                       continue;
                p = WarpZoneLib_NearestPointOnBox(e.origin + e.mins, e.origin + e.maxs, org0);
                if(needlineofsight)
                {
@@ -626,6 +667,9 @@ void WarpZone_FindRadius_Recurse(vector org, float rad,        vector org0,
        }
        for(e = wz; e; e = e.WarpZone_findradius_next)
        {
+               if(WarpZoneLib_BadClassname(e.classname))
+                       continue;
+
                org0_new = WarpZone_TransformOrigin(e, org);
                traceline(e.warpzone_targetorigin, org0_new, MOVE_NOMONSTERS, e);
                org_new = trace_endpos;
@@ -772,3 +816,64 @@ entity WarpZone_RefSys_SpawnSameRefSys(entity me)
        WarpZone_RefSys_Copy(e, me);
        return e;
 }
+
+float WarpZoneLib_ExactTrigger_Touch()
+{
+       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;
+}
index 7742db8b9b101f54968503b3f5e238f993120faf..3e2b7c7c63eacae9b1dfd93c4dfc55feb77bef3c 100644 (file)
@@ -104,4 +104,13 @@ entity WarpZone_RefSys_SpawnSameRefSys(entity me); // spawn().R = me.R
 #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
index e61318d6fb5db0914d80c7377dcefd25fb473e1b..f61712d2322dc8436b7bd0675ee1a32103f87ba1 100644 (file)
@@ -1,11 +1,10 @@
+#include "mathlib.qh"
 #if defined(CSQC)
        #include "../dpdefs/csprogsdefs.qh"
-    #include "mathlib.qh"
 #elif defined(MENUQC)
 #elif defined(SVQC)
-       #include "../dpdefs/progsdefs.qh"
     #include "../dpdefs/dpextensions.qh"
-    #include "mathlib.qh"
+       #include "../dpdefs/progsdefs.qh"
 #endif
 
 int fpclassify(float x)
index 9e750f0a5e84ec2ff4f658c0266d2063e93b717d..6f7adf44f753c2d2ba5a9527b1b397d35fbca598 100644 (file)
@@ -105,7 +105,8 @@ 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 */
-const float M_PI       = 3.14159265358979323846;  /* pi */
+// -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 */
index c4dc7287f1c182e79ac96e009a8000902678043c..53d903902517cccf9eccc76f790c3a68ac5d25d6 100644 (file)
@@ -1,15 +1,17 @@
+#include "server.qh"
+
+#include "common.qh"
 #if defined(CSQC)
 #elif defined(MENUQC)
 #elif defined(SVQC)
-       #include "../dpdefs/progsdefs.qh"
-       #include "../dpdefs/dpextensions.qh"
-       #include "common.qh"
-       #include "server.qh"
        #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"
-       #include "../server/command/common.qh"
 #endif
 
 #ifdef WARPZONELIB_KEEPDEBUG
@@ -51,7 +53,7 @@ void WarpZone_TeleportPlayer(entity teleporter, entity player, vector to, vector
        WarpZone_PostTeleportPlayer_Callback(player);
 }
 
-float WarpZone_Teleported_Send(entity to, float sf)
+bool WarpZone_Teleported_Send(entity to, int sf)
 {
        WriteByte(MSG_ENTITY, ENT_CLIENT_WARPZONE_TELEPORTED);
        WriteCoord(MSG_ENTITY, self.angles.x);
@@ -216,7 +218,7 @@ void WarpZone_Touch (void)
        }
 }
 
-float WarpZone_Send(entity to, float sendflags)
+bool WarpZone_Send(entity to, int sendflags)
 {
        WriteByte(MSG_ENTITY, ENT_CLIENT_WARPZONE);
 
@@ -270,7 +272,7 @@ float WarpZone_Send(entity to, float sendflags)
        return true;
 }
 
-float WarpZone_Camera_Send(entity to, float sendflags)
+bool WarpZone_Camera_Send(entity to, int sendflags)
 {
        int f = 0;
        WriteByte(MSG_ENTITY, ENT_CLIENT_WARPZONE_CAMERA);
index b94eafbdafd4e422af7dd6eb5c31933156dbb988..0af6d3c0dcd44dacfb266a3f3ed9f400b0ee7bf4 100644 (file)
@@ -1,72 +1,15 @@
+#include "util_server.qh"
+
+#include "common.qh"
+
 #if defined(CSQC)
 #elif defined(MENUQC)
 #elif defined(SVQC)
-       #include "../dpdefs/progsdefs.qh"
-    #include "../dpdefs/dpextensions.qh"
-    #include "common.qh"
-    #include "util_server.qh"
     #include "../csqcmodellib/sv_model.qh"
+    #include "../dpdefs/dpextensions.qh"
+       #include "../dpdefs/progsdefs.qh"
 #endif
-
-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;
-}
-
-float WarpZoneLib_ExactTrigger_Touch()
-{
-       return !WarpZoneLib_BoxTouchesBrush(other.absmin, other.absmax, self, other);
-}
+#include "common.qh"
 
 void WarpZoneLib_ExactTrigger_Init()
 {
index 38df7fe0cc804f55c344a368046b4e5adb428fe3..0a42d7d12c67227417356d86403ae37c1718d3b3 100644 (file)
@@ -3,5 +3,7 @@
 
 float WarpZoneLib_MoveOutOfSolid(entity e);
 float WarpZoneLib_ExactTrigger_Touch();
+#ifdef SVQC
 void WarpZoneLib_ExactTrigger_Init();
 #endif
+#endif
index 503c23979284e6f796268c6dfbed02b885eec214..57fcfc8d423e363f0d2055e1fbfc2db4fc714d8c 100644 (file)
@@ -12,12 +12,14 @@ Zac "Mario" Jardine
 **Extended Team
 Antonio "terencehill" Piu
 Archer
+BuddyFriendGuy
 Debugger
 GATTS
 Halogene
 IDWMaster
 Jan "zykure" Behrens
 JH0nny
+Luigi
 Łukasz "kuniu the frogg" Polek
 Matthias "matthiaskrgr" Krüger
 Mattia "Melanosuchus" Basaglia
@@ -57,6 +59,7 @@ Sahil "DiaboliK" Singhal
 nifrek
 
 *Level Design
+Amadeusz "amade/proraide" Sławiński
 Ben "MooKow" Banker
 Calinou
 Cortez
@@ -64,6 +67,8 @@ Cuinn "Cuinnton" Herrick
 Debugger
 Jakob "tZork" Markström Gröhn
 Konrad "Justin" Slawinski
+Maddin
+L0
 Łukasz "kuniu the frogg" Polek
 Maik "SavageX" Merten
 Marvin "Mirio" Beck
@@ -73,8 +78,10 @@ Pearce "theShadow" Michal
 Rasmus "FruitieX" Eskola
 Ruszkai "CuBe0wL" Ákos
 Severin "sev" Meyer
+ShadoW
 
 *Music / Sound FX
+AquaNova (Archer)
 blkrbt
 chooksta
 Independent.nu
@@ -87,7 +94,6 @@ Saulo "mand1nga" Gil
 {SC0RP} - Ian "ID" Dorrell
 Stephan
 unfa
-AquaNova (Archer)
 
 *Game Code
 Samual "Ares" Lenks
@@ -124,15 +130,15 @@ Dale "graphitemaster" Weiler
 
 **Other Active Contributors
 Erik "Ablu" Schilling
-Jope "Sless" Withers
 Mircea "Taoki" Kitsune
-Robert "ai" Kuroto
+Penguinum
 
 
 **Translators
 
 *Asturian
 Llumex03
+Tornes "Tornes.Llume" Ḷḷume
 Ximielga
 
 *Belarusian
@@ -142,8 +148,14 @@ Mihail "meequz" Varantsou
 lokster
 set_killer
 
+*Chinese (China)
+Antonidas
+kalawore
+sapphireliu
+
 *Czech
 shogun assassin/woky
+Superovoce
 Tomáš "CZHeron" Volavka
 
 *Dutch
@@ -152,6 +164,7 @@ PinkRobot
 vegiburger
 
 *English (Australia)
+Laurene "sunflowers" Albrand
 Zac "Mario" Jardine
 
 *Finnish
@@ -173,7 +186,7 @@ Rudolf "divVerent" Polzer
 Yepoleb
 
 *Greek
-Γιάννης "Evropi" Α.
+Γιάννης "Evropi" Ανθυμίδης
 Konstantinos "LDinos" Mihalenas
 Savoritias
 Vindex
@@ -182,9 +195,6 @@ Vindex
 Ruszkai "CuBe0wL" Ákos
 xaN1C4n3
 
-*Japanese
-Lento
-
 *Italian
 Antonio "terencehill" Piu
 Felice "MaidenBeast" Sallustio
@@ -197,10 +207,11 @@ Alex "tiprogrammierer.alex" Progger
 Amadeusz "amade/proraide" Sławiński
 
 *Portuguese
-Ricardo "Hellgardia" Silva
+Ricardo Manuel "Hellgardia" da Cruz Coelho da Silva
 xXxCHAOTICxXx
 
 *Romanian
+Adrian-Ciprian "adrian.tinjala" Tînjală
 BusterDBK
 Mircea "Taoki" Kitsune
 Tudor "TropiKo" Ionel
@@ -218,7 +229,7 @@ Sergej "Clearness High" Lutsyk
 *Serbian
 Саша "salepetronije" Петровић
 Pendulla
-Ristovski
+Rafael "Ristovski"
 
 *Spanish
 0000simon
@@ -272,6 +283,7 @@ Henning "Tymo" Janssen
 Innovati
 Jitspoe
 Jody Gallagher
+Jope "Sless" Withers
 Juergen "LowDragon" Timm
 KadaverJack
 Kevin "Tyrann" Shanahan
@@ -305,6 +317,7 @@ Q1 Retexturing Project
 Qantourisc
 Oleh "BlaXpirit" Prypin
 Rick "Rat" Kelley
+Robert "ai" Kuroto
 Ronan
 Sajt
 Saulo "mand1nga" Gil