]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Merge branch 'master' into Mario/user_movetypes
authorMario <mario@smbclan.net>
Thu, 18 Aug 2016 15:06:52 +0000 (01:06 +1000)
committerMario <mario@smbclan.net>
Thu, 18 Aug 2016 15:06:52 +0000 (01:06 +1000)
597 files changed:
.gitlab-ci.yml
_hud_common.cfg
_hud_descriptions.cfg
defaultXonotic.cfg
hud_luma.cfg
hud_luminos.cfg
hud_luminos_minimal.cfg
hud_luminos_minimal_xhair.cfg
hud_luminos_old.cfg
hud_nexuiz.cfg
qcsrc/Doxyfile
qcsrc/client/_mod.inc
qcsrc/client/_mod.qh
qcsrc/client/announcer.qc
qcsrc/client/autocvars.qh
qcsrc/client/commands/cl_cmd.qc
qcsrc/client/commands/cl_cmd.qh
qcsrc/client/csqcmodel_hooks.qc
qcsrc/client/hud/all.inc
qcsrc/client/hud/hud.qc
qcsrc/client/hud/hud.qh
qcsrc/client/hud/hud_config.qc
qcsrc/client/hud/hud_config.qh
qcsrc/client/hud/panel/_mod.inc
qcsrc/client/hud/panel/_mod.qh
qcsrc/client/hud/panel/ammo.qc
qcsrc/client/hud/panel/centerprint.qc
qcsrc/client/hud/panel/healtharmor.qc
qcsrc/client/hud/panel/infomessages.qc
qcsrc/client/hud/panel/modicons.qc
qcsrc/client/hud/panel/powerups.qc
qcsrc/client/hud/panel/quickmenu.qc
qcsrc/client/hud/panel/score.qc
qcsrc/client/hud/panel/scoreboard.qc [new file with mode: 0644]
qcsrc/client/hud/panel/scoreboard.qh [new file with mode: 0644]
qcsrc/client/hud/panel/vote.qc
qcsrc/client/hud/panel/weapons.qc
qcsrc/client/main.qc
qcsrc/client/main.qh
qcsrc/client/mapvoting.qc
qcsrc/client/mapvoting.qh
qcsrc/client/player_skeleton.qc
qcsrc/client/scoreboard.qc [deleted file]
qcsrc/client/scoreboard.qh [deleted file]
qcsrc/client/view.qc
qcsrc/client/weapons/projectile.qc
qcsrc/common/anim.qh
qcsrc/common/animdecide.qh
qcsrc/common/campaign_common.qh
qcsrc/common/command/all.qh
qcsrc/common/command/command.qh
qcsrc/common/command/generic.qc
qcsrc/common/command/generic.qh
qcsrc/common/command/markup.qc
qcsrc/common/command/markup.qh
qcsrc/common/command/rpn.qh
qcsrc/common/constants.qh
qcsrc/common/csqcmodel_settings.qh
qcsrc/common/deathtypes/all.qh
qcsrc/common/effects/all.qc
qcsrc/common/effects/all.qh
qcsrc/common/effects/effect.qh
qcsrc/common/effects/effectinfo.qc
qcsrc/common/effects/qc/all.qh
qcsrc/common/effects/qc/casings.qc
qcsrc/common/effects/qc/damageeffects.qc
qcsrc/common/effects/qc/gibs.qc
qcsrc/common/effects/qc/globalsound.qc
qcsrc/common/effects/qc/globalsound.qh
qcsrc/common/effects/qc/modeleffects.qc
qcsrc/common/effects/qc/rubble.qh
qcsrc/common/ent_cs.qc
qcsrc/common/ent_cs.qh
qcsrc/common/gamemodes/gamemode/nexball/nexball.qc
qcsrc/common/gamemodes/gamemode/onslaught/cl_controlpoint.qc
qcsrc/common/gamemodes/gamemode/onslaught/cl_generator.qc
qcsrc/common/gamemodes/gamemode/onslaught/onslaught.qc
qcsrc/common/impulses/all.qh
qcsrc/common/items/all.qh
qcsrc/common/items/inventory.qh
qcsrc/common/items/item.qh
qcsrc/common/items/item/ammo.qh
qcsrc/common/items/item/armor.qh
qcsrc/common/items/item/health.qh
qcsrc/common/items/item/pickup.qh
qcsrc/common/items/item/powerup.qh
qcsrc/common/mapinfo.qc
qcsrc/common/mapinfo.qh
qcsrc/common/minigames/cl_minigames.qc
qcsrc/common/minigames/cl_minigames.qh
qcsrc/common/minigames/cl_minigames_hud.qc
qcsrc/common/minigames/cl_minigames_hud.qh
qcsrc/common/minigames/minigame/bd.qc
qcsrc/common/minigames/minigame/c4.qc
qcsrc/common/minigames/minigame/nmm.qc
qcsrc/common/minigames/minigame/pong.qc
qcsrc/common/minigames/minigame/pp.qc
qcsrc/common/minigames/minigame/ps.qc
qcsrc/common/minigames/minigame/snake.qc
qcsrc/common/minigames/minigame/ttt.qc
qcsrc/common/minigames/minigames.qh
qcsrc/common/minigames/sv_minigames.qc
qcsrc/common/minigames/sv_minigames.qh
qcsrc/common/models/all.qh
qcsrc/common/models/model.qh
qcsrc/common/monsters/all.qh
qcsrc/common/monsters/monster.qh
qcsrc/common/monsters/monster/mage.qc
qcsrc/common/monsters/monster/shambler.qc
qcsrc/common/monsters/monster/spider.qc
qcsrc/common/monsters/monster/wyvern.qc
qcsrc/common/monsters/spawn.qh
qcsrc/common/monsters/sv_monsters.qc
qcsrc/common/monsters/sv_monsters.qh
qcsrc/common/mutators/all.inc
qcsrc/common/mutators/base.qh
qcsrc/common/mutators/events.qh
qcsrc/common/mutators/mutator/buffs/all.qh
qcsrc/common/mutators/mutator/buffs/buffs.qc
qcsrc/common/mutators/mutator/bugrigs/bugrigs.qc
qcsrc/common/mutators/mutator/campcheck/campcheck.qc
qcsrc/common/mutators/mutator/damagetext/damagetext.qc
qcsrc/common/mutators/mutator/globalforces/_mod.inc [new file with mode: 0644]
qcsrc/common/mutators/mutator/globalforces/_mod.qh [new file with mode: 0644]
qcsrc/common/mutators/mutator/globalforces/globalforces.qc [new file with mode: 0644]
qcsrc/common/mutators/mutator/globalforces/module.inc [new file with mode: 0644]
qcsrc/common/mutators/mutator/instagib/instagib.qc
qcsrc/common/mutators/mutator/itemstime.qc
qcsrc/common/mutators/mutator/midair/midair.qc
qcsrc/common/mutators/mutator/multijump/multijump.qc
qcsrc/common/mutators/mutator/nades/nades.qc
qcsrc/common/mutators/mutator/nades/nades.qh
qcsrc/common/mutators/mutator/nades/net.qc
qcsrc/common/mutators/mutator/overkill/hmg.qc
qcsrc/common/mutators/mutator/overkill/overkill.qc
qcsrc/common/mutators/mutator/overkill/rpc.qc
qcsrc/common/mutators/mutator/physical_items/physical_items.qc
qcsrc/common/mutators/mutator/pinata/pinata.qc
qcsrc/common/mutators/mutator/random_gravity/random_gravity.qc
qcsrc/common/mutators/mutator/sandbox/sandbox.qc
qcsrc/common/mutators/mutator/superspec/superspec.qc
qcsrc/common/mutators/mutator/touchexplode/touchexplode.qc
qcsrc/common/mutators/mutator/waypoints/all.qh
qcsrc/common/mutators/mutator/waypoints/waypointsprites.qc
qcsrc/common/net_notice.qh
qcsrc/common/notifications/all.inc
qcsrc/common/notifications/all.qc
qcsrc/common/notifications/all.qh
qcsrc/common/physics/movelib.qh
qcsrc/common/physics/movetypes/movetypes.qc
qcsrc/common/physics/movetypes/movetypes.qh
qcsrc/common/physics/player.qc
qcsrc/common/physics/player.qh
qcsrc/common/playerstats.qc
qcsrc/common/playerstats.qh
qcsrc/common/sounds/all.qh
qcsrc/common/sounds/sound.qh
qcsrc/common/state.qc
qcsrc/common/state.qh
qcsrc/common/stats.qh
qcsrc/common/t_items.qc
qcsrc/common/t_items.qh
qcsrc/common/teams.qh
qcsrc/common/triggers/func/breakable.qc
qcsrc/common/triggers/func/breakable.qh
qcsrc/common/triggers/func/conveyor.qc
qcsrc/common/triggers/func/door.qc
qcsrc/common/triggers/func/include.qh
qcsrc/common/triggers/func/plat.qc
qcsrc/common/triggers/func/train.qc
qcsrc/common/triggers/include.qh
qcsrc/common/triggers/misc/follow.qc
qcsrc/common/triggers/platforms.qc
qcsrc/common/triggers/platforms.qh
qcsrc/common/triggers/subs.qc
qcsrc/common/triggers/subs.qh
qcsrc/common/triggers/target/include.qh
qcsrc/common/triggers/target/music.qc
qcsrc/common/triggers/target/music.qh
qcsrc/common/triggers/target/speaker.qc
qcsrc/common/triggers/teleporters.qh
qcsrc/common/triggers/trigger/gamestart.qc
qcsrc/common/triggers/trigger/gravity.qc
qcsrc/common/triggers/trigger/impulse.qc
qcsrc/common/triggers/trigger/impulse.qh
qcsrc/common/triggers/trigger/include.qh
qcsrc/common/triggers/trigger/jumppads.qc
qcsrc/common/triggers/trigger/jumppads.qh
qcsrc/common/triggers/trigger/keylock.qc
qcsrc/common/triggers/trigger/secret.qc
qcsrc/common/triggers/trigger/secret.qh
qcsrc/common/triggers/trigger/swamp.qc
qcsrc/common/triggers/trigger/swamp.qh
qcsrc/common/triggers/trigger/viewloc.qc
qcsrc/common/triggers/trigger/viewloc.qh
qcsrc/common/triggers/triggers.qc
qcsrc/common/triggers/triggers.qh
qcsrc/common/turrets/all.qh
qcsrc/common/turrets/checkpoint.qc
qcsrc/common/turrets/cl_turrets.qc
qcsrc/common/turrets/config.qh
qcsrc/common/turrets/sv_turrets.qc
qcsrc/common/turrets/sv_turrets.qh
qcsrc/common/turrets/targettrigger.qc
qcsrc/common/turrets/turret.qh
qcsrc/common/turrets/turret/ewheel.qc
qcsrc/common/turrets/turret/ewheel_weapon.qc
qcsrc/common/turrets/turret/flac.qc
qcsrc/common/turrets/turret/flac_weapon.qc
qcsrc/common/turrets/turret/fusionreactor.qc
qcsrc/common/turrets/turret/hellion.qc
qcsrc/common/turrets/turret/hellion_weapon.qc
qcsrc/common/turrets/turret/hk.qc
qcsrc/common/turrets/turret/hk_weapon.qc
qcsrc/common/turrets/turret/machinegun.qc
qcsrc/common/turrets/turret/machinegun_weapon.qc
qcsrc/common/turrets/turret/mlrs.qc
qcsrc/common/turrets/turret/mlrs_weapon.qc
qcsrc/common/turrets/turret/phaser.qc
qcsrc/common/turrets/turret/phaser_weapon.qc
qcsrc/common/turrets/turret/plasma.qc
qcsrc/common/turrets/turret/plasma_dual.qc
qcsrc/common/turrets/turret/plasma_weapon.qc
qcsrc/common/turrets/turret/tesla.qc
qcsrc/common/turrets/turret/tesla_weapon.qc
qcsrc/common/turrets/turret/walker.qc
qcsrc/common/turrets/turret/walker_weapon.qc
qcsrc/common/turrets/util.qc
qcsrc/common/turrets/util.qh
qcsrc/common/util.qc
qcsrc/common/util.qh
qcsrc/common/vehicles/all.qh
qcsrc/common/vehicles/cl_vehicles.qc
qcsrc/common/vehicles/cl_vehicles.qh
qcsrc/common/vehicles/sv_vehicles.qc
qcsrc/common/vehicles/sv_vehicles.qh
qcsrc/common/vehicles/vehicle.qh
qcsrc/common/vehicles/vehicle/bumblebee.qc
qcsrc/common/vehicles/vehicle/bumblebee.qh
qcsrc/common/vehicles/vehicle/racer.qc
qcsrc/common/vehicles/vehicle/racer_weapon.qc
qcsrc/common/vehicles/vehicle/raptor.qc
qcsrc/common/vehicles/vehicle/raptor.qh
qcsrc/common/vehicles/vehicle/raptor_weapons.qc
qcsrc/common/vehicles/vehicle/spiderbot.qc
qcsrc/common/viewloc.qc
qcsrc/common/viewloc.qh
qcsrc/common/weapons/all.qc
qcsrc/common/weapons/all.qh
qcsrc/common/weapons/calculations.qc
qcsrc/common/weapons/calculations.qh
qcsrc/common/weapons/config.qh
qcsrc/common/weapons/weapon.qh
qcsrc/common/weapons/weapon/arc.qc
qcsrc/common/weapons/weapon/blaster.qc
qcsrc/common/weapons/weapon/crylink.qc
qcsrc/common/weapons/weapon/devastator.qc
qcsrc/common/weapons/weapon/electro.qc
qcsrc/common/weapons/weapon/fireball.qc
qcsrc/common/weapons/weapon/hagar.qc
qcsrc/common/weapons/weapon/hlac.qc
qcsrc/common/weapons/weapon/hook.qc
qcsrc/common/weapons/weapon/machinegun.qc
qcsrc/common/weapons/weapon/minelayer.qc
qcsrc/common/weapons/weapon/mortar.qc
qcsrc/common/weapons/weapon/porto.qc
qcsrc/common/weapons/weapon/rifle.qc
qcsrc/common/weapons/weapon/seeker.qc
qcsrc/common/weapons/weapon/shockwave.qc
qcsrc/common/weapons/weapon/shotgun.qc
qcsrc/common/weapons/weapon/tuba.qc
qcsrc/common/weapons/weapon/vaporizer.qc
qcsrc/common/weapons/weapon/vortex.qc
qcsrc/dpdefs/csprogsdefs.qh
qcsrc/dpdefs/doc.md
qcsrc/dpdefs/dpextensions.qh
qcsrc/dpdefs/keycodes.qh
qcsrc/dpdefs/menudefs.qh
qcsrc/dpdefs/progsdefs.qh
qcsrc/ecs/README.md
qcsrc/ecs/_lib.inc
qcsrc/ecs/_lib.qh [new file with mode: 0644]
qcsrc/ecs/components/input.qh
qcsrc/ecs/components/physics.qh
qcsrc/ecs/events/_mod.inc
qcsrc/ecs/events/_mod.qh
qcsrc/ecs/events/physics.qc [new file with mode: 0644]
qcsrc/ecs/events/physics.qh [new file with mode: 0644]
qcsrc/ecs/systems/_mod.inc
qcsrc/ecs/systems/_mod.qh
qcsrc/ecs/systems/cl_physics.qc [new file with mode: 0644]
qcsrc/ecs/systems/input.qc [new file with mode: 0644]
qcsrc/ecs/systems/input.qh [new file with mode: 0644]
qcsrc/ecs/systems/physics.qc
qcsrc/ecs/systems/physics.qh
qcsrc/ecs/systems/sv_physics.qc [new file with mode: 0644]
qcsrc/lib/_all.inc
qcsrc/lib/arraylist.qh
qcsrc/lib/csqcmodel/cl_model.qc
qcsrc/lib/csqcmodel/cl_model.qh
qcsrc/lib/csqcmodel/cl_player.qc
qcsrc/lib/csqcmodel/cl_player.qh
qcsrc/lib/csqcmodel/common.qh
qcsrc/lib/csqcmodel/interpolate.qh
qcsrc/lib/csqcmodel/settings.qh
qcsrc/lib/csqcmodel/sv_model.qc
qcsrc/lib/csqcmodel/sv_model.qh
qcsrc/lib/defer.qh
qcsrc/lib/i18n.qh
qcsrc/lib/intrusivelist.qh
qcsrc/lib/iter.qh
qcsrc/lib/lazy.qh
qcsrc/lib/linkedlist.qh
qcsrc/lib/log.qh
qcsrc/lib/map.qh
qcsrc/lib/matrix/matrix.qc
qcsrc/lib/net.qh
qcsrc/lib/oo.qh
qcsrc/lib/p99.qh
qcsrc/lib/random.qc
qcsrc/lib/registry.qh
qcsrc/lib/spawnfunc.qh
qcsrc/lib/stats.qh
qcsrc/lib/test.qh
qcsrc/lib/urllib.qc
qcsrc/lib/vector.qh
qcsrc/lib/warpzone/anglestransform.qh
qcsrc/lib/warpzone/client.qh
qcsrc/lib/warpzone/common.qc
qcsrc/lib/warpzone/common.qh
qcsrc/lib/warpzone/mathlib.qh
qcsrc/lib/warpzone/server.qc
qcsrc/lib/warpzone/server.qh
qcsrc/lib/warpzone/util_server.qh
qcsrc/menu/anim/animation.qh
qcsrc/menu/anim/animhost.qc
qcsrc/menu/anim/animhost.qh
qcsrc/menu/anim/easing.qh
qcsrc/menu/anim/keyframe.qh
qcsrc/menu/command/all.qc
qcsrc/menu/command/all.qh [new file with mode: 0644]
qcsrc/menu/draw.qc
qcsrc/menu/item.qh
qcsrc/menu/item/borderimage.qh
qcsrc/menu/item/button.qh
qcsrc/menu/item/checkbox.qh
qcsrc/menu/item/container.qh
qcsrc/menu/item/dialog.qh
qcsrc/menu/item/image.qh
qcsrc/menu/item/inputbox.qh
qcsrc/menu/item/inputcontainer.qh
qcsrc/menu/item/label.qc
qcsrc/menu/item/label.qh
qcsrc/menu/item/listbox.qh
qcsrc/menu/item/modalcontroller.qh
qcsrc/menu/item/nexposee.qh
qcsrc/menu/item/radiobutton.qh
qcsrc/menu/item/slider.qh
qcsrc/menu/item/tab.qh
qcsrc/menu/item/textslider.qh
qcsrc/menu/matrix.qc
qcsrc/menu/matrix.qh [new file with mode: 0644]
qcsrc/menu/menu.qc
qcsrc/menu/skin.qh
qcsrc/menu/xonotic/bigbutton.qh
qcsrc/menu/xonotic/bigcommandbutton.qh
qcsrc/menu/xonotic/button.qh
qcsrc/menu/xonotic/campaign.qh
qcsrc/menu/xonotic/charmap.qh
qcsrc/menu/xonotic/checkbox.qh
qcsrc/menu/xonotic/checkbox_slider_invalid.qh
qcsrc/menu/xonotic/checkbox_string.qh
qcsrc/menu/xonotic/colorbutton.qh
qcsrc/menu/xonotic/colorpicker.qh
qcsrc/menu/xonotic/colorpicker_string.qh
qcsrc/menu/xonotic/commandbutton.qh
qcsrc/menu/xonotic/credits.qh
qcsrc/menu/xonotic/crosshairpicker.qh
qcsrc/menu/xonotic/crosshairpreview.qh
qcsrc/menu/xonotic/cvarlist.qh
qcsrc/menu/xonotic/datasource.qh
qcsrc/menu/xonotic/demolist.qh
qcsrc/menu/xonotic/dialog.qh
qcsrc/menu/xonotic/dialog_credits.qh
qcsrc/menu/xonotic/dialog_firstrun.qh
qcsrc/menu/xonotic/dialog_hudpanel_ammo.qh
qcsrc/menu/xonotic/dialog_hudpanel_centerprint.qh
qcsrc/menu/xonotic/dialog_hudpanel_chat.qh
qcsrc/menu/xonotic/dialog_hudpanel_engineinfo.qh
qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.qh
qcsrc/menu/xonotic/dialog_hudpanel_infomessages.qh
qcsrc/menu/xonotic/dialog_hudpanel_itemstime.qh
qcsrc/menu/xonotic/dialog_hudpanel_modicons.qh
qcsrc/menu/xonotic/dialog_hudpanel_notification.qh
qcsrc/menu/xonotic/dialog_hudpanel_physics.qh
qcsrc/menu/xonotic/dialog_hudpanel_powerups.qh
qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.qh
qcsrc/menu/xonotic/dialog_hudpanel_quickmenu.qh
qcsrc/menu/xonotic/dialog_hudpanel_racetimer.qh
qcsrc/menu/xonotic/dialog_hudpanel_radar.qh
qcsrc/menu/xonotic/dialog_hudpanel_score.qh
qcsrc/menu/xonotic/dialog_hudpanel_timer.qh
qcsrc/menu/xonotic/dialog_hudpanel_vote.qh
qcsrc/menu/xonotic/dialog_hudpanel_weapons.qh
qcsrc/menu/xonotic/dialog_hudsetup_exit.qh
qcsrc/menu/xonotic/dialog_monstertools.qh
qcsrc/menu/xonotic/dialog_multiplayer.qh
qcsrc/menu/xonotic/dialog_multiplayer_create.qh
qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.qc
qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.qh
qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qh
qcsrc/menu/xonotic/dialog_multiplayer_join.qc
qcsrc/menu/xonotic/dialog_multiplayer_join.qh
qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc
qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qh
qcsrc/menu/xonotic/dialog_multiplayer_media.qh
qcsrc/menu/xonotic/dialog_multiplayer_media_demo.qh
qcsrc/menu/xonotic/dialog_multiplayer_media_demo_startconfirm.qh
qcsrc/menu/xonotic/dialog_multiplayer_media_demo_timeconfirm.qh
qcsrc/menu/xonotic/dialog_multiplayer_media_musicplayer.qh
qcsrc/menu/xonotic/dialog_multiplayer_media_screenshot.qh
qcsrc/menu/xonotic/dialog_multiplayer_media_screenshot_viewer.qh
qcsrc/menu/xonotic/dialog_multiplayer_profile.qh
qcsrc/menu/xonotic/dialog_quit.qh
qcsrc/menu/xonotic/dialog_sandboxtools.qh
qcsrc/menu/xonotic/dialog_settings.qh
qcsrc/menu/xonotic/dialog_settings_audio.qh
qcsrc/menu/xonotic/dialog_settings_effects.qh
qcsrc/menu/xonotic/dialog_settings_game.qh
qcsrc/menu/xonotic/dialog_settings_game_crosshair.qh
qcsrc/menu/xonotic/dialog_settings_game_hud.qc
qcsrc/menu/xonotic/dialog_settings_game_hud.qh
qcsrc/menu/xonotic/dialog_settings_game_hudconfirm.qh
qcsrc/menu/xonotic/dialog_settings_game_messages.qh
qcsrc/menu/xonotic/dialog_settings_game_model.qh
qcsrc/menu/xonotic/dialog_settings_game_view.qh
qcsrc/menu/xonotic/dialog_settings_game_weapons.qh
qcsrc/menu/xonotic/dialog_settings_input.qh
qcsrc/menu/xonotic/dialog_settings_input_userbind.qh
qcsrc/menu/xonotic/dialog_settings_misc.qh
qcsrc/menu/xonotic/dialog_settings_misc_cvars.qh
qcsrc/menu/xonotic/dialog_settings_misc_reset.qh
qcsrc/menu/xonotic/dialog_settings_user.qh
qcsrc/menu/xonotic/dialog_settings_user_languagewarning.qh
qcsrc/menu/xonotic/dialog_settings_video.qh
qcsrc/menu/xonotic/dialog_singleplayer.qh
qcsrc/menu/xonotic/dialog_singleplayer_winner.qh
qcsrc/menu/xonotic/dialog_teamselect.qh
qcsrc/menu/xonotic/dialog_uid2name.qh
qcsrc/menu/xonotic/gametypelist.qc
qcsrc/menu/xonotic/gametypelist.qh
qcsrc/menu/xonotic/hudskinlist.qh
qcsrc/menu/xonotic/inputbox.qh
qcsrc/menu/xonotic/keybinder.qc
qcsrc/menu/xonotic/keybinder.qh
qcsrc/menu/xonotic/languagelist.qh
qcsrc/menu/xonotic/listbox.qh
qcsrc/menu/xonotic/mainwindow.qh
qcsrc/menu/xonotic/maplist.qc
qcsrc/menu/xonotic/maplist.qh
qcsrc/menu/xonotic/picker.qh
qcsrc/menu/xonotic/playerlist.qh
qcsrc/menu/xonotic/playermodel.qh
qcsrc/menu/xonotic/playlist.qh
qcsrc/menu/xonotic/radiobutton.qh
qcsrc/menu/xonotic/rootdialog.qh
qcsrc/menu/xonotic/screenshotimage.qh
qcsrc/menu/xonotic/screenshotlist.qh
qcsrc/menu/xonotic/serverlist.qc
qcsrc/menu/xonotic/serverlist.qh
qcsrc/menu/xonotic/skinlist.qh
qcsrc/menu/xonotic/slider.qh
qcsrc/menu/xonotic/slider_picmip.qh
qcsrc/menu/xonotic/slider_resolution.qc
qcsrc/menu/xonotic/slider_resolution.qh
qcsrc/menu/xonotic/slider_sbfadetime.qc
qcsrc/menu/xonotic/soundlist.qh
qcsrc/menu/xonotic/statslist.qc
qcsrc/menu/xonotic/statslist.qh
qcsrc/menu/xonotic/tab.qh
qcsrc/menu/xonotic/tabcontroller.qh
qcsrc/menu/xonotic/textlabel.qh
qcsrc/menu/xonotic/textslider.qh
qcsrc/menu/xonotic/util.qc
qcsrc/menu/xonotic/util.qh
qcsrc/menu/xonotic/weaponarenacheckbox.qh
qcsrc/menu/xonotic/weaponslist.qh
qcsrc/server-testcase/framework.qc
qcsrc/server/autocvars.qh
qcsrc/server/bot/_mod.inc
qcsrc/server/bot/_mod.qh
qcsrc/server/bot/aim.qc [deleted file]
qcsrc/server/bot/aim.qh [deleted file]
qcsrc/server/bot/api.qc [new file with mode: 0644]
qcsrc/server/bot/api.qh [new file with mode: 0644]
qcsrc/server/bot/bot.qc [deleted file]
qcsrc/server/bot/bot.qh [deleted file]
qcsrc/server/bot/default/_mod.inc [new file with mode: 0644]
qcsrc/server/bot/default/_mod.qh [new file with mode: 0644]
qcsrc/server/bot/default/aim.qc [new file with mode: 0644]
qcsrc/server/bot/default/aim.qh [new file with mode: 0644]
qcsrc/server/bot/default/bot.qc [new file with mode: 0644]
qcsrc/server/bot/default/bot.qh [new file with mode: 0644]
qcsrc/server/bot/default/cvars.qc [new file with mode: 0644]
qcsrc/server/bot/default/cvars.qh [new file with mode: 0644]
qcsrc/server/bot/default/havocbot/_mod.inc [new file with mode: 0644]
qcsrc/server/bot/default/havocbot/_mod.qh [new file with mode: 0644]
qcsrc/server/bot/default/havocbot/havocbot.qc [new file with mode: 0644]
qcsrc/server/bot/default/havocbot/havocbot.qh [new file with mode: 0644]
qcsrc/server/bot/default/havocbot/roles.qc [new file with mode: 0644]
qcsrc/server/bot/default/havocbot/roles.qh [new file with mode: 0644]
qcsrc/server/bot/default/havocbot/scripting.qh [new file with mode: 0644]
qcsrc/server/bot/default/navigation.qc [new file with mode: 0644]
qcsrc/server/bot/default/navigation.qh [new file with mode: 0644]
qcsrc/server/bot/default/scripting.qc [new file with mode: 0644]
qcsrc/server/bot/default/scripting.qh [new file with mode: 0644]
qcsrc/server/bot/default/waypoints.qc [new file with mode: 0644]
qcsrc/server/bot/default/waypoints.qh [new file with mode: 0644]
qcsrc/server/bot/havocbot/_mod.inc [deleted file]
qcsrc/server/bot/havocbot/_mod.qh [deleted file]
qcsrc/server/bot/havocbot/havocbot.qc [deleted file]
qcsrc/server/bot/havocbot/havocbot.qh [deleted file]
qcsrc/server/bot/havocbot/roles.qc [deleted file]
qcsrc/server/bot/havocbot/roles.qh [deleted file]
qcsrc/server/bot/havocbot/scripting.qh [deleted file]
qcsrc/server/bot/navigation.qc [deleted file]
qcsrc/server/bot/navigation.qh [deleted file]
qcsrc/server/bot/scripting.qc [deleted file]
qcsrc/server/bot/scripting.qh [deleted file]
qcsrc/server/bot/waypoints.qc [deleted file]
qcsrc/server/bot/waypoints.qh [deleted file]
qcsrc/server/campaign.qc
qcsrc/server/cheats.qc
qcsrc/server/cl_client.qc
qcsrc/server/cl_client.qh
qcsrc/server/cl_impulse.qc
qcsrc/server/cl_player.qc
qcsrc/server/command/common.qc
qcsrc/server/command/radarmap.qc
qcsrc/server/command/sv_cmd.qc
qcsrc/server/command/vote.qc
qcsrc/server/defs.qh
qcsrc/server/g_damage.qc
qcsrc/server/g_damage.qh
qcsrc/server/g_hook.qc
qcsrc/server/g_lights.qc
qcsrc/server/g_subs.qc
qcsrc/server/g_world.qc
qcsrc/server/ipban.qc
qcsrc/server/item_key.qc
qcsrc/server/mapvoting.qc
qcsrc/server/miscfunctions.qc
qcsrc/server/mutators/all.qc
qcsrc/server/mutators/events.qh
qcsrc/server/mutators/gamemode.qh
qcsrc/server/mutators/mutator.qh
qcsrc/server/mutators/mutator/gamemode_assault.qc
qcsrc/server/mutators/mutator/gamemode_ctf.qc
qcsrc/server/mutators/mutator/gamemode_ctf.qh
qcsrc/server/mutators/mutator/gamemode_cts.qc
qcsrc/server/mutators/mutator/gamemode_domination.qc
qcsrc/server/mutators/mutator/gamemode_freezetag.qc
qcsrc/server/mutators/mutator/gamemode_invasion.qc
qcsrc/server/mutators/mutator/gamemode_keepaway.qc
qcsrc/server/mutators/mutator/gamemode_keyhunt.qc
qcsrc/server/mutators/mutator/gamemode_lms.qc
qcsrc/server/mutators/mutator/gamemode_race.qc
qcsrc/server/mutators/mutator/gamemode_tdm.qc
qcsrc/server/pathlib/main.qc
qcsrc/server/pathlib/movenode.qc
qcsrc/server/pathlib/path_waypoint.qc
qcsrc/server/portals.qc
qcsrc/server/progs.inc
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/spawnpoints.qc
qcsrc/server/sv_main.qc
qcsrc/server/sys-post.qh
qcsrc/server/teamplay.qc
qcsrc/server/tests.qc
qcsrc/server/weapons/accuracy.qc
qcsrc/server/weapons/selection.qc
qcsrc/server/weapons/spawning.qc
qcsrc/server/weapons/throwing.qc
qcsrc/server/weapons/throwing.qh
qcsrc/server/weapons/tracing.qc
qcsrc/server/weapons/tracing.qh
qcsrc/server/weapons/weaponsystem.qc
qcsrc/server/weapons/weaponsystem.qh
qcsrc/tools/cloc.txt [new file with mode: 0644]
qcsrc/tools/headerstyle.sh
qcsrc/tools/whitespace.sh
qcsrc/uncrustify.cfg

index ce9e150565876706d375681718156c2fe9b4a733..8838f39c9734b2fbb015b615c68e645cb487dd22 100644 (file)
@@ -5,6 +5,12 @@ before_script:
   - cd gmqcc && make -j $(nproc) && export QCC="$PWD/gmqcc"
   - cd ..
 
+report_cloc:
+  stage: test
+  script:
+    - cloc --force-lang-def=qcsrc/tools/cloc.txt --sql 1 --sql-project xonotic qcsrc | sqlite3 code.db
+    - sqlite3 code.db 'select file,nCode from t where nCode > 1000 order by nBlank+nComment+nCode desc'
+
 test_compilation_units:
   stage: test
   script:
@@ -24,7 +30,7 @@ test_sv_game:
     - wget -O data/maps/g-23.waypoints.cache https://gitlab.com/xonotic/xonotic-maps.pk3dir/raw/master/maps/g-23.waypoints.cache
     - wget -O data/maps/g-23.waypoints.hardwired https://gitlab.com/xonotic/xonotic-maps.pk3dir/raw/master/maps/g-23.waypoints.hardwired
     - make
-    - EXPECT=d17f62e08ff11b8b25116fa4a64f7e86
+    - EXPECT=74f3802009cec230bdaa3b87235368ca
     - HASH=$(${ENGINE} -noconfig -nohome +exec serverbench.cfg
       | tee /dev/stderr
       | grep '^:'
index 7bf9111cd4dab6c5d3d655e4ed3bc765c074ce49..725bfe4e38b840dec5a7c4dc27c04f7028e503ce 100644 (file)
@@ -44,6 +44,8 @@ seta hud_panel_centerprint      1 "enable this panel"
 //seta hud_panel_mapvote          1 "enable this panel"
 seta hud_panel_itemstime        2 "enable this panel, 1 = show when spectating, 2 = even playing in warmup stage"
 //seta hud_panel_quickmenu        1 "enable this panel"
+//seta hud_panel_scoreboard       1 "enable this panel"
+seta hud_panel_scoreboard_accuracy 1 "show weapon accuracy stats panel on scoreboard; colors can be configured with accuracy_color* cvars"
 
 seta hud_panel_weapons_dynamichud          1 "apply the dynamic hud effects to this panel"
 seta hud_panel_ammo_dynamichud             1 "apply the dynamic hud effects to this panel"
@@ -62,6 +64,7 @@ seta hud_panel_infomessages_dynamichud     0 "apply the dynamic hud effects to t
 seta hud_panel_physics_dynamichud          1 "apply the dynamic hud effects to this panel"
 seta hud_panel_centerprint_dynamichud      1 "apply the dynamic hud effects to this panel"
 seta hud_panel_itemstime_dynamichud        1 "apply the dynamic hud effects to this panel"
+seta hud_panel_scoreboard_dynamichud       0 "apply the dynamic hud effects to this panel"
 
 seta hud_panel_weapons_ammo_full_shells 60 "show 100% of the status bar at this ammo count"
 seta hud_panel_weapons_ammo_full_nails 320 "show 100% of the status bar at this ammo count"
@@ -69,13 +72,18 @@ seta hud_panel_weapons_ammo_full_cells 180 "show 100% of the status bar at this
 seta hud_panel_weapons_ammo_full_plasma 180 "show 100% of the status bar at this ammo count"
 seta hud_panel_weapons_ammo_full_rockets 160 "show 100% of the status bar at this ammo count"
 seta hud_panel_weapons_ammo_full_fuel 100 "show 100% of the status bar at this ammo count"
+seta hud_panel_weapons_hide_ondeath 0 "hide this panel when dead"
 
 seta hud_panel_ammo_maxammo "40" "when you have this much ammo, the ammo status bar is full"
+seta hud_panel_ammo_hide_ondeath 0 "hide this panel when dead"
+
+seta hud_panel_powerups_hide_ondeath 0 "hide this panel when dead"
 
 seta hud_panel_healtharmor_maxhealth "200" "when you have this much health, the health status bar is full"
 seta hud_panel_healtharmor_maxarmor "200" "when you have this much armor, the armor status bar is full"
 seta hud_panel_healtharmor_progressbar_gfx_damage 5 "show damage effect when damaged at least by this amount; 0 disables the effect"
 seta hud_panel_healtharmor_progressbar_gfx_lowhealth 40 "health progressbar blinks when health is lower than this amount"
+seta hud_panel_healtharmor_hide_ondeath 0 "hide this panel when dead"
 
 seta hud_panel_timer_increment "0" "show elapsed time instead of remaining time"
 
@@ -95,6 +103,10 @@ seta hud_panel_quickmenu_file "" "load the quick menu from this file (empty or 0
 seta hud_panel_quickmenu_translatecommands 0 "when the game is translated, translate strings inside commands too (useful for chat commands)"
 seta hud_panel_quickmenu_time 5 "quickmenu expires after this number of seconds in the same page"
 
+seta hud_panel_infomessages_group0 1 "show group 0 messages (showing keys for non-crucial actions you can do while spectating/observing)"
+seta hud_panel_infomessages_group_time 6 "number of seconds a message of a group lasts before it gets changed"
+seta hud_panel_infomessages_group_fadetime 0.4 "group message fade in/out time"
+
 // hud panel aliases
 alias quickmenu "cl_cmd hud quickmenu ${* ?}"
 
index ee46898904a77f6d992b974f867c8fa798169aa8..9a1654f83abd1a177f392a12fd6d785ce883a706 100644 (file)
@@ -329,6 +329,7 @@ seta hud_panel_mapvote_bg_color_team "" "override panel color with team color in
 seta hud_panel_mapvote_bg_alpha "" "if set to something else than \"\" = override default panel background alpha"
 seta hud_panel_mapvote_bg_border "" "if set to something else than \"\" = override default size of border around the background"
 seta hud_panel_mapvote_bg_padding "" "if set to something else than \"\" = override default padding of contents from border"
+seta hud_panel_mapvote_highlight_border "" "highlight border size of the selected map"
 
 seta hud_panel_itemstime_pos "" "position of this base of the panel"
 seta hud_panel_itemstime_size "" "size of this panel"
@@ -355,3 +356,25 @@ seta hud_panel_quickmenu_bg_alpha "" "if set to something else than \"\" = overr
 seta hud_panel_quickmenu_bg_border "" "if set to something else than \"\" = override default size of border around the background"
 seta hud_panel_quickmenu_bg_padding "" "if set to something else than \"\" = override default padding of contents from border"
 seta hud_panel_quickmenu_align "" "text alignment: 0 left, 0.5 center, 1 right"
+
+seta hud_panel_scoreboard_pos "" "position of this base of the panel"
+seta hud_panel_scoreboard_size "" "size of this panel"
+seta hud_panel_scoreboard_bg "" "if set to something else than \"\" = override default background"
+seta hud_panel_scoreboard_bg_color "" "if set to something else than \"\" = override default panel background color"
+seta hud_panel_scoreboard_bg_color_team "" "override panel color with team color in team based games"
+seta hud_panel_scoreboard_bg_alpha "" "if set to something else than \"\" = override default panel background alpha"
+seta hud_panel_scoreboard_bg_border "" "if set to something else than \"\" = override default size of border around the background"
+seta hud_panel_scoreboard_bg_padding "" "if set to something else than \"\" = override default padding of contents from border"
+seta hud_panel_scoreboard_fadeinspeed "" "speed at which scoreboard fades in, higher is faster (0 = instant)"
+seta hud_panel_scoreboard_fadeoutspeed "" "speed at which scoreboard fades out, higher is faster (0 = instant)"
+seta hud_panel_scoreboard_respawntime_decimals "" "decimal places to show for the respawntime countdown display on the scoreboard"
+seta hud_panel_scoreboard_table_bg_alpha "" "background alpha of a scoreboard table"
+seta hud_panel_scoreboard_table_bg_scale "" "scale for the tiled scoreboard background"
+seta hud_panel_scoreboard_table_fg_alpha "" "foreground alpha of a scoreboard table"
+seta hud_panel_scoreboard_table_fg_alpha_self "" "self foreground alpha of a scoreboard table"
+seta hud_panel_scoreboard_table_highlight "" "enable highlighting for rows and columns in scoreboard tables"
+seta hud_panel_scoreboard_table_highlight_alpha "" "highlight alpha of a scoreboard table"
+seta hud_panel_scoreboard_table_highlight_alpha_self "" "self highlight alpha of a scoreboard table"
+seta hud_panel_scoreboard_bg_teams_color_team "" "override panel team color in team tables"
+seta hud_panel_scoreboard_accuracy_doublerows "" "use two rows instead of one"
+seta hud_panel_scoreboard_accuracy_nocolors "" "don't use colors displaying accuracy stats"
index 11ba8e4ff3428a486bd95b67d71d032b77c63f4f..d2731c0732e2623c2dda636e5d367622546a1a26 100644 (file)
@@ -832,6 +832,10 @@ seta sbar_info_pos 0 "Y-axis distance from lower right corner for engine info pr
 
 // scoreboard
 seta scoreboard_columns default
+
+// keep old scoreboard cvars for compatibility's sake
+// they've been replaced by hud_panel_scoreboard_* cvars
+// TODO remove them after a future release (0.8.2+)
 seta scoreboard_border_thickness 1 "scoreboard border thickness"
 seta scoreboard_accuracy_border_thickness 1 "accuracy stats border thickness"
 seta scoreboard_accuracy_doublerows 0 "use two rows instead of one"
@@ -1077,7 +1081,7 @@ set g_ban_sync_trusted_servers "" "request ban lists from these xonotic servers
 set g_ban_sync_timeout 45      "time out in seconds for the ban sync requests"
 set g_ban_sync_trusted_servers_verify 0        "when set to 1, additional bans sent by the servers are ignored, and only bans for the requested IP are used"
 
-set g_showweaponspawns 1       "display sprites for weapon spawns found on the map when a weapon key is pressed and the weapon is not available"
+set g_showweaponspawns 1 "1: display waypoints for weapon spawns found on the map when a weapon key is pressed and the weapon is not owned; 2: for dropped weapons too; 3: for all the weapons sharing the same impulse"
 
 // ballistics use physical units, but qu based
 //   Quake-Newton: 1 qN  = 1 qu * 1 g / 1 s^2
@@ -1452,6 +1456,9 @@ set cl_fullbright_items 0 "enable fullbright items (if server allows, controled
 set cl_weapon_stay_color "2 0.5 0.5" "Color of picked up weapons when g_weapon_stay > 0"
 set cl_weapon_stay_alpha 0.75 "Alpha of picked up weapons when g_weapon_stay > 0"
 
+set sv_showspectators 0 "Show who's spectating who in the player info panel. Shouldn't be used on competitive servers, also disable when watching a suspected cheater"
+seta cl_showspectators 1
+
 // Facility for config.cfg use ONLY.
 // Interpreted in post-config.cfg.
 seta menu_forced_saved_cvars "" "These cvars will always be saved, despite engine/Xonotic cvar saving status"
index 2f4f31e92b7290f7f2852a69ffdc1dc8272915ff..5ebdeaeec999de16665fbadd76f228d2edd9ffd3 100644 (file)
@@ -29,7 +29,7 @@ seta hud_progressbar_acceleration_neg_color "0.86 0.35 0"
 seta hud_progressbar_vehicles_ammo1_color "0.77 0.67 0"
 seta hud_progressbar_vehicles_ammo2_color "0.86 0.35 0"
 
-seta _hud_panelorder "17 15 12 9 5 10 6 14 0 7 4 11 2 1 3 8 13 16 18 23 19 20 21 22 "
+seta _hud_panelorder "17 15 12 9 5 10 6 14 0 7 4 11 2 1 3 8 13 16 18 23 19 20 21 22 23 24 "
 
 seta hud_configure_grid "1"
 seta hud_configure_grid_xsize "0.005000"
@@ -230,7 +230,7 @@ seta hud_panel_engineinfo_bg_padding ""
 seta hud_panel_engineinfo_framecounter_time "0.1"
 seta hud_panel_engineinfo_framecounter_decimals "0"
 
-seta hud_panel_infomessages_pos "0.720000 0.100000"
+seta hud_panel_infomessages_pos "0.680000 0.100000"
 seta hud_panel_infomessages_size "0.280000 0.080000"
 seta hud_panel_infomessages_bg "0"
 seta hud_panel_infomessages_bg_color ""
@@ -330,6 +330,7 @@ seta hud_panel_mapvote_bg_color_team ""
 seta hud_panel_mapvote_bg_alpha ""
 seta hud_panel_mapvote_bg_border ""
 seta hud_panel_mapvote_bg_padding ""
+seta hud_panel_mapvote_highlight_border "1"
 
 seta hud_panel_itemstime_pos "0.030000 0.260000"
 seta hud_panel_itemstime_size "0.070000 0.230000"
@@ -357,4 +358,26 @@ seta hud_panel_quickmenu_bg_border ""
 seta hud_panel_quickmenu_bg_padding ""
 seta hud_panel_quickmenu_align "0"
 
+seta hud_panel_scoreboard_pos "0.150000 0.150000"
+seta hud_panel_scoreboard_size "0.700000 0.700000"
+seta hud_panel_scoreboard_bg "border_default"
+seta hud_panel_scoreboard_bg_color "0 0.3 0.5"
+seta hud_panel_scoreboard_bg_color_team ""
+seta hud_panel_scoreboard_bg_alpha "0.7"
+seta hud_panel_scoreboard_bg_border ""
+seta hud_panel_scoreboard_bg_padding ""
+seta hud_panel_scoreboard_fadeinspeed "10"
+seta hud_panel_scoreboard_fadeoutspeed "5"
+seta hud_panel_scoreboard_respawntime_decimals "1"
+seta hud_panel_scoreboard_table_bg_alpha "0"
+seta hud_panel_scoreboard_table_bg_scale "0.25"
+seta hud_panel_scoreboard_table_fg_alpha "0.9"
+seta hud_panel_scoreboard_table_fg_alpha_self "1"
+seta hud_panel_scoreboard_table_highlight "1"
+seta hud_panel_scoreboard_table_highlight_alpha "0.2"
+seta hud_panel_scoreboard_table_highlight_alpha_self "0.4"
+seta hud_panel_scoreboard_bg_teams_color_team "0"
+seta hud_panel_scoreboard_accuracy_doublerows "0"
+seta hud_panel_scoreboard_accuracy_nocolors "0"
+
 menu_sync
index 3d259ebf394d7b104f848c37e8a35058c8b6aec0..8f64ddebb6e943040a0c8458f64ecc02a22f4a2b 100644 (file)
@@ -29,7 +29,7 @@ seta hud_progressbar_acceleration_neg_color "0.125 0.25 0.5"
 seta hud_progressbar_vehicles_ammo1_color "0.8 0.7 0"
 seta hud_progressbar_vehicles_ammo2_color "0.7 0.4 0"
 
-seta _hud_panelorder "17 15 12 9 10 5 6 14 0 7 4 11 2 1 3 8 13 16 18 23 19 20 21 22 "
+seta _hud_panelorder "17 15 12 9 10 5 6 14 0 7 4 11 2 1 3 8 13 16 18 23 19 20 21 22 23 24 "
 
 seta hud_configure_grid "1"
 seta hud_configure_grid_xsize "0.010000"
@@ -230,7 +230,7 @@ seta hud_panel_engineinfo_bg_padding ""
 seta hud_panel_engineinfo_framecounter_time "0.1"
 seta hud_panel_engineinfo_framecounter_decimals "0"
 
-seta hud_panel_infomessages_pos "0.720000 0.100000"
+seta hud_panel_infomessages_pos "0.680000 0.100000"
 seta hud_panel_infomessages_size "0.280000 0.080000"
 seta hud_panel_infomessages_bg "0"
 seta hud_panel_infomessages_bg_color ""
@@ -330,6 +330,7 @@ seta hud_panel_mapvote_bg_color_team ""
 seta hud_panel_mapvote_bg_alpha ""
 seta hud_panel_mapvote_bg_border ""
 seta hud_panel_mapvote_bg_padding ""
+seta hud_panel_mapvote_highlight_border "1"
 
 seta hud_panel_itemstime_pos "0.030000 0.260000"
 seta hud_panel_itemstime_size "0.070000 0.230000"
@@ -357,4 +358,26 @@ seta hud_panel_quickmenu_bg_border ""
 seta hud_panel_quickmenu_bg_padding ""
 seta hud_panel_quickmenu_align "0"
 
+seta hud_panel_scoreboard_pos "0.150000 0.150000"
+seta hud_panel_scoreboard_size "0.700000 0.700000"
+seta hud_panel_scoreboard_bg "border_default"
+seta hud_panel_scoreboard_bg_color ""
+seta hud_panel_scoreboard_bg_color_team "0.7"
+seta hud_panel_scoreboard_bg_alpha "0.7"
+seta hud_panel_scoreboard_bg_border ""
+seta hud_panel_scoreboard_bg_padding ""
+seta hud_panel_scoreboard_fadeinspeed "10"
+seta hud_panel_scoreboard_fadeoutspeed "5"
+seta hud_panel_scoreboard_respawntime_decimals "1"
+seta hud_panel_scoreboard_table_bg_alpha "0.8"
+seta hud_panel_scoreboard_table_bg_scale "0.25"
+seta hud_panel_scoreboard_table_fg_alpha "0.9"
+seta hud_panel_scoreboard_table_fg_alpha_self "1"
+seta hud_panel_scoreboard_table_highlight "1"
+seta hud_panel_scoreboard_table_highlight_alpha "0.08"
+seta hud_panel_scoreboard_table_highlight_alpha_self "0.3"
+seta hud_panel_scoreboard_bg_teams_color_team "0"
+seta hud_panel_scoreboard_accuracy_doublerows "1"
+seta hud_panel_scoreboard_accuracy_nocolors "0"
+
 menu_sync
index c1ac51b7ab854ddf345f7e11023b64713dccc810..31926d2f5ab9d906dfbf79f26d2e5d9e8441ebfe 100644 (file)
@@ -29,7 +29,7 @@ seta hud_progressbar_acceleration_neg_color "0.125 0.25 0.5"
 seta hud_progressbar_vehicles_ammo1_color "0.8 0.7 0"
 seta hud_progressbar_vehicles_ammo2_color "0.7 0.4 0"
 
-seta _hud_panelorder "17 10 3 0 14 6 9 13 4 1 2 11 12 7 5 8 15 16 18 23 19 20 21 22 "
+seta _hud_panelorder "17 10 3 0 14 6 9 13 4 1 2 11 12 7 5 8 15 16 18 23 19 20 21 22 23 24 "
 
 seta hud_configure_grid "1"
 seta hud_configure_grid_xsize "0.010000"
@@ -231,7 +231,7 @@ seta hud_panel_engineinfo_framecounter_time "0.1"
 seta hud_panel_engineinfo_framecounter_decimals "0"
 
 seta hud_panel_infomessages_pos "0.710000 0"
-seta hud_panel_infomessages_size "0.290000 0.100000"
+seta hud_panel_infomessages_size "0.280000 0.090000"
 seta hud_panel_infomessages_bg "0"
 seta hud_panel_infomessages_bg_color ""
 seta hud_panel_infomessages_bg_color_team ""
@@ -330,6 +330,7 @@ seta hud_panel_mapvote_bg_color_team ""
 seta hud_panel_mapvote_bg_alpha ""
 seta hud_panel_mapvote_bg_border ""
 seta hud_panel_mapvote_bg_padding ""
+seta hud_panel_mapvote_highlight_border "1"
 
 seta hud_panel_itemstime_pos "0.000000 0.310000"
 seta hud_panel_itemstime_size "0.070000 0.180000"
@@ -357,4 +358,26 @@ seta hud_panel_quickmenu_bg_border ""
 seta hud_panel_quickmenu_bg_padding ""
 seta hud_panel_quickmenu_align "0"
 
+seta hud_panel_scoreboard_pos "0.150000 0.150000"
+seta hud_panel_scoreboard_size "0.700000 0.700000"
+seta hud_panel_scoreboard_bg "0"
+seta hud_panel_scoreboard_bg_color ""
+seta hud_panel_scoreboard_bg_color_team ""
+seta hud_panel_scoreboard_bg_alpha ""
+seta hud_panel_scoreboard_bg_border ""
+seta hud_panel_scoreboard_bg_padding ""
+seta hud_panel_scoreboard_fadeinspeed "10"
+seta hud_panel_scoreboard_fadeoutspeed "5"
+seta hud_panel_scoreboard_respawntime_decimals "1"
+seta hud_panel_scoreboard_table_bg_alpha "0.8"
+seta hud_panel_scoreboard_table_bg_scale "0.25"
+seta hud_panel_scoreboard_table_fg_alpha "0.9"
+seta hud_panel_scoreboard_table_fg_alpha_self "1"
+seta hud_panel_scoreboard_table_highlight "1"
+seta hud_panel_scoreboard_table_highlight_alpha "0.08"
+seta hud_panel_scoreboard_table_highlight_alpha_self "0.3"
+seta hud_panel_scoreboard_bg_teams_color_team "0.7"
+seta hud_panel_scoreboard_accuracy_doublerows "1"
+seta hud_panel_scoreboard_accuracy_nocolors "0"
+
 menu_sync
index d6125985b8a42e180e753e91a4b3ee584bddf932..380b65814864325977cb29475ce31d896ed71dd0 100644 (file)
@@ -29,7 +29,7 @@ seta hud_progressbar_acceleration_neg_color "0.125 0.25 0.5"
 seta hud_progressbar_vehicles_ammo1_color "0.8 0.7 0"
 seta hud_progressbar_vehicles_ammo2_color "0.7 0.4 0"
 
-seta _hud_panelorder "17 15 3 1 2 11 10 0 14 6 9 13 4 12 7 5 8 16 18 23 19 20 21 22 "
+seta _hud_panelorder "17 15 3 1 2 11 10 0 14 6 9 13 4 12 7 5 8 16 18 23 19 20 21 22 23 24 "
 
 seta hud_configure_grid "1"
 seta hud_configure_grid_xsize "0.010000"
@@ -231,7 +231,7 @@ seta hud_panel_engineinfo_framecounter_time "0.1"
 seta hud_panel_engineinfo_framecounter_decimals "0"
 
 seta hud_panel_infomessages_pos "0.710000 0"
-seta hud_panel_infomessages_size "0.290000 0.100000"
+seta hud_panel_infomessages_size "0.280000 0.090000"
 seta hud_panel_infomessages_bg "0"
 seta hud_panel_infomessages_bg_color ""
 seta hud_panel_infomessages_bg_color_team ""
@@ -330,6 +330,7 @@ seta hud_panel_mapvote_bg_color_team ""
 seta hud_panel_mapvote_bg_alpha ""
 seta hud_panel_mapvote_bg_border ""
 seta hud_panel_mapvote_bg_padding ""
+seta hud_panel_mapvote_highlight_border "1"
 
 seta hud_panel_itemstime_pos "0.000000 0.310000"
 seta hud_panel_itemstime_size "0.070000 0.180000"
@@ -357,4 +358,26 @@ seta hud_panel_quickmenu_bg_border ""
 seta hud_panel_quickmenu_bg_padding ""
 seta hud_panel_quickmenu_align "0"
 
+seta hud_panel_scoreboard_pos "0.150000 0.150000"
+seta hud_panel_scoreboard_size "0.700000 0.700000"
+seta hud_panel_scoreboard_bg "0"
+seta hud_panel_scoreboard_bg_color ""
+seta hud_panel_scoreboard_bg_color_team ""
+seta hud_panel_scoreboard_bg_alpha ""
+seta hud_panel_scoreboard_bg_border ""
+seta hud_panel_scoreboard_bg_padding ""
+seta hud_panel_scoreboard_fadeinspeed "10"
+seta hud_panel_scoreboard_fadeoutspeed "5"
+seta hud_panel_scoreboard_respawntime_decimals "1"
+seta hud_panel_scoreboard_table_bg_alpha "0.8"
+seta hud_panel_scoreboard_table_bg_scale "0.25"
+seta hud_panel_scoreboard_table_fg_alpha "0.9"
+seta hud_panel_scoreboard_table_fg_alpha_self "1"
+seta hud_panel_scoreboard_table_highlight "1"
+seta hud_panel_scoreboard_table_highlight_alpha "0.08"
+seta hud_panel_scoreboard_table_highlight_alpha_self "0.3"
+seta hud_panel_scoreboard_bg_teams_color_team "0.7"
+seta hud_panel_scoreboard_accuracy_doublerows "1"
+seta hud_panel_scoreboard_accuracy_nocolors "0"
+
 menu_sync
index 4ee8005213de354475b006596b82655b7c5408f9..96b4f508f50c1a193ad5dca91664274a96b6d781 100644 (file)
@@ -29,7 +29,7 @@ seta hud_progressbar_acceleration_neg_color "0.125 0.25 0.5"
 seta hud_progressbar_vehicles_ammo1_color "0.8 0.7 0"
 seta hud_progressbar_vehicles_ammo2_color "0.7 0.4 0"
 
-seta _hud_panelorder "17 15 10 9 6 8 14 5 0 4 13 2 7 1 3 11 12 16 18 23 19 20 21 22 "
+seta _hud_panelorder "17 15 10 9 6 8 14 5 0 4 13 2 7 1 3 11 12 16 18 23 19 20 21 22 23 24 "
 
 seta hud_configure_grid "1"
 seta hud_configure_grid_xsize "0.010000"
@@ -330,6 +330,7 @@ seta hud_panel_mapvote_bg_color_team ""
 seta hud_panel_mapvote_bg_alpha ""
 seta hud_panel_mapvote_bg_border ""
 seta hud_panel_mapvote_bg_padding ""
+seta hud_panel_mapvote_highlight_border "1"
 
 seta hud_panel_itemstime_pos "0.020000 0.490000"
 seta hud_panel_itemstime_size "0.090000 0.140000"
@@ -357,4 +358,26 @@ seta hud_panel_quickmenu_bg_border ""
 seta hud_panel_quickmenu_bg_padding ""
 seta hud_panel_quickmenu_align "1"
 
+seta hud_panel_scoreboard_pos "0.150000 0.150000"
+seta hud_panel_scoreboard_size "0.700000 0.700000"
+seta hud_panel_scoreboard_bg ""
+seta hud_panel_scoreboard_bg_color ""
+seta hud_panel_scoreboard_bg_color_team ""
+seta hud_panel_scoreboard_bg_alpha ""
+seta hud_panel_scoreboard_bg_border ""
+seta hud_panel_scoreboard_bg_padding ""
+seta hud_panel_scoreboard_fadeinspeed "10"
+seta hud_panel_scoreboard_fadeoutspeed "5"
+seta hud_panel_scoreboard_respawntime_decimals "1"
+seta hud_panel_scoreboard_table_bg_alpha "0.8"
+seta hud_panel_scoreboard_table_bg_scale "0.25"
+seta hud_panel_scoreboard_table_fg_alpha "0.9"
+seta hud_panel_scoreboard_table_fg_alpha_self "1"
+seta hud_panel_scoreboard_table_highlight "1"
+seta hud_panel_scoreboard_table_highlight_alpha "0.08"
+seta hud_panel_scoreboard_table_highlight_alpha_self "0.3"
+seta hud_panel_scoreboard_bg_teams_color_team "0.7"
+seta hud_panel_scoreboard_accuracy_doublerows "1"
+seta hud_panel_scoreboard_accuracy_nocolors "0"
+
 menu_sync
index df565ef686ebf47a92f2541f74183dfa937c2aa8..ae786574f3bfcbd6a59ed889927f4d333617deb0 100644 (file)
@@ -29,7 +29,7 @@ seta hud_progressbar_acceleration_neg_color "0.125 0.25 0.5"
 seta hud_progressbar_vehicles_ammo1_color "0.8 0.7 0"
 seta hud_progressbar_vehicles_ammo2_color "0.7 0.4 0"
 
-seta _hud_panelorder "17 15 0 11 8 5 6 14 9 13 7 2 3 1 10 12 4 16 18 23 19 20 21 22 "
+seta _hud_panelorder "17 15 0 11 8 5 6 14 9 13 7 2 3 1 10 12 4 16 18 23 19 20 21 22 23 24 "
 
 seta hud_configure_grid "1"
 seta hud_configure_grid_xsize "0.010000"
@@ -330,6 +330,7 @@ seta hud_panel_mapvote_bg_color_team ""
 seta hud_panel_mapvote_bg_alpha ""
 seta hud_panel_mapvote_bg_border ""
 seta hud_panel_mapvote_bg_padding ""
+seta hud_panel_mapvote_highlight_border "1"
 
 seta hud_panel_itemstime_pos "0.000000 0.290000"
 seta hud_panel_itemstime_size "0.150000 0.060000"
@@ -357,4 +358,26 @@ seta hud_panel_quickmenu_bg_border ""
 seta hud_panel_quickmenu_bg_padding ""
 seta hud_panel_quickmenu_align "0"
 
+seta hud_panel_scoreboard_pos "0.150000 0.150000"
+seta hud_panel_scoreboard_size "0.700000 0.700000"
+seta hud_panel_scoreboard_bg ""
+seta hud_panel_scoreboard_bg_color ""
+seta hud_panel_scoreboard_bg_color_team ""
+seta hud_panel_scoreboard_bg_alpha "0.7"
+seta hud_panel_scoreboard_bg_border ""
+seta hud_panel_scoreboard_bg_padding ""
+seta hud_panel_scoreboard_fadeinspeed "10"
+seta hud_panel_scoreboard_fadeoutspeed "5"
+seta hud_panel_scoreboard_respawntime_decimals "1"
+seta hud_panel_scoreboard_table_bg_alpha "0.8"
+seta hud_panel_scoreboard_table_bg_scale "0.25"
+seta hud_panel_scoreboard_table_fg_alpha "0.9"
+seta hud_panel_scoreboard_table_fg_alpha_self "1"
+seta hud_panel_scoreboard_table_highlight "1"
+seta hud_panel_scoreboard_table_highlight_alpha "0.1"
+seta hud_panel_scoreboard_table_highlight_alpha_self "0.25"
+seta hud_panel_scoreboard_bg_teams_color_team "0.7"
+seta hud_panel_scoreboard_accuracy_doublerows "1"
+seta hud_panel_scoreboard_accuracy_nocolors "0"
+
 menu_sync
index cb9ca2a883afc26501bec16c6ebcf17687241cfc..09d0128578d272c49812442b4d840efc7eede915 100644 (file)
@@ -2002,10 +2002,11 @@ PREDEFINED             = \
     "INIT(class)=class::class()" \
     "CONSTRUCTOR(class)=class::class(" \
     "DESTRUCTOR(class)=class::~class()" \
-    "ATTRIB(class, name, T, val)=T name = val;" \
-    "ATTRIB_STRZONE(class, name, T, val)=T name = val;" \
-    "STATIC_ATTRIB(class, name, T, val)=static T name = val;" \
-    "STATIC_ATTRIB_STRZONE(class, name, T, val)=static T name = val;" \
+    "ATTRIB(class, name, T, val)=T name = val" \
+    "ATTRIB_STRZONE(class, name, T, val)=T name = val" \
+    "ATTRIBARRAY(class, name, T, val)=T name[val]" \
+    "STATIC_ATTRIB(class, name, T, val)=static T name = val" \
+    "STATIC_ATTRIB_STRZONE(class, name, T, val)=static T name = val" \
     "METHOD(class, name, prototype)=virtual void class::name()" \
     "ENDCLASS(class)=};" \
     __STDC__
index 186be97400aaa76e6253d2786d525c31c234f28d..0920265d630bec596040cd55735ce790510adc76 100644 (file)
@@ -6,7 +6,6 @@
 #include <client/mapvoting.qc>
 #include <client/miscfunctions.qc>
 #include <client/player_skeleton.qc>
-#include <client/scoreboard.qc>
 #include <client/shownames.qc>
 #include <client/teamradar.qc>
 #include <client/view.qc>
index 1c66ff781e07ceb95562c9cd57ec7238311a772f..75266dfa2d0aaec18e189dcc84ee21f9e00abcee 100644 (file)
@@ -6,7 +6,6 @@
 #include <client/mapvoting.qh>
 #include <client/miscfunctions.qh>
 #include <client/player_skeleton.qh>
-#include <client/scoreboard.qh>
 #include <client/shownames.qh>
 #include <client/teamradar.qh>
 #include <client/view.qh>
index 0a0959b87ae09bb088725c13a4a8c970a5876264..62b732bec25034e773801113d86aa9f268bfcbf4 100644 (file)
@@ -24,7 +24,7 @@ void Announcer_Countdown(entity this)
        if(roundstarttime == -1)
        {
                Local_Notification(MSG_CENTER, CENTER_COUNTDOWN_ROUNDSTOP);
-               remove(this);
+               delete(this);
                announcer_countdown = NULL;
                return;
        }
@@ -40,7 +40,7 @@ void Announcer_Countdown(entity this)
        {
                Local_Notification(MSG_CENTER, CENTER_COUNTDOWN_BEGIN);
                Local_Notification(MSG_MULTI, MULTI_COUNTDOWN_BEGIN);
-               remove(this);
+               delete(this);
                announcer_countdown = NULL;
                return;
        }
@@ -58,7 +58,7 @@ void Announcer_Countdown(entity this)
                {
                        Local_Notification(MSG_CENTER, CENTER_COUNTDOWN_GAMESTART, countdown_rounded);
                        Notification annce_num = Announcer_PickNumber(CNT_GAMESTART, countdown_rounded);
-                       if(annce_num != NULL)           
+                       if(annce_num != NULL)
                                Local_Notification(MSG_ANNCE, annce_num);
                }
 
@@ -87,7 +87,7 @@ void Announcer_Gamestart()
                        centerprint_kill(ORDINAL(CPID_ROUND));
                        if(announcer_countdown)
                        {
-                               remove(announcer_countdown);
+                               delete(announcer_countdown);
                                announcer_countdown = NULL;
                        }
                }
index d159cd3170e27426c5d40653f8f6141c463e6ccb..0ac857754bd8f8867709ada63c3acc6573e369a7 100644 (file)
@@ -210,6 +210,10 @@ bool autocvar_hud_panel_infomessages_dynamichud = false;
 bool autocvar_hud_panel_physics_dynamichud      = true;
 bool autocvar_hud_panel_centerprint_dynamichud  = true;
 bool autocvar_hud_panel_itemstime_dynamichud    = true;
+bool autocvar_hud_panel_healtharmor_hide_ondeath  = false;
+bool autocvar_hud_panel_ammo_hide_ondeath         = false;
+bool autocvar_hud_panel_powerups_hide_ondeath     = false;
+bool autocvar_hud_panel_weapons_hide_ondeath      = false;
 bool autocvar_hud_panel_ammo;
 bool autocvar_hud_panel_ammo_iconalign;
 int autocvar_hud_panel_ammo_maxammo;
@@ -262,6 +266,7 @@ float autocvar_hud_panel_healtharmor_progressbar_gfx_smooth;
 int autocvar_hud_panel_healtharmor_text;
 bool autocvar_hud_panel_infomessages;
 bool autocvar_hud_panel_infomessages_flip;
+float autocvar_hud_panel_mapvote_highlight_border = 1;
 bool autocvar_hud_panel_modicons;
 int autocvar_hud_panel_modicons_ca_layout;
 int autocvar_hud_panel_modicons_dom_layout;
@@ -395,30 +400,7 @@ float autocvar_r_drawviewmodel;
 int autocvar_r_fakelight;
 int autocvar_r_fullbright;
 float autocvar_r_letterbox;
-bool autocvar_scoreboard_accuracy;
-bool autocvar_scoreboard_accuracy_doublerows;
-bool autocvar_scoreboard_accuracy_nocolors;
-float autocvar_scoreboard_alpha_bg;
-float autocvar_scoreboard_alpha_fg = 1.0;
-float autocvar_scoreboard_alpha_name = 0.9;
-float autocvar_scoreboard_alpha_name_self = 1;
-float autocvar_scoreboard_bg_scale;
-float autocvar_scoreboard_border_thickness;
-float autocvar_scoreboard_color_bg_b;
-float autocvar_scoreboard_color_bg_g;
-float autocvar_scoreboard_color_bg_r;
-float autocvar_scoreboard_color_bg_team;
 string autocvar_scoreboard_columns;
-float autocvar_scoreboard_fadeinspeed = 10;
-float autocvar_scoreboard_fadeoutspeed = 5;
-bool autocvar_scoreboard_highlight;
-float autocvar_scoreboard_highlight_alpha = 0.10;
-float autocvar_scoreboard_highlight_alpha_self = 0.25;
-float autocvar_scoreboard_offset_left;
-float autocvar_scoreboard_offset_right;
-float autocvar_scoreboard_offset_vertical;
-float autocvar_scoreboard_respawntime_decimals;
-bool autocvar_scoreboard_dynamichud = false;
 bool autocvar_v_flipped;
 float autocvar_vid_conheight;
 float autocvar_vid_conwidth;
@@ -464,6 +446,7 @@ string autocvar__cl_playermodel;
 float autocvar_cl_deathglow;
 bool autocvar_developer_csqcentities;
 float autocvar_g_jetpack_attenuation;
+bool autocvar_cl_showspectators;
 string autocvar_crosshair_hmg = "";
 vector autocvar_crosshair_hmg_color = '0.2 1.0 0.2';
 float autocvar_crosshair_hmg_alpha = 1;
@@ -474,4 +457,3 @@ float autocvar_crosshair_rpc_alpha = 1;
 float autocvar_crosshair_rpc_size = 1;
 int autocvar_cl_nade_timer;
 bool autocvar_cl_items_nofade;
-float autocvar_slowmo;
index 100bebf5fa697bd5c0cd3d57acf11ee0dd6fa147..9b8f58f94418e13163a120c30eaefcb3f37bc886 100644 (file)
@@ -307,13 +307,13 @@ void LocalCommand_hud(int request, int argc)
 
                                case "scoreboard_columns_set":
                                {
-                                       Cmd_HUD_SetFields(argc);
+                                       Cmd_Scoreboard_SetFields(argc);
                                        return;
                                }
 
                                case "scoreboard_columns_help":
                                {
-                                       Cmd_HUD_Help();
+                                       Cmd_Scoreboard_Help();
                                        return;
                                }
 
index 65a723389e793645f7f2a674a8277ad85d61f0a8..f1be4315fe5df1caeaaca2b6e29b62031bae2001 100644 (file)
@@ -1,7 +1,7 @@
 #pragma once
 
-void Cmd_HUD_SetFields(int);
-void Cmd_HUD_Help();
+void Cmd_Scoreboard_SetFields(int);
+void Cmd_Scoreboard_Help();
 
 // used by common/command/generic.qc:GenericCommand_dumpcommands to list all commands into a .txt file
 void LocalCommand_macro_write_aliases(int fh);
index 30148bdd44e7f4be1fb88b33d406ae203b525788..d6ee5f8f79add97bf2dfded05615e01788260bab 100644 (file)
@@ -142,7 +142,7 @@ void CSQCPlayer_ModelAppearance_Apply(entity this, bool islocalplayer)
                _setmodel(e, cvar_defstring("_cl_playermodel"));
                forceplayermodels_goodmodel = e.model;
                forceplayermodels_goodmodelindex = e.modelindex;
-               remove(e);
+               delete(e);
        }
 
        // first, try finding it from the server
@@ -175,7 +175,7 @@ void CSQCPlayer_ModelAppearance_Apply(entity this, bool islocalplayer)
                forceplayermodels_model = e.model;
                forceplayermodels_modelindex = e.modelindex;
                forceplayermodels_skin = autocvar__cl_playerskin;
-               remove(e);
+               delete(e);
        }
 
        if(autocvar_cl_forcemyplayermodel != "" && autocvar_cl_forcemyplayermodel != forceplayermodels_mymodel)
@@ -185,7 +185,7 @@ void CSQCPlayer_ModelAppearance_Apply(entity this, bool islocalplayer)
                forceplayermodels_myisgoodmodel = fexists(e.model);
                forceplayermodels_mymodel = e.model;
                forceplayermodels_mymodelindex = e.modelindex;
-               remove(e);
+               delete(e);
        }
 
        // apply it
@@ -369,7 +369,7 @@ int CSQCPlayer_FallbackFrame(entity this, int f)
                case 29: return 4; // anim_duckwalkbackright -> anim_duckwalk
                case 30: return 4; // anim_duckwalkbackleft -> anim_duckwalk
        }
-       LOG_DEBUGF("Frame %d missing in model %s, and we have no fallback - FAIL!\n", f, this.model);
+       LOG_DEBUGF("Frame %d missing in model %s, and we have no fallback - FAIL!", f, this.model);
        return f;
 }
 void CSQCPlayer_FallbackFrame_Apply(entity this)
@@ -433,7 +433,7 @@ void CSQCModel_AutoTagIndex_Apply(entity this)
                                                        // we need to prevent this from 'appening
                                                        this.tag_entity = NULL;
                                                        this.drawmask = 0;
-                                                       LOG_TRACE("h_ model lacks weapon attachment, but v_ model is attached to it\n");
+                                                       LOG_TRACE("h_ model lacks weapon attachment, but v_ model is attached to it");
                                                }
                                        }
                                        else if(this.tag_entity.isplayermodel)
index aa36eec409ba36a501407b4de4e3e0d43498ec46..8305304fe9ae8f65a32bad1cc66426d62f4d3970 100644 (file)
@@ -19,3 +19,4 @@
 // #include "panel/mapvote.qc"
 // #include "panel/itemstime.qc"
 #include "panel/quickmenu.qc"
+#include "panel/scoreboard.qc"
index d575e8cb546eb06ee5ded7a65ef60a864d7db649..c87e733e1d4e633dc2bd28e815d8c885c89ab22e 100644 (file)
@@ -2,7 +2,6 @@
 
 #include "hud_config.qh"
 #include "../mapvoting.qh"
-#include "../scoreboard.qh"
 #include "../teamradar.qh"
 #include <common/t_items.qh>
 #include <common/deathtypes/all.qh>
@@ -383,8 +382,8 @@ void HUD_Panel_Draw(entity panent)
 void HUD_Reset()
 {
        // reset gametype specific icons
-       if(gametype == MAPINFO_TYPE_CTF)
-               HUD_Mod_CTF_Reset();
+       if(gametype.m_modicons_reset)
+               gametype.m_modicons_reset();
 }
 
 float autocvar_hud_dynamic_shake = 1;
@@ -493,14 +492,13 @@ void Hud_Dynamic_Frame()
 void HUD_Main()
 {
        int i;
-       // global hud alpha fade
-       if(menu_enabled == 1)
+       // global hud alpha fade (scoreboard-related panels behave differently and override it temporarly)
+       if(hud_configure_menu_open == 1)
                hud_fade_alpha = 1;
+       else if(!autocvar__hud_configure)
+               hud_fade_alpha = (1 - scoreboard_fade_alpha) * (1 - autocvar__menu_alpha);
        else
-               hud_fade_alpha = (1 - autocvar__menu_alpha);
-
-       if(scoreboard_fade_alpha)
-               hud_fade_alpha = (1 - scoreboard_fade_alpha);
+               hud_fade_alpha = 1 - autocvar__menu_alpha;
 
        HUD_Configure_Frame();
 
@@ -510,8 +508,14 @@ void HUD_Main()
        // they must fade only when the menu does
        if(scoreboard_fade_alpha == 1)
        {
-               HUD_Panel_Draw(HUD_PANEL(CENTERPRINT));
-               return;
+               if(autocvar__menu_alpha == 1)
+                       return;
+               if(scoreboard_fade_alpha == 1)
+               {
+                       HUD_Panel_Draw(HUD_PANEL(SCOREBOARD));
+                       HUD_Panel_Draw(HUD_PANEL(CENTERPRINT));
+                       return;
+               }
        }
 
        if(!autocvar__hud_configure && !hud_fade_alpha)
@@ -602,7 +606,7 @@ void HUD_Main()
                        }
                }
                if (warning)
-                       LOG_TRACE("Automatically fixed wrong/missing panel numbers in _hud_panelorder\n");
+                       LOG_TRACE("Automatically fixed wrong/missing panel numbers in _hud_panelorder");
 
                cvar_set("_hud_panelorder", s);
                if(hud_panelorder_prev)
index 2a53444669b7829c9818ca342ae8bf6484f0fafa..b269312d8871ceb2212ea6fd8beba1f15d28779d 100644 (file)
@@ -88,7 +88,7 @@ int complain_weapon;
 float complain_weapon_type;
 float complain_weapon_time;
 
-int ps_primary, ps_secondary;
+PlayerScoreField ps_primary, ps_secondary;
 int ts_primary, ts_secondary;
 
 Weapon last_switchweapon;
@@ -98,18 +98,11 @@ float weaponprevtime;
 
 float teamnagger;
 
-float hud_configure_checkcollisions;
-float hud_configure_prev;
-vector hud_configure_gridSize;
-vector hud_configure_realGridSize;
-
 int hudShiftState;
 const int S_SHIFT = 1;
 const int S_CTRL = 2;
 const int S_ALT = 4;
 
-float menu_enabled; // 1 showing the entire HUD, 2 showing only the clicked panel
-
 float hud_fade_alpha;
 
 string hud_skin_path;
@@ -235,6 +228,7 @@ REGISTER_HUD_PANEL(MINIGAME_MENU,   HUD_MinigameMenu,   minigamemenu,   PANEL_CO
 REGISTER_HUD_PANEL(MAPVOTE,         MapVote_Draw,       mapvote,        PANEL_CONFIG_NO  , PANEL_SHOW_MAPVOTE )
 REGISTER_HUD_PANEL(ITEMSTIME,       HUD_ItemsTime,      itemstime,      PANEL_CONFIG_MAIN, PANEL_SHOW_MAINGAME)
 REGISTER_HUD_PANEL(QUICKMENU,       HUD_QuickMenu,      quickmenu,      PANEL_CONFIG_MAIN, PANEL_SHOW_MAINGAME)
+REGISTER_HUD_PANEL(SCOREBOARD,      Scoreboard_Draw,    scoreboard,     PANEL_CONFIG_NO  , PANEL_SHOW_ALWAYS  )
 // always add new panels to the end of list
 
 // Because calling lots of functions in QC apparently cuts fps in half on many machines:
@@ -274,12 +268,12 @@ REGISTER_HUD_PANEL(QUICKMENU,       HUD_QuickMenu,      quickmenu,      PANEL_CO
 
 // Get value for panel_bg_color: if "" fetch default, else use panel_bg_color. Convert pants, shirt or teamcolor into a vector.
 #define HUD_Panel_GetColor() MACRO_BEGIN {                                                                          \
-       if ((teamplay) && panel_bg_color_team) {                                                                        \
+       if ((teamplay) && panel_bg_color_team > 0) {                                                                        \
                if (autocvar__hud_configure && myteam == NUM_SPECTATOR)                                                     \
                        panel_bg_color = '1 0 0' * panel_bg_color_team;                                                         \
                else                                                                                                        \
                        panel_bg_color = myteamcolors * panel_bg_color_team;                                                    \
-       } else if (autocvar_hud_configure_teamcolorforced && autocvar__hud_configure && panel_bg_color_team) {          \
+       } else if (autocvar_hud_configure_teamcolorforced && autocvar__hud_configure && panel_bg_color_team > 0) {          \
                panel_bg_color = '1 0 0' * panel_bg_color_team;                                                             \
        } else {                                                                                                        \
                if (panel_bg_color_str == "") {                                                                             \
@@ -315,7 +309,7 @@ REGISTER_HUD_PANEL(QUICKMENU,       HUD_QuickMenu,      quickmenu,      PANEL_CO
        if (autocvar__hud_configure) {                                                                                  \
                if (!panel_enabled)                                                                                         \
                        panel_bg_alpha = 0.25;                                                                                  \
-               else if (menu_enabled == 2 && panel == highlightedPanel)                                                    \
+               else if (hud_configure_menu_open == 2 && panel == highlightedPanel)                                                    \
                        panel_bg_alpha = (1 - autocvar__menu_alpha) * max(cvar("hud_configure_bg_minalpha"), panel_bg_alpha) + autocvar__menu_alpha * panel_bg_alpha;\
                else                                                                                                        \
                        panel_bg_alpha = max(cvar("hud_configure_bg_minalpha"), panel_bg_alpha);                                \
@@ -353,16 +347,16 @@ REGISTER_HUD_PANEL(QUICKMENU,       HUD_QuickMenu,      quickmenu,      PANEL_CO
 // return smoothly faded pos and size of given panel when a dialog is active
 // don't center too wide panels, it doesn't work with different resolutions
 #define HUD_Panel_UpdatePosSize_ForMenu() MACRO_BEGIN { \
-       vector menu_enable_size = panel_size; \
+       vector new_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); \
+               new_size.x = max_panel_width; \
+               new_size.y = panel_size.y * (new_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; \
+       vector new_pos = eX * (panel_bg_border + 0.5 * max_panel_width) + eY * 0.5 * vid_conheight - 0.5 * new_size; \
+       panel_pos = (1 - autocvar__menu_alpha) * panel_pos + (autocvar__menu_alpha) * new_pos; \
+       panel_size = (1 - autocvar__menu_alpha) * panel_size + (autocvar__menu_alpha) * new_size; \
 } MACRO_END
 
 // Scale the pos and size vectors to absolute coordinates
@@ -386,16 +380,16 @@ REGISTER_HUD_PANEL(QUICKMENU,       HUD_QuickMenu,      quickmenu,      PANEL_CO
                panel_bg_padding_str = cvar_string(strcat("hud_panel_", panel.panel_name, "_bg_padding"));                  \
                HUD_Panel_GetBg();                                                                                          \
                if (panel.current_panel_bg != "0") {                                                                        \
-                       HUD_Panel_GetColorTeam();                                                                               \
-                       HUD_Panel_GetColor();                                                                                   \
                        HUD_Panel_GetBgAlpha();                                                                                 \
                        HUD_Panel_GetBorder();                                                                                  \
                }                                                                                                           \
+               HUD_Panel_GetColorTeam();                                                                               \
+               HUD_Panel_GetColor();                                                                                   \
                HUD_Panel_GetFgAlpha();                                                                                     \
                HUD_Panel_GetPadding();                                                                                     \
                panel.current_panel_bg_alpha = panel_bg_alpha;                                                              \
                panel.current_panel_fg_alpha = panel_fg_alpha;                                                              \
-               if (menu_enabled == 2 && panel == highlightedPanel) {                                                       \
+               if (hud_configure_menu_open == 2 && panel == highlightedPanel) {                                                       \
                        HUD_Panel_UpdatePosSize_ForMenu();                                                                      \
                } else {                                                                                                    \
                        panel_bg_alpha *= hud_fade_alpha;                                                                       \
@@ -425,7 +419,7 @@ REGISTER_HUD_PANEL(QUICKMENU,       HUD_QuickMenu,      quickmenu,      PANEL_CO
        panel_pos = stov(cvar_string(strcat("hud_panel_", panel.panel_name, "_pos")));                                  \
        panel_size = stov(cvar_string(strcat("hud_panel_", panel.panel_name, "_size")));                                \
        HUD_Panel_ScalePosSize();                                                                                       \
-       if (menu_enabled == 2 && panel == highlightedPanel) {                                                           \
+       if (hud_configure_menu_open == 2 && panel == highlightedPanel) {                                                           \
                HUD_Panel_UpdatePosSize_ForMenu();                                                                          \
        }                                                                                                               \
        panel_bg_border_str = cvar_string(strcat("hud_panel_", panel.panel_name, "_bg_border"));                        \
index 56a79364d49bbef3142efd7021ce3ea634885463..654d49ba8c60f5ce9f59b3eb40bd2b24877d28fa 100644 (file)
@@ -1,6 +1,7 @@
 #include "hud_config.qh"
 
 #include "hud.qh"
+#include "panel/scoreboard.qh"
 
 #define HUD_Write(s) fputs(fh, s)
 #define HUD_Write_Cvar(cvar) HUD_Write(strcat("seta ", cvar, " \"", cvar_string(cvar), "\"\n"))
@@ -207,6 +208,21 @@ void HUD_Panel_ExportCfg(string cfgname)
                                case HUD_PANEL_QUICKMENU:
                                        HUD_Write_PanelCvar("_align");
                                        break;
+                               case HUD_PANEL_SCOREBOARD:
+                                       HUD_Write_PanelCvar("_fadeinspeed");
+                                       HUD_Write_PanelCvar("_fadeoutspeed");
+                                       HUD_Write_PanelCvar("_respawntime_decimals");
+                                       HUD_Write_PanelCvar("_table_bg_alpha");
+                                       HUD_Write_PanelCvar("_table_bg_scale");
+                                       HUD_Write_PanelCvar("_table_fg_alpha");
+                                       HUD_Write_PanelCvar("_table_fg_alpha_self");
+                                       HUD_Write_PanelCvar("_table_highlight");
+                                       HUD_Write_PanelCvar("_table_highlight_alpha");
+                                       HUD_Write_PanelCvar("_table_highlight_alpha_self");
+                                       HUD_Write_PanelCvar("_bg_teams_color_team");
+                                       HUD_Write_PanelCvar("_accuracy_doublerows");
+                                       HUD_Write_PanelCvar("_accuracy_nocolors");
+                                       break;
                        }
                        HUD_Write("\n");
                }
@@ -221,9 +237,9 @@ void HUD_Panel_ExportCfg(string cfgname)
 
 void HUD_Configure_Exit_Force()
 {
-       if (menu_enabled)
+       if (hud_configure_menu_open)
        {
-               menu_enabled = 0;
+               hud_configure_menu_open = 0;
                localcmd("togglemenu\n");
        }
        cvar_set("_hud_configure", "0");
@@ -727,14 +743,14 @@ float HUD_Panel_InputEvent(float bInputType, float nPrimary, float nSecondary)
        {
                if (bInputType == 1)
                        return true;
-               menu_enabled = 1;
+               hud_configure_menu_open = 1;
                localcmd("menu_showhudexit\n");
        }
        else if(nPrimary == K_BACKSPACE && hudShiftState & S_CTRL)
        {
                if (bInputType == 1)
                        return true;
-               if (!menu_enabled)
+               if (!hud_configure_menu_open)
                        cvar_set("_hud_configure", "0");
        }
        else if(nPrimary == K_TAB && hudShiftState & S_CTRL) // switch panel
@@ -1082,7 +1098,7 @@ void HUD_Panel_Highlight(float allow_move)
 
 void HUD_Panel_EnableMenu()
 {
-       menu_enabled = 2;
+       hud_configure_menu_open = 2;
        localcmd("menu_showhudoptions ", highlightedPanel.panel_name, "\n");
 }
 float mouse_over_panel;
@@ -1181,7 +1197,7 @@ void HUD_Panel_Mouse()
        {
                if(prevMouseClicked)
                        highlightedAction = 0;
-               if(menu_enabled == 2)
+               if(hud_configure_menu_open == 2)
                        mouse_over_panel = 0;
                else
                        mouse_over_panel = HUD_Panel_Check_Mouse_Pos(true);
@@ -1229,7 +1245,7 @@ void HUD_Configure_Frame()
        int i;
        if(autocvar__hud_configure)
        {
-               if(isdemo() || intermission == 2)
+               if(isdemo() || intermission == 2 || scoreboard_active)
                {
                        HUD_Configure_Exit_Force();
                        return;
@@ -1248,7 +1264,7 @@ void HUD_Configure_Frame()
                if(autocvar__menu_alpha != _menu_alpha_prev)
                {
                        if(autocvar__menu_alpha == 0)
-                               menu_enabled = 0;
+                               hud_configure_menu_open = 0;
                        _menu_alpha_prev = autocvar__menu_alpha;
                }
 
@@ -1256,8 +1272,8 @@ void HUD_Configure_Frame()
        }
        else if(hud_configure_prev)
        {
-               if(menu_enabled)
-                       menu_enabled = 0;
+               if(hud_configure_menu_open)
+                       hud_configure_menu_open = 0;
                if(autocvar_hud_cursormode)
                        setcursormode(0);
                hud_dynamic_shake_factor = -1;
index 32c846076145def23fbe3bb769dfbbec2bb63473..6ab64f6aed2a7548f5b51dc36bbb012713c8c9e7 100644 (file)
@@ -8,6 +8,12 @@ int prevMouseClicked; // previous state
 float prevMouseClickedTime; // time during previous left mouse click, to check for doubleclicks
 vector prevMouseClickedPos; // pos during previous left mouse click, to check for doubleclicks
 
+float hud_configure_prev;
+float hud_configure_checkcollisions;
+vector hud_configure_gridSize;
+vector hud_configure_realGridSize;
+float hud_configure_menu_open; // 1 showing the entire HUD, 2 showing only the clicked panel
+
 void HUD_Panel_ExportCfg(string cfgname);
 
 void HUD_Panel_Mouse();
index 5681474b84e75ea22e1894ddfd1aced1948f03b0..d495fdee7670c8874ee45388484abd996092624c 100644 (file)
@@ -18,3 +18,4 @@
 #include <client/hud/panel/timer.qc>
 #include <client/hud/panel/vote.qc>
 #include <client/hud/panel/weapons.qc>
+#include <client/hud/panel/scoreboard.qc>
index 930a3fe02ba8ccc73879bf98039e5b3845e53a3e..fa9b755309da1b4e2b90810e32179230189bd5b9 100644 (file)
@@ -18,3 +18,4 @@
 #include <client/hud/panel/timer.qh>
 #include <client/hud/panel/vote.qh>
 #include <client/hud/panel/weapons.qh>
+#include <client/hud/panel/scoreboard.qh>
index 5c45ff0f331a1544be55bf6b4f3a262d7f704022..bd3ccd068160d9130db8f308fe28548a4c092dad 100644 (file)
@@ -98,8 +98,10 @@ void HUD_Ammo()
        if(hud != HUD_NORMAL) return;
        if(!autocvar__hud_configure)
        {
-               if(!autocvar_hud_panel_ammo) return;
-               if(spectatee_status == -1) return;
+               if((!autocvar_hud_panel_ammo) || (spectatee_status == -1))
+                       return;
+               if(STAT(HEALTH) < 1 && autocvar_hud_panel_ammo_hide_ondeath)
+                       return;
        }
 
        HUD_Panel_UpdateCvars();
index e2e82acffe4efa33ab7275d2bfdb776399da0f70..9dd5f05ff57d6152ba66c05ebdd154a1c2beb79c 100644 (file)
@@ -1,6 +1,6 @@
 #include "centerprint.qh"
 
-#include <client/scoreboard.qh>
+#include "scoreboard.qh"
 
 // CenterPrint (#16)
 
@@ -57,8 +57,7 @@ void centerprint_generic(int new_id, string strMessage, float duration, int coun
                        {
                                // fade out the current msg (duration and countdown_num are ignored)
                                centerprint_time[j] = min(5, autocvar_hud_panel_centerprint_fade_out);
-                               if (centerprint_expire_time[j] > time + min(5, autocvar_hud_panel_centerprint_fade_out) || centerprint_expire_time[j] < time)
-                                       centerprint_expire_time[j] = time + min(5, autocvar_hud_panel_centerprint_fade_out);
+                               centerprint_expire_time[j] = -1; // don't use the variable time here!
                                return;
                        }
                        break; // found a msg with the same id, at position j
@@ -80,14 +79,14 @@ void centerprint_generic(int new_id, string strMessage, float duration, int coun
        if (duration < 0)
        {
                centerprint_time[j] = -1;
-               centerprint_expire_time[j] = time;
+               centerprint_expire_time[j] = -1; // don't use the variable time here!
        }
        else
        {
                if(duration == 0)
                        duration = max(1, autocvar_hud_panel_centerprint_time);
                centerprint_time[j] = duration;
-               centerprint_expire_time[j] = time + duration;
+               centerprint_expire_time[j] = -1; // don't use the variable time here!
        }
        centerprint_countdown_num[j] = countdown_num;
 }
@@ -155,13 +154,14 @@ void HUD_CenterPrint ()
        }
 
        // this panel fades only when the menu does
-       float hud_fade_alpha_save = 0;
-       if(scoreboard_fade_alpha)
-       {
-               hud_fade_alpha_save = hud_fade_alpha;
+       float hud_fade_alpha_save = hud_fade_alpha;
+       if(hud_configure_menu_open == 1)
+               hud_fade_alpha = 1;
+       else
                hud_fade_alpha = 1 - autocvar__menu_alpha;
-       }
+
        HUD_Panel_UpdateCvars();
+       hud_fade_alpha = hud_fade_alpha_save;
 
        if ( HUD_Radar_Clickable() )
        {
@@ -171,17 +171,13 @@ void HUD_CenterPrint ()
                panel_pos = eY * hud_panel_radar_bottom + eX * 0.5 * (vid_conwidth - panel_size_x);
                panel_size_y = min(panel_size_y, vid_conheight - hud_panel_radar_bottom);
        }
-       else if(scoreboard_fade_alpha)
+       else if(!autocvar__hud_configure && scoreboard_fade_alpha)
        {
-               hud_fade_alpha = hud_fade_alpha_save;
-
                // move the panel below the scoreboard
                if (scoreboard_bottom >= 0.96 * vid_conheight)
                        return;
                vector target_pos;
-
                target_pos = eY * scoreboard_bottom + eX * 0.5 * (vid_conwidth - panel_size.x);
-
                if(target_pos.y > panel_pos.y)
                {
                        panel_pos = panel_pos + (target_pos - panel_pos) * sqrt(scoreboard_fade_alpha);
@@ -228,6 +224,13 @@ void HUD_CenterPrint ()
        {
                if (j == CENTERPRINT_MAX_MSGS)
                        j = 0;
+               if (centerprint_expire_time[j] == -1)
+               {
+                       // here we are sure the time variable is not altered by CSQC_Ent_Update
+                       centerprint_expire_time[j] = time;
+                       if (centerprint_time[j] > 0)
+                               centerprint_expire_time[j] += centerprint_time[j];
+               }
                if (centerprint_expire_time[j] <= time)
                {
                        if (centerprint_countdown_num[j] && centerprint_time[j] > 0)
index bc4291a948648e8eb5f8cf843c683cdc17d7ba1c..b56e390b35824802dc07db5bbe60c5f22541ae66 100644 (file)
@@ -8,19 +8,21 @@ void HUD_HealthArmor()
        int armor, health, fuel;
        if(!autocvar__hud_configure)
        {
-               if(!autocvar_hud_panel_healtharmor) return;
+               if((!autocvar_hud_panel_healtharmor) || (spectatee_status == -1))
+                       return;
                if(hud != HUD_NORMAL) return;
-               if(spectatee_status == -1) return;
 
                health = STAT(HEALTH);
                if(health <= 0)
                {
+                       health = 0;
                        prev_health = -1;
-                       return;
+                       if(autocvar_hud_panel_healtharmor_hide_ondeath)
+                               return;
                }
                armor = STAT(ARMOR);
 
-               // code to check for spectatee_status changes is in Ent_ClientData()
+               // code to check for spectatee_status changes is in ENT_CLIENT_CLIENTDATA
                // prev_p_health and prev_health can be set to -1 there
 
                if (prev_p_health == -1)
index 30b7fa8a7929bf46a9b618e3e7c2b67d918b8aa6..d341b6492efdecf606dffde7229e770113b5f1fe 100644 (file)
@@ -5,12 +5,54 @@
 
 // Info messages panel (#14)
 
-#define drawInfoMessage(s) MACRO_BEGIN {                                                                                                                                                       \
-       if(autocvar_hud_panel_infomessages_flip)                                                                                                                                                \
-               o.x = pos.x + mySize.x - stringwidth(s, true, fontsize);                                                                                                        \
-       drawcolorcodedstring(o, s, fontsize, a, DRAWFLAG_NORMAL);                                                                                                               \
-       o.y += fontsize.y;                                                                                                                                                                                              \
+float autocvar_hud_panel_infomessages_group0 = 1;
+float autocvar_hud_panel_infomessages_group_fadetime = 0.4;
+float autocvar_hud_panel_infomessages_group_time = 6;
+const int IMG_COUNT = 1; // number of InfoMessage Groups
+float img_fade[IMG_COUNT];
+int img_cur_msg[IMG_COUNT];
+float img_time[IMG_COUNT];
+
+int img_select(int group_id)
+{
+       float fadetime = max(0.001, autocvar_hud_panel_infomessages_group_fadetime);
+       if(time > img_time[group_id])
+       {
+               img_fade[group_id] = max(0, img_fade[group_id] - frametime / fadetime);
+               if(!img_fade[group_id])
+               {
+                       ++img_cur_msg[group_id];
+                       img_time[group_id] = floor(time) + autocvar_hud_panel_infomessages_group_time;
+               }
+       }
+       else
+               img_fade[group_id] = min(1, img_fade[group_id] + frametime / fadetime);
+       return img_cur_msg[group_id];
+}
+
+float stringwidth_colors(string s, vector theSize);
+vector InfoMessages_drawstring(string s, vector pos, vector sz, float a, vector fontsize)
+{
+       getWrappedLine_remaining = s;
+       float offset = 0;
+       while(getWrappedLine_remaining)
+       {
+               s = getWrappedLine(sz.x - offset, fontsize, stringwidth_colors);
+               if(autocvar_hud_panel_infomessages_flip)
+                       offset = sz.x - stringwidth_colors(s, fontsize) - offset;
+               drawcolorcodedstring(pos + eX * offset, s, fontsize, a, DRAWFLAG_NORMAL);
+               pos.y += fontsize.y;
+               offset = fontsize.x;
+       }
+       pos.y += fontsize.y * 0.25;
+       return pos;
+}
+
+#define InfoMessage(s) MACRO_BEGIN { \
+       pos = InfoMessages_drawstring(s, pos, mySize, ((img_curr_group >= 0) ? panel_fg_alpha * img_fade[img_curr_group] : panel_fg_alpha), fontsize); \
+       img_curr_group = -1; \
 } MACRO_END
+
 void HUD_InfoMessages()
 {
        if(!autocvar__hud_configure)
@@ -34,75 +76,58 @@ void HUD_InfoMessages()
                mySize -= '2 2 0' * panel_bg_padding;
        }
 
-       // always force 5:1 aspect
-       vector newSize = '0 0 0';
-       if(mySize.x/mySize.y > 5)
-       {
-               newSize.x = 5 * mySize.y;
-               newSize.y = mySize.y;
-
-               pos.x = pos.x + (mySize.x - newSize.x) / 2;
-       }
-       else
-       {
-               newSize.y = 1/5 * mySize.x;
-               newSize.x = mySize.x;
-
-               pos.y = pos.y + (mySize.y - newSize.y) / 2;
-       }
-
-       mySize = newSize;
-       entity tm;
-       vector o;
-       o = pos;
-
-       vector fontsize;
-       fontsize = '0.20 0.20 0' * mySize.y;
-
-       float a;
-       a = panel_fg_alpha;
-
+       vector fontsize = '0.2 0.2 0' * mySize.y;
        string s;
+       int img_curr_group = -1;
        if(!autocvar__hud_configure)
        {
                if(spectatee_status)
                {
-                       a = 1;
                        if(spectatee_status == -1)
                                s = _("^1Observing");
                        else
                                s = sprintf(_("^1Spectating: ^7%s"), entcs_GetName(current_player));
-                       drawInfoMessage(s);
-
-                       if(spectatee_status == -1)
-                               s = sprintf(_("^1Press ^3%s^1 to spectate"), getcommandkey("primary fire", "+fire"));
-                       else
-                               s = sprintf(_("^1Press ^3%s^1 or ^3%s^1 for next or previous player"), getcommandkey("next weapon", "weapnext"), getcommandkey("previous weapon", "weapprev"));
-                       drawInfoMessage(s);
-
-                       if(spectatee_status == -1)
-                               s = sprintf(_("^1Use ^3%s^1 or ^3%s^1 to change the speed"), getcommandkey("next weapon", "weapnext"), getcommandkey("previous weapon", "weapprev"));
-                       else
-                               s = sprintf(_("^1Press ^3%s^1 to observe, ^3%s^1 to change camera mode"), getcommandkey("secondary fire", "+fire2"), getcommandkey("drop weapon", "dropweapon"));
-                       drawInfoMessage(s);
+                       InfoMessage(s);
 
-                       s = sprintf(_("^1Press ^3%s^1 for gamemode info"), getcommandkey("server info", "+show_info"));
-                       drawInfoMessage(s);
+                       if(autocvar_hud_panel_infomessages_group0)
+                       {
+                               img_curr_group = 0;
+                               switch(img_select(img_curr_group) % 3)
+                               {
+                                       default:
+                                       case 0:
+                                               if(spectatee_status == -1)
+                                                       s = sprintf(_("^1Press ^3%s^1 to spectate"), getcommandkey(_("primary fire"), "+fire"));
+                                               else
+                                                       s = sprintf(_("^1Press ^3%s^1 or ^3%s^1 for next or previous player"), getcommandkey(_("next weapon"), "weapnext"), getcommandkey(_("previous weapon"), "weapprev"));
+                                               break;
+                                       case 1:
+                                               if(spectatee_status == -1)
+                                                       s = sprintf(_("^1Use ^3%s^1 or ^3%s^1 to change the speed"), getcommandkey(_("next weapon"), "weapnext"), getcommandkey(_("previous weapon"), "weapprev"));
+                                               else
+                                                       s = sprintf(_("^1Press ^3%s^1 to observe, ^3%s^1 to change camera mode"), getcommandkey(_("secondary fire"), "+fire2"), getcommandkey(_("drop weapon"), "dropweapon"));
+                                               break;
+                                       case 2:
+                                               s = sprintf(_("^1Press ^3%s^1 for gamemode info"), getcommandkey(_("server info"), "+show_info"));
+                                               break;
+                               }
+                               InfoMessage(s);
+                       }
 
                        if(gametype == MAPINFO_TYPE_LMS)
                        {
                                entity sk;
                                sk = playerslots[player_localnum];
-                               if(sk.(scores[ps_primary]) >= 666)
+                               if(sk.(scores(ps_primary)) >= 666)
                                        s = _("^1Match has already begun");
-                               else if(sk.(scores[ps_primary]) > 0)
+                               else if(sk.(scores(ps_primary)) > 0)
                                        s = _("^1You have no more lives left");
                                else
-                                       s = sprintf(_("^1Press ^3%s^1 to join"), getcommandkey("jump", "+jump"));
+                                       s = sprintf(_("^1Press ^3%s^1 to join"), getcommandkey(_("jump"), "+jump"));
                        }
                        else
-                               s = sprintf(_("^1Press ^3%s^1 to join"), getcommandkey("jump", "+jump"));
-                       drawInfoMessage(s);
+                               s = sprintf(_("^1Press ^3%s^1 to join"), getcommandkey(_("jump"), "+jump"));
+                       InfoMessage(s);
                }
 
                if (time < STAT(GAMESTARTTIME))
@@ -110,13 +135,13 @@ void HUD_InfoMessages()
                        //we need to ceil, otherwise the countdown would be off by .5 when using round()
                        float countdown = ceil(STAT(GAMESTARTTIME) - time);
                        s = sprintf(_("^1Game starts in ^3%d^1 seconds"), countdown);
-                       drawInfoMessage(s);
+                       InfoMessage(s);
                }
 
                if(warmup_stage)
                {
                        s = _("^2Currently in ^1warmup^2 stage!");
-                       drawInfoMessage(s);
+                       InfoMessage(s);
                }
 
                string blinkcolor;
@@ -130,9 +155,9 @@ void HUD_InfoMessages()
                        if(ready_waiting_for_me)
                        {
                                if(warmup_stage)
-                                       s = sprintf(_("%sPress ^3%s%s to end warmup"), blinkcolor, getcommandkey("ready", "ready"), blinkcolor);
+                                       s = sprintf(_("%sPress ^3%s%s to end warmup"), blinkcolor, getcommandkey(_("ready"), "ready"), blinkcolor);
                                else
-                                       s = sprintf(_("%sPress ^3%s%s once you are ready"), blinkcolor, getcommandkey("ready", "ready"), blinkcolor);
+                                       s = sprintf(_("%sPress ^3%s%s once you are ready"), blinkcolor, getcommandkey(_("ready"), "ready"), blinkcolor);
                        }
                        else
                        {
@@ -141,18 +166,18 @@ void HUD_InfoMessages()
                                else
                                        s = _("^2Waiting for others to ready up...");
                        }
-                       drawInfoMessage(s);
+                       InfoMessage(s);
                }
                else if(warmup_stage && !spectatee_status)
                {
-                       s = sprintf(_("^2Press ^3%s^2 to end warmup"), getcommandkey("ready", "ready"));
-                       drawInfoMessage(s);
+                       s = sprintf(_("^2Press ^3%s^2 to end warmup"), getcommandkey(_("ready"), "ready"));
+                       InfoMessage(s);
                }
 
                if(teamplay && !spectatee_status && gametype != MAPINFO_TYPE_CA && teamnagger)
                {
                        float ts_min = 0, ts_max = 0;
-                       tm = teams.sort_next;
+                       entity tm = teams.sort_next;
                        if (tm)
                        {
                                for (; tm.sort_next; tm = tm.sort_next)
@@ -168,24 +193,36 @@ void HUD_InfoMessages()
                                {
                                        s = strcat(blinkcolor, _("Teamnumbers are unbalanced!"));
                                        tm = GetTeam(myteam, false);
-                                       if (tm)
-                                       if (tm.team != NUM_SPECTATOR)
-                                       if (tm.team_size == ts_max)
-                                               s = strcat(s, sprintf(_(" Press ^3%s%s to adjust"), getcommandkey("team menu", "menu_showteamselect"), blinkcolor));
-                                       drawInfoMessage(s);
+                                       if (tm && tm.team != NUM_SPECTATOR && tm.team_size == ts_max)
+                                               s = strcat(s, sprintf(_(" Press ^3%s%s to adjust"), getcommandkey(_("team menu"), "menu_showteamselect"), blinkcolor));
+                                       InfoMessage(s);
                                }
                        }
                }
+
+               if(autocvar_cl_showspectators)
+               if(num_spectators)
+               //if(spectatee_status != -1)
+               {
+                       s = ((spectatee_status) ? _("^1Spectating this player:") : _("^1Spectating you:"));
+                       // InfoMessage(s)
+                       int limit = min(num_spectators, MAX_SPECTATORS);
+                       for(int i = 0; i < limit; ++i)
+                       {
+                               float slot = spectatorlist[i];
+                               if(i == 0)
+                                       s = strcat(s, " ^7", entcs_GetName(slot));
+                               else
+                                       s = strcat("^7", entcs_GetName(slot));
+                               InfoMessage(s);
+                       }
+               }
        }
        else
        {
-               s = _("^7Press ^3ESC ^7to show HUD options.");
-               drawInfoMessage(s);
-               s = _("^3Doubleclick ^7a panel for panel-specific options.");
-               drawInfoMessage(s);
-               s = _("^3CTRL ^7to disable collision testing, ^3SHIFT ^7and");
-               drawInfoMessage(s);
-               s = _("^3ALT ^7+ ^3ARROW KEYS ^7for fine adjustments.");
-               drawInfoMessage(s);
+               InfoMessage(_("^7Press ^3ESC ^7to show HUD options."));
+               InfoMessage(_("^3Doubleclick ^7a panel for panel-specific options."));
+               InfoMessage(_("^3CTRL ^7to disable collision testing, ^3SHIFT ^7and"));
+               InfoMessage(_("^3ALT ^7+ ^3ARROW KEYS ^7for fine adjustments."));
        }
 }
index 5901a16326ca40047480f5e71d67ae7d783f7cfd..2c99485731ebbf1acef68f063a4c4867bb5bb8b5 100644 (file)
@@ -532,9 +532,9 @@ void HUD_Mod_Race(vector pos, vector mySize)
        entity me;
        me = playerslots[player_localnum];
        float score;
-       score = me.(scores[ps_primary]);
+       score = me.(scores(ps_primary));
 
-       if(!(scores_flags[ps_primary] & SFL_TIME) || teamplay) // race/cts record display on HUD
+       if(!(scores_flags(ps_primary) & SFL_TIME) || teamplay) // race/cts record display on HUD
                return; // no records in the actual race
 
        // clientside personal record
@@ -743,18 +743,7 @@ void HUD_Mod_Dom(vector myPos, vector mySize)
 
 void HUD_ModIcons_SetFunc()
 {
-       switch(gametype)
-       {
-               case MAPINFO_TYPE_KEYHUNT:              HUD_ModIcons_GameType = HUD_Mod_KH; break;
-               case MAPINFO_TYPE_CTF:                  HUD_ModIcons_GameType = HUD_Mod_CTF; break;
-               case MAPINFO_TYPE_NEXBALL:              HUD_ModIcons_GameType = HUD_Mod_NexBall; break;
-               case MAPINFO_TYPE_CTS:
-               case MAPINFO_TYPE_RACE:         HUD_ModIcons_GameType = HUD_Mod_Race; break;
-               case MAPINFO_TYPE_CA:
-               case MAPINFO_TYPE_FREEZETAG:    HUD_ModIcons_GameType = HUD_Mod_CA; break;
-               case MAPINFO_TYPE_DOMINATION:   HUD_ModIcons_GameType = HUD_Mod_Dom; break;
-               case MAPINFO_TYPE_KEEPAWAY:     HUD_ModIcons_GameType = HUD_Mod_Keepaway; break;
-       }
+       HUD_ModIcons_GameType = gametype.m_modicons;
 }
 
 int mod_prev; // previous state of mod_active to check for a change
index 223bf72ce8efae4a679f8c6405673deaf1aac283..7528c2ba2b1a6f89353b6e4cf83116f5ee4a6473 100644 (file)
@@ -68,9 +68,10 @@ void HUD_Powerups()
        // Initialize items
        if(!autocvar__hud_configure)
        {
-               if(!autocvar_hud_panel_powerups) return;
-               if(spectatee_status == -1) return;
-               if(STAT(HEALTH) <= 0) return;
+               if((!autocvar_hud_panel_powerups) || (spectatee_status == -1))
+                       return;
+               if(STAT(HEALTH) <= 0 && autocvar_hud_panel_powerups_hide_ondeath)
+                       return;
                if(!(allItems & (ITEM_Strength.m_itemid | ITEM_Shield.m_itemid | IT_SUPERWEAPON)) && !allBuffs) return;
 
                strengthTime = bound(0, STAT(STRENGTH_FINISHED) - time, 99);
index 4cb5c9fd4e752fbabea639ce94c0658c854cc061..b2d3588844a00a6044e1cf338e3c1f4257a53c0e 100644 (file)
@@ -156,7 +156,7 @@ bool QuickMenu_Open(string mode, string submenu)
        }
        else
        {
-               LOG_WARNINGF("Unrecognized mode %s\n", mode);
+               LOG_WARNF("Unrecognized mode %s", mode);
                return false;
        }
 
@@ -292,7 +292,7 @@ bool QuickMenu_Page_Load(string target_submenu, bool new_page)
                        // printf("^1 skipping %s\n", s);
                }
                if(QuickMenu_Buffer_Index == QuickMenu_Buffer_Size)
-                       LOG_WARNINGF("Couldn't find submenu \"%s\"\n", z_submenu);
+                       LOG_WARNF("Couldn't find submenu \"%s\"", z_submenu);
        }
 
        // only the last page can contain up to QUICKMENU_MAXLINES entries
@@ -866,9 +866,9 @@ void QuickMenu_Default(string target_submenu)
 
        if(target_submenu != "" && !target_submenu_found)
        {
-               LOG_WARNINGF("Couldn't find submenu \"%s\"\n", target_submenu);
+               LOG_WARNF("Couldn't find submenu \"%s\"", target_submenu);
                if(prvm_language != "en")
-                       LOG_WARNINGF("^3Warning: submenu must be in English\n", target_submenu);
+                       LOG_WARNF("^3Warning: submenu must be in English", target_submenu);
                QuickMenu_Buffer_Size = 0;
        }
 }
index b07b84ed33f8001c34779cea4a7bddd9d4db5813..cd0d6fa32a887e6448fe25350ff896e1b185275b 100644 (file)
@@ -1,12 +1,12 @@
 #include "score.qh"
 
-#include <client/scoreboard.qh>
+#include "scoreboard.qh"
 #include <common/ent_cs.qh>
 #include <common/mapinfo.qh>
 
 // Score (#7)
 
-void HUD_UpdatePlayerTeams();
+void Scoreboard_UpdatePlayerTeams();
 void HUD_Score_Rankings(vector pos, vector mySize, entity me)
 {
        float score;
@@ -71,8 +71,8 @@ void HUD_Score_Rankings(vector pos, vector mySize, entity me)
                return;
        }
 
-       if (!scoreboard_fade_alpha) // the scoreboard too calls HUD_UpdatePlayerTeams
-               HUD_UpdatePlayerTeams();
+       if (!scoreboard_fade_alpha) // the scoreboard too calls Scoreboard_UpdatePlayerTeams
+               Scoreboard_UpdatePlayerTeams();
        if (team_count)
        {
                // show team scores in the first line
@@ -80,11 +80,12 @@ void HUD_Score_Rankings(vector pos, vector mySize, entity me)
                for(tm = teams.sort_next; tm; tm = tm.sort_next) {
                        if(tm.team == NUM_SPECTATOR)
                                continue;
-                       if(!tm.team && teamplay)
+                       if(!tm.team)
                                continue;
+
                        if (tm.team == myteam)
                                drawfill(pos + eX * score_size * i, eX * score_size + eY * fontsize.y, '1 1 1', highlight_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
-                       drawstring_aspect(pos + eX * score_size * i, ftos(tm.(teamscores[ts_primary])), eX * score_size + eY * fontsize.y, Team_ColorRGB(tm.team) * 0.8, panel_fg_alpha, DRAWFLAG_NORMAL);
+                       drawstring_aspect(pos + eX * score_size * i, ftos(tm.(teamscores(ts_primary))), eX * score_size + eY * fontsize.y, Team_ColorRGB(tm.team) * 0.8, panel_fg_alpha, DRAWFLAG_NORMAL);
                        ++i;
                }
                first_pl = 1;
@@ -124,7 +125,7 @@ void HUD_Score_Rankings(vector pos, vector mySize, entity me)
                        score_color = Team_ColorRGB(pl.team) * 0.8;
                s = textShortenToWidth(entcs_GetName(pl.sv_entnum), name_size, fontsize, stringwidth_colors);
                drawcolorcodedstring(pos + eX * (name_size - stringwidth(s, true, fontsize)), s, fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
-               drawstring(pos + eX * (name_size + spacing_size), ftos(pl.(scores[ps_primary])), fontsize, score_color, panel_fg_alpha, DRAWFLAG_NORMAL);
+               drawstring(pos + eX * (name_size + spacing_size), ftos(pl.(scores(ps_primary))), fontsize, score_color, panel_fg_alpha, DRAWFLAG_NORMAL);
                pos.y += fontsize.y;
                ++i;
        }
@@ -162,23 +163,23 @@ void HUD_Score()
 
        me = playerslots[current_player];
 
-       if((scores_flags[ps_primary] & SFL_TIME) && !teamplay) { // race/cts record display on HUD
+       if((scores_flags(ps_primary) & SFL_TIME) && !teamplay) { // race/cts record display on HUD
                string timer, distrtimer;
 
                pl = players.sort_next;
                if(pl == me)
                        pl = pl.sort_next;
-               if(scores_flags[ps_primary] & SFL_ZERO_IS_WORST)
-                       if(pl.scores[ps_primary] == 0)
+               if(scores_flags(ps_primary) & SFL_ZERO_IS_WORST)
+                       if(pl.scores(ps_primary) == 0)
                                pl = NULL;
 
-               score = me.(scores[ps_primary]);
+               score = me.(scores(ps_primary));
                timer = TIME_ENCODED_TOSTRING(score);
 
                draw_beginBoldFont();
-               if (pl && ((!(scores_flags[ps_primary] & SFL_ZERO_IS_WORST)) || score)) {
+               if (pl && ((!(scores_flags(ps_primary) & SFL_ZERO_IS_WORST)) || score)) {
                        // distribution display
-                       distribution = me.(scores[ps_primary]) - pl.(scores[ps_primary]);
+                       distribution = me.(scores(ps_primary)) - pl.(scores(ps_primary));
 
                        distrtimer = ftos_decimals(fabs(distribution/pow(10, TIME_DECIMALS)), TIME_DECIMALS);
 
@@ -211,11 +212,11 @@ void HUD_Score()
                if(autocvar__hud_configure)
                        distribution = 42;
                else if(pl)
-                       distribution = me.(scores[ps_primary]) - pl.(scores[ps_primary]);
+                       distribution = me.(scores(ps_primary)) - pl.(scores(ps_primary));
                else
                        distribution = 0;
 
-               score = me.(scores[ps_primary]);
+               score = me.(scores(ps_primary));
                if(autocvar__hud_configure)
                        score = 123;
 
@@ -281,9 +282,10 @@ void HUD_Score()
                for(tm = teams.sort_next; tm; tm = tm.sort_next) {
                        if(tm.team == NUM_SPECTATOR)
                                continue;
-                       if(!tm.team && teamplay)
+                       if(!tm.team)
                                continue;
-                       score = tm.(teamscores[ts_primary]);
+
+                       score = tm.(teamscores(ts_primary));
                        if(autocvar__hud_configure)
                                score = 123;
 
diff --git a/qcsrc/client/hud/panel/scoreboard.qc b/qcsrc/client/hud/panel/scoreboard.qc
new file mode 100644 (file)
index 0000000..9e2acb0
--- /dev/null
@@ -0,0 +1,1542 @@
+#include "scoreboard.qh"
+
+#include "quickmenu.qh"
+#include <common/ent_cs.qh>
+#include <common/constants.qh>
+#include <common/mapinfo.qh>
+#include <common/minigames/cl_minigames.qh>
+#include <common/stats.qh>
+#include <common/teams.qh>
+
+float sbt_bg_alpha;
+float sbt_fg_alpha;
+float sbt_fg_alpha_self;
+bool sbt_highlight;
+float sbt_highlight_alpha;
+float sbt_highlight_alpha_self;
+
+// provide basic panel cvars to old clients
+// TODO remove them after a future release (0.8.2+)
+string autocvar_hud_panel_scoreboard_pos = "0.150000 0.150000";
+string autocvar_hud_panel_scoreboard_size = "0.700000 0.700000";
+string autocvar_hud_panel_scoreboard_bg = "border_default";
+string autocvar_hud_panel_scoreboard_bg_color = "0 0.3 0.5";
+string autocvar_hud_panel_scoreboard_bg_color_team = "";
+string autocvar_hud_panel_scoreboard_bg_alpha = "0.7";
+string autocvar_hud_panel_scoreboard_bg_border = "";
+string autocvar_hud_panel_scoreboard_bg_padding = "";
+
+float autocvar_hud_panel_scoreboard_fadeinspeed = 10;
+float autocvar_hud_panel_scoreboard_fadeoutspeed = 5;
+float autocvar_hud_panel_scoreboard_respawntime_decimals = 1;
+float autocvar_hud_panel_scoreboard_table_bg_alpha = 0;
+float autocvar_hud_panel_scoreboard_table_bg_scale = 0.25;
+float autocvar_hud_panel_scoreboard_table_fg_alpha = 0.9;
+float autocvar_hud_panel_scoreboard_table_fg_alpha_self = 1;
+bool autocvar_hud_panel_scoreboard_table_highlight = true;
+float autocvar_hud_panel_scoreboard_table_highlight_alpha = 0.2;
+float autocvar_hud_panel_scoreboard_table_highlight_alpha_self = 0.4;
+float autocvar_hud_panel_scoreboard_bg_teams_color_team = 0;
+
+bool autocvar_hud_panel_scoreboard_accuracy = true;
+bool autocvar_hud_panel_scoreboard_accuracy_doublerows = false;
+bool autocvar_hud_panel_scoreboard_accuracy_nocolors = false;
+
+bool autocvar_hud_panel_scoreboard_dynamichud = false;
+
+
+void drawstringright(vector, string, vector, vector, float, float);
+void drawstringcenter(vector, string, vector, vector, float, float);
+
+// wrapper to put all possible scores titles through gettext
+string TranslateScoresLabel(string l)
+{
+       switch(l)
+       {
+               case "bckills": return CTX(_("SCO^bckills"));
+               case "bctime": return CTX(_("SCO^bctime"));
+               case "caps": return CTX(_("SCO^caps"));
+               case "captime": return CTX(_("SCO^captime"));
+               case "deaths": return CTX(_("SCO^deaths"));
+               case "destroyed": return CTX(_("SCO^destroyed"));
+               case "dmg": return CTX(_("SCO^dmg"));
+               case "dmgtaken": return CTX(_("SCO^dmgtaken"));
+               case "drops": return CTX(_("SCO^drops"));
+               case "faults": return CTX(_("SCO^faults"));
+               case "fckills": return CTX(_("SCO^fckills"));
+               case "goals": return CTX(_("SCO^goals"));
+               case "kckills": return CTX(_("SCO^kckills"));
+               case "kdratio": return CTX(_("SCO^kdratio"));
+               case "k/d": return CTX(_("SCO^k/d"));
+               case "kd": return CTX(_("SCO^kd"));
+               case "kdr": return CTX(_("SCO^kdr"));
+               case "kills": return CTX(_("SCO^kills"));
+               case "laps": return CTX(_("SCO^laps"));
+               case "lives": return CTX(_("SCO^lives"));
+               case "losses": return CTX(_("SCO^losses"));
+               case "name": return CTX(_("SCO^name"));
+               case "sum": return CTX(_("SCO^sum"));
+               case "nick": return CTX(_("SCO^nick"));
+               case "objectives": return CTX(_("SCO^objectives"));
+               case "pickups": return CTX(_("SCO^pickups"));
+               case "ping": return CTX(_("SCO^ping"));
+               case "pl": return CTX(_("SCO^pl"));
+               case "pushes": return CTX(_("SCO^pushes"));
+               case "rank": return CTX(_("SCO^rank"));
+               case "returns": return CTX(_("SCO^returns"));
+               case "revivals": return CTX(_("SCO^revivals"));
+               case "rounds": return CTX(_("SCO^rounds won"));
+               case "score": return CTX(_("SCO^score"));
+               case "suicides": return CTX(_("SCO^suicides"));
+               case "takes": return CTX(_("SCO^takes"));
+               case "ticks": return CTX(_("SCO^ticks"));
+               default: return l;
+       }
+}
+
+void Scoreboard_InitScores()
+{
+       int i, f;
+
+       ps_primary = ps_secondary = NULL;
+       ts_primary = ts_secondary = -1;
+       FOREACH(Scores, true, {
+               f = (scores_flags(it) & SFL_SORT_PRIO_MASK);
+               if(f == SFL_SORT_PRIO_PRIMARY)
+                       ps_primary = it;
+               if(f == SFL_SORT_PRIO_SECONDARY)
+                       ps_secondary = it;
+       });
+       if(ps_secondary == NULL)
+               ps_secondary = ps_primary;
+
+       for(i = 0; i < MAX_TEAMSCORE; ++i)
+       {
+               f = (teamscores_flags(i) & SFL_SORT_PRIO_MASK);
+               if(f == SFL_SORT_PRIO_PRIMARY)
+                       ts_primary = i;
+               if(f == SFL_SORT_PRIO_SECONDARY)
+                       ts_secondary = i;
+       }
+       if(ts_secondary == -1)
+               ts_secondary = ts_primary;
+
+       Cmd_Scoreboard_SetFields(0);
+}
+
+float SetTeam(entity pl, float Team);
+//float lastpnum;
+void Scoreboard_UpdatePlayerTeams()
+{
+       float Team;
+       entity pl, tmp;
+       float num;
+
+       num = 0;
+       for(pl = players.sort_next; pl; pl = pl.sort_next)
+       {
+               num += 1;
+               Team = entcs_GetScoreTeam(pl.sv_entnum);
+               if(SetTeam(pl, Team))
+               {
+                       tmp = pl.sort_prev;
+                       Scoreboard_UpdatePlayerPos(pl);
+                       if(tmp)
+                               pl = tmp;
+                       else
+                               pl = players.sort_next;
+               }
+       }
+       /*
+       if(num != lastpnum)
+               print(strcat("PNUM: ", ftos(num), "\n"));
+       lastpnum = num;
+       */
+}
+
+int Scoreboard_CompareScore(int vl, int vr, int f)
+{
+    TC(int, vl); TC(int, vr); TC(int, f);
+       if(f & SFL_ZERO_IS_WORST)
+       {
+               if(vl == 0 && vr != 0)
+                       return 1;
+               if(vl != 0 && vr == 0)
+                       return 0;
+       }
+       if(vl > vr)
+               return IS_INCREASING(f);
+       if(vl < vr)
+               return IS_DECREASING(f);
+       return -1;
+}
+
+float Scoreboard_ComparePlayerScores(entity left, entity right)
+{
+       float vl, vr, r;
+       vl = entcs_GetTeam(left.sv_entnum);
+       vr = entcs_GetTeam(right.sv_entnum);
+
+       if(!left.gotscores)
+               vl = NUM_SPECTATOR;
+       if(!right.gotscores)
+               vr = NUM_SPECTATOR;
+
+       if(vl > vr)
+               return true;
+       if(vl < vr)
+               return false;
+
+       if(vl == NUM_SPECTATOR)
+       {
+               // FIRST the one with scores (spectators), THEN the ones without (downloaders)
+               // no other sorting
+               if(!left.gotscores && right.gotscores)
+                       return true;
+               return false;
+       }
+
+       r = Scoreboard_CompareScore(left.scores(ps_primary), right.scores(ps_primary), scores_flags(ps_primary));
+       if (r >= 0)
+               return r;
+
+       r = Scoreboard_CompareScore(left.scores(ps_secondary), right.scores(ps_secondary), scores_flags(ps_secondary));
+       if (r >= 0)
+               return r;
+
+       FOREACH(Scores, true, {
+               r = Scoreboard_CompareScore(left.scores(it), right.scores(it), scores_flags(it));
+               if (r >= 0) return r;
+       });
+
+       if (left.sv_entnum < right.sv_entnum)
+               return true;
+
+       return false;
+}
+
+void Scoreboard_UpdatePlayerPos(entity player)
+{
+       entity ent;
+       for(ent = player.sort_next; ent && Scoreboard_ComparePlayerScores(player, ent); ent = player.sort_next)
+       {
+               SORT_SWAP(player, ent);
+       }
+       for(ent = player.sort_prev; ent != players && Scoreboard_ComparePlayerScores(ent, player); ent = player.sort_prev)
+       {
+               SORT_SWAP(ent, player);
+       }
+}
+
+float Scoreboard_CompareTeamScores(entity left, entity right)
+{
+       int i, r;
+
+       if(left.team == NUM_SPECTATOR)
+               return 1;
+       if(right.team == NUM_SPECTATOR)
+               return 0;
+
+       r = Scoreboard_CompareScore(left.teamscores(ts_primary), right.teamscores(ts_primary), teamscores_flags(ts_primary));
+       if (r >= 0)
+               return r;
+
+       r = Scoreboard_CompareScore(left.teamscores(ts_secondary), right.teamscores(ts_secondary), teamscores_flags(ts_secondary));
+       if (r >= 0)
+               return r;
+
+       for(i = 0; i < MAX_TEAMSCORE; ++i)
+       {
+               r = Scoreboard_CompareScore(left.teamscores(i), right.teamscores(i), teamscores_flags(i));
+               if (r >= 0)
+                       return r;
+       }
+
+       if (left.team < right.team)
+               return true;
+
+       return false;
+}
+
+void Scoreboard_UpdateTeamPos(entity Team)
+{
+       entity ent;
+       for(ent = Team.sort_next; ent && Scoreboard_CompareTeamScores(Team, ent); ent = Team.sort_next)
+       {
+               SORT_SWAP(Team, ent);
+       }
+       for(ent = Team.sort_prev; ent != teams && Scoreboard_CompareTeamScores(ent, Team); ent = Team.sort_prev)
+       {
+               SORT_SWAP(ent, Team);
+       }
+}
+
+void Cmd_Scoreboard_Help()
+{
+       LOG_INFO(_("You can modify the scoreboard using the ^2scoreboard_columns_set command.\n"));
+       LOG_INFO(_("^3|---------------------------------------------------------------|\n"));
+       LOG_INFO(_("Usage:\n"));
+       LOG_INFO(_("^2scoreboard_columns_set default\n"));
+       LOG_INFO(_("^2scoreboard_columns_set ^7field1 field2 ...\n"));
+       LOG_INFO(_("The following field names are recognized (case insensitive):\n"));
+       LOG_INFO(_("You can use a ^3|^7 to start the right-aligned fields.\n"));
+       LOG_INFO("\n");
+
+       LOG_INFO(_("^3name^7 or ^3nick^7             Name of a player\n"));
+       LOG_INFO(_("^3ping^7                     Ping time\n"));
+       LOG_INFO(_("^3pl^7                       Packet loss\n"));
+       LOG_INFO(_("^3elo^7                      Player ELO\n"));
+       LOG_INFO(_("^3kills^7                    Number of kills\n"));
+       LOG_INFO(_("^3deaths^7                   Number of deaths\n"));
+       LOG_INFO(_("^3suicides^7                 Number of suicides\n"));
+       LOG_INFO(_("^3frags^7                    kills - suicides\n"));
+       LOG_INFO(_("^3kd^7                       The kill-death ratio\n"));
+       LOG_INFO(_("^3dmg^7                      The total damage done\n"));
+       LOG_INFO(_("^3dmgtaken^7                 The total damage taken\n"));
+       LOG_INFO(_("^3sum^7                      frags - deaths\n"));
+       LOG_INFO(_("^3caps^7                     How often a flag (CTF) or a key (KeyHunt) was captured\n"));
+       LOG_INFO(_("^3pickups^7                  How often a flag (CTF) or a key (KeyHunt) or a ball (Keepaway) was picked up\n"));
+       LOG_INFO(_("^3captime^7                  Time of fastest cap (CTF)\n"));
+       LOG_INFO(_("^3fckills^7                  Number of flag carrier kills\n"));
+       LOG_INFO(_("^3returns^7                  Number of flag returns\n"));
+       LOG_INFO(_("^3drops^7                    Number of flag drops\n"));
+       LOG_INFO(_("^3lives^7                    Number of lives (LMS)\n"));
+       LOG_INFO(_("^3rank^7                     Player rank\n"));
+       LOG_INFO(_("^3pushes^7                   Number of players pushed into void\n"));
+       LOG_INFO(_("^3destroyed^7                Number of keys destroyed by pushing them into void\n"));
+       LOG_INFO(_("^3kckills^7                  Number of keys carrier kills\n"));
+       LOG_INFO(_("^3losses^7                   Number of times a key was lost\n"));
+       LOG_INFO(_("^3laps^7                     Number of laps finished (race/cts)\n"));
+       LOG_INFO(_("^3time^7                     Total time raced (race/cts)\n"));
+       LOG_INFO(_("^3fastest^7                  Time of fastest lap (race/cts)\n"));
+       LOG_INFO(_("^3ticks^7                    Number of ticks (DOM)\n"));
+       LOG_INFO(_("^3takes^7                    Number of domination points taken (DOM)\n"));
+       LOG_INFO(_("^3bckills^7                  Number of ball carrier kills\n"));
+       LOG_INFO(_("^3bctime^7                   Total amount of time holding the ball in Keepaway\n"));
+       LOG_INFO(_("^3score^7                    Total score\n"));
+       LOG_INFO("\n");
+
+       LOG_INFO(_("Before a field you can put a + or - sign, then a comma separated list\n"
+               "of game types, then a slash, to make the field show up only in these\n"
+               "or in all but these game types. You can also specify 'all' as a\n"
+               "field to show all fields available for the current game mode.\n\n"));
+
+       LOG_INFO(_("The special game type names 'teams' and 'noteams' can be used to\n"
+               "include/exclude ALL teams/noteams game modes.\n\n"));
+
+       LOG_INFO(_("Example: scoreboard_columns_set name ping pl | +ctf/field3 -dm/field4\n"));
+       LOG_INFO(_("will display name, ping and pl aligned to the left, and the fields\n"
+               "right of the vertical bar aligned to the right.\n"));
+       LOG_INFO(_("'field3' will only be shown in CTF, and 'field4' will be shown in all\n"
+               "other gamemodes except DM.\n"));
+}
+
+// NOTE: adding a gametype with ? to not warn for an optional field
+// make sure it's excluded in a previous exclusive rule, if any
+// otherwise the previous exclusive rule warns anyway
+// e.g. -teams,rc,cts,lms/kills ?+rc/kills
+#define SCOREBOARD_DEFAULT_COLUMNS \
+"ping pl name |" \
+" -teams,rc,cts,inv,lms/kills +ft,tdm/kills ?+rc,inv/kills" \
+" -teams,lms/deaths +ft,tdm/deaths" \
+" -teams,lms,rc,cts,inv,ka/suicides +ft,tdm/suicides ?+rc,inv/suicides" \
+" -cts,dm,tdm,ka,ft/frags" /* tdm already has this in "score" */ \
+" -rc,cts,nb/dmg -rc,cts,nb/dmgtaken" \
+" +ctf/caps +ctf/pickups +ctf/fckills +ctf/returns +ons/caps +ons/takes" \
+" +lms/lives +lms/rank" \
+" +kh/caps +kh/pushes +kh/destroyed" \
+" ?+rc/laps ?+rc/time +rc,cts/fastest" \
+" +as/objectives +nb/faults +nb/goals" \
+" +ka/pickups +ka/bckills +ka/bctime +ft/revivals" \
+" -lms,rc,cts,inv,nb/score"
+
+void Cmd_Scoreboard_SetFields(int argc)
+{
+    TC(int, argc);
+       int i, slash;
+       string str, pattern;
+       float have_name = 0, have_primary = 0, have_secondary = 0, have_separator = 0;
+       float missing;
+
+       if(!gametype)
+       {
+               // set up a temporary scoreboard layout
+               // no layout can be properly set up until score_info data haven't been received
+               argc = tokenizebyseparator("0 1 ping pl name | score", " ");
+               ps_primary = SP_SCORE;
+               ps_secondary = SP_SCORE;
+               scores_label(ps_primary) = strzone("score");
+               scores_flags(ps_primary) = SFL_ALLOW_HIDE;
+       }
+
+       // TODO: re enable with gametype dependant cvars?
+       if(argc < 3) // no arguments provided
+               argc = tokenizebyseparator(strcat("0 1 ", autocvar_scoreboard_columns), " ");
+
+       if(argc < 3)
+               argc = tokenizebyseparator(strcat("0 1 ", SCOREBOARD_DEFAULT_COLUMNS), " ");
+
+       if(argc == 3)
+       {
+               if(argv(2) == "default")
+                       argc = tokenizebyseparator(strcat("0 1 ", SCOREBOARD_DEFAULT_COLUMNS), " ");
+               else if(argv(2) == "all")
+               {
+                       string s;
+                       s = "ping pl name |";
+                       FOREACH(Scores, true, {
+                               if(it != ps_primary)
+                               if(it != ps_secondary)
+                               if(scores_label(it) != "")
+                                       s = strcat(s, " ", scores_label(it));
+                       });
+                       if(ps_secondary != ps_primary)
+                               s = strcat(s, " ", scores_label(ps_secondary));
+                       s = strcat(s, " ", scores_label(ps_primary));
+                       argc = tokenizebyseparator(strcat("0 1 ", s), " ");
+               }
+       }
+
+
+       sbt_num_fields = 0;
+
+       hud_fontsize = HUD_GetFontsize("hud_fontsize");
+
+       for(i = 1; i < argc - 1; ++i)
+       {
+               float nocomplain;
+               str = argv(i+1);
+
+               nocomplain = false;
+               if(substring(str, 0, 1) == "?")
+               {
+                       nocomplain = true;
+                       str = substring(str, 1, strlen(str) - 1);
+               }
+
+               slash = strstrofs(str, "/", 0);
+               if(slash >= 0)
+               {
+                       pattern = substring(str, 0, slash);
+                       str = substring(str, slash + 1, strlen(str) - (slash + 1));
+
+                       if (!isGametypeInFilter(gametype, teamplay, false, pattern))
+                               continue;
+               }
+
+               strunzone(sbt_field_title[sbt_num_fields]);
+               sbt_field_title[sbt_num_fields] = strzone(TranslateScoresLabel(str));
+               sbt_field_size[sbt_num_fields] = stringwidth(sbt_field_title[sbt_num_fields], false, hud_fontsize);
+               str = strtolower(str);
+
+               PlayerScoreField j;
+               switch(str)
+               {
+                       case "ping": sbt_field[sbt_num_fields] = SP_PING; break;
+                       case "pl": sbt_field[sbt_num_fields] = SP_PL; break;
+                       case "kd": case "kdr": case "kdratio": case "k/d": sbt_field[sbt_num_fields] = SP_KDRATIO; break;
+                       case "sum": case "diff": case "k-d": sbt_field[sbt_num_fields] = SP_SUM; break;
+                       case "name": case "nick": sbt_field[sbt_num_fields] = SP_NAME; have_name = true; break;
+                       case "|": sbt_field[sbt_num_fields] = SP_SEPARATOR; have_separator = true; break;
+                       case "elo": sbt_field[sbt_num_fields] = SP_ELO; break;
+                       case "dmg": sbt_field[sbt_num_fields] = SP_DMG; break;
+                       case "dmgtaken": sbt_field[sbt_num_fields] = SP_DMGTAKEN; break;
+                       default:
+                       {
+                               FOREACH(Scores, true, {
+                                       if (str == strtolower(scores_label(it))) {
+                                               j = it;
+                                               goto found; // sorry, but otherwise fteqcc -O3 miscompiles this and warns about "unreachable code"
+                                       }
+                               });
+
+LABEL(notfound)
+                               if(str == "frags")
+                                       j = SP_FRAGS;
+                               else
+                               {
+                                       if(!nocomplain)
+                                               LOG_INFOF("^1Error:^7 Unknown score field: '%s'\n", str);
+                                       continue;
+                               }
+LABEL(found)
+                               sbt_field[sbt_num_fields] = j;
+                               if(j == ps_primary)
+                                       have_primary = 1;
+                               if(j == ps_secondary)
+                                       have_secondary = 1;
+
+                       }
+               }
+               ++sbt_num_fields;
+               if(sbt_num_fields >= MAX_SBT_FIELDS)
+                       break;
+       }
+
+       if(scores_flags(ps_primary) & SFL_ALLOW_HIDE)
+               have_primary = 1;
+       if(scores_flags(ps_secondary) & SFL_ALLOW_HIDE)
+               have_secondary = 1;
+       if(ps_primary == ps_secondary)
+               have_secondary = 1;
+       missing = (!have_primary) + (!have_secondary) + (!have_separator) + (!have_name);
+
+       if(sbt_num_fields + missing < MAX_SBT_FIELDS)
+       {
+               if(!have_name)
+               {
+                       strunzone(sbt_field_title[sbt_num_fields]);
+                       for(i = sbt_num_fields; i > 0; --i)
+                       {
+                               sbt_field_title[i] = sbt_field_title[i-1];
+                               sbt_field_size[i] = sbt_field_size[i-1];
+                               sbt_field[i] = sbt_field[i-1];
+                       }
+                       sbt_field_title[0] = strzone(TranslateScoresLabel("name"));
+                       sbt_field[0] = SP_NAME;
+                       ++sbt_num_fields;
+                       LOG_INFO("fixed missing field 'name'\n");
+
+                       if(!have_separator)
+                       {
+                               strunzone(sbt_field_title[sbt_num_fields]);
+                               for(i = sbt_num_fields; i > 1; --i)
+                               {
+                                       sbt_field_title[i] = sbt_field_title[i-1];
+                                       sbt_field_size[i] = sbt_field_size[i-1];
+                                       sbt_field[i] = sbt_field[i-1];
+                               }
+                               sbt_field_title[1] = strzone("|");
+                               sbt_field[1] = SP_SEPARATOR;
+                               sbt_field_size[1] = stringwidth("|", false, hud_fontsize);
+                               ++sbt_num_fields;
+                               LOG_INFO("fixed missing field '|'\n");
+                       }
+               }
+               else if(!have_separator)
+               {
+                       strunzone(sbt_field_title[sbt_num_fields]);
+                       sbt_field_title[sbt_num_fields] = strzone("|");
+                       sbt_field_size[sbt_num_fields] = stringwidth("|", false, hud_fontsize);
+                       sbt_field[sbt_num_fields] = SP_SEPARATOR;
+                       ++sbt_num_fields;
+                       LOG_INFO("fixed missing field '|'\n");
+               }
+               if(!have_secondary)
+               {
+                       strunzone(sbt_field_title[sbt_num_fields]);
+                       sbt_field_title[sbt_num_fields] = strzone(TranslateScoresLabel(scores_label(ps_secondary)));
+                       sbt_field_size[sbt_num_fields] = stringwidth(sbt_field_title[sbt_num_fields], false, hud_fontsize);
+                       sbt_field[sbt_num_fields] = ps_secondary;
+                       ++sbt_num_fields;
+                       LOG_INFOF("fixed missing field '%s'\n", scores_label(ps_secondary));
+               }
+               if(!have_primary)
+               {
+                       strunzone(sbt_field_title[sbt_num_fields]);
+                       sbt_field_title[sbt_num_fields] = strzone(TranslateScoresLabel(scores_label(ps_primary)));
+                       sbt_field_size[sbt_num_fields] = stringwidth(sbt_field_title[sbt_num_fields], false, hud_fontsize);
+                       sbt_field[sbt_num_fields] = ps_primary;
+                       ++sbt_num_fields;
+                       LOG_INFOF("fixed missing field '%s'\n", scores_label(ps_primary));
+               }
+       }
+
+       sbt_field[sbt_num_fields] = SP_END;
+}
+
+// MOVEUP::
+vector sbt_field_rgb;
+string sbt_field_icon0;
+string sbt_field_icon1;
+string sbt_field_icon2;
+vector sbt_field_icon0_rgb;
+vector sbt_field_icon1_rgb;
+vector sbt_field_icon2_rgb;
+float sbt_field_icon0_alpha;
+float sbt_field_icon1_alpha;
+float sbt_field_icon2_alpha;
+string Scoreboard_GetField(entity pl, PlayerScoreField field)
+{
+       float tmp, num, denom;
+       int f;
+       string str;
+       sbt_field_rgb = '1 1 1';
+       sbt_field_icon0 = "";
+       sbt_field_icon1 = "";
+       sbt_field_icon2 = "";
+       sbt_field_icon0_rgb = '1 1 1';
+       sbt_field_icon1_rgb = '1 1 1';
+       sbt_field_icon2_rgb = '1 1 1';
+       sbt_field_icon0_alpha = 1;
+       sbt_field_icon1_alpha = 1;
+       sbt_field_icon2_alpha = 1;
+       switch(field)
+       {
+               case SP_PING:
+                       if (!pl.gotscores)
+                               return "\xE2\x96\xB6\xE2\x96\xB6\xE2\x96\xB6"; // >>> sign using U+25B6
+                       //str = getplayerkeyvalue(pl.sv_entnum, "ping");
+                       f = pl.ping;
+                       if(f == 0)
+                               return _("N/A");
+                       tmp = max(0, min(220, f-80)) / 220;
+                       sbt_field_rgb = '1 1 1' - '0 1 1' * tmp;
+                       return ftos(f);
+
+               case SP_PL:
+                       if (!pl.gotscores)
+                               return _("N/A");
+                       f = pl.ping_packetloss;
+                       tmp = pl.ping_movementloss;
+                       if(f == 0 && tmp == 0)
+                               return "";
+                       str = ftos(ceil(f * 100));
+                       if(tmp != 0)
+                               str = strcat(str, "~", ftos(ceil(tmp * 100)));
+                       tmp = bound(0, f / 0.2 + tmp / 0.04, 1); // 20% is REALLY BAD pl
+                       sbt_field_rgb = '1 0.5 0.5' - '0 0.5 0.5' * tmp;
+                       return str;
+
+               case SP_NAME:
+                       if(ready_waiting && pl.ready)
+                       {
+                               sbt_field_icon0 = "gfx/scoreboard/player_ready";
+                       }
+                       else if(!teamplay)
+                       {
+                               f = stof(getplayerkeyvalue(pl.sv_entnum, "colors"));
+                               {
+                                       sbt_field_icon0 = "gfx/scoreboard/playercolor_base";
+                                       sbt_field_icon1 = "gfx/scoreboard/playercolor_shirt";
+                                       sbt_field_icon1_rgb = colormapPaletteColor(floor(f / 16), 0);
+                                       sbt_field_icon2 = "gfx/scoreboard/playercolor_pants";
+                                       sbt_field_icon2_rgb = colormapPaletteColor(f % 16, 1);
+                               }
+                       }
+                       return entcs_GetName(pl.sv_entnum);
+
+               case SP_FRAGS:
+                       f = pl.(scores(SP_KILLS));
+                       f -= pl.(scores(SP_SUICIDES));
+                       return ftos(f);
+
+               case SP_KDRATIO:
+                       num = pl.(scores(SP_KILLS));
+                       denom = pl.(scores(SP_DEATHS));
+
+                       if(denom == 0) {
+                               sbt_field_rgb = '0 1 0';
+                               str = sprintf("%d", num);
+                       } else if(num <= 0) {
+                               sbt_field_rgb = '1 0 0';
+                               str = sprintf("%.1f", num/denom);
+                       } else
+                               str = sprintf("%.1f", num/denom);
+                       return str;
+
+               case SP_SUM:
+                       f = pl.(scores(SP_KILLS));
+                       f -= pl.(scores(SP_DEATHS));
+
+                       if(f > 0) {
+                               sbt_field_rgb = '0 1 0';
+                       } else if(f == 0) {
+                               sbt_field_rgb = '1 1 1';
+                       } else {
+                               sbt_field_rgb = '1 0 0';
+                       }
+                       return ftos(f);
+
+               case SP_ELO:
+               {
+                       float elo = pl.(scores(SP_ELO));
+                       switch (elo) {
+                               case -1: return "...";
+                               case -2: return _("N/A");
+                               default: return ftos(elo);
+                       }
+               }
+
+               case SP_DMG:
+                       num = pl.(scores(SP_DMG));
+                       denom = 1000;
+
+                       str = sprintf("%.1f k", num/denom);
+                       return str;
+
+               case SP_DMGTAKEN:
+                       num = pl.(scores(SP_DMGTAKEN));
+                       denom = 1000;
+
+                       str = sprintf("%.1f k", num/denom);
+                       return str;
+
+               default:
+                       tmp = pl.(scores(field));
+                       f = scores_flags(field);
+                       if(field == ps_primary)
+                               sbt_field_rgb = '1 1 0';
+                       else if(field == ps_secondary)
+                               sbt_field_rgb = '0 1 1';
+                       else
+                               sbt_field_rgb = '1 1 1';
+                       return ScoreString(f, tmp);
+       }
+       //return "error";
+}
+
+float sbt_fixcolumnwidth_len;
+float sbt_fixcolumnwidth_iconlen;
+float sbt_fixcolumnwidth_marginlen;
+
+string Scoreboard_FixColumnWidth(int i, string str)
+{
+    TC(int, i);
+       float f;
+       vector sz;
+       PlayerScoreField field = sbt_field[i];
+
+       sbt_fixcolumnwidth_iconlen = 0;
+
+       if(sbt_field_icon0 != "")
+       {
+               sz = draw_getimagesize(sbt_field_icon0);
+               f = sz.x / sz.y;
+               if(sbt_fixcolumnwidth_iconlen < f)
+                       sbt_fixcolumnwidth_iconlen = f;
+       }
+
+       if(sbt_field_icon1 != "")
+       {
+               sz = draw_getimagesize(sbt_field_icon1);
+               f = sz.x / sz.y;
+               if(sbt_fixcolumnwidth_iconlen < f)
+                       sbt_fixcolumnwidth_iconlen = f;
+       }
+
+       if(sbt_field_icon2 != "")
+       {
+               sz = draw_getimagesize(sbt_field_icon2);
+               f = sz.x / sz.y;
+               if(sbt_fixcolumnwidth_iconlen < f)
+                       sbt_fixcolumnwidth_iconlen = f;
+       }
+
+       sbt_fixcolumnwidth_iconlen *= hud_fontsize.y / hud_fontsize.x; // fix icon aspect
+
+       if(sbt_fixcolumnwidth_iconlen != 0)
+               sbt_fixcolumnwidth_marginlen = stringwidth(" ", false, hud_fontsize);
+       else
+               sbt_fixcolumnwidth_marginlen = 0;
+
+       if(field == SP_NAME) // name gets all remaining space
+       {
+               int j;
+               float namesize;
+               namesize = panel_size.x;
+               for(j = 0; j < sbt_num_fields; ++j)
+                       if(j != i)
+                               if (sbt_field[i] != SP_SEPARATOR)
+                                       namesize -= sbt_field_size[j] + hud_fontsize.x;
+               sbt_field_size[i] = namesize;
+
+               if (sbt_fixcolumnwidth_iconlen != 0)
+                       namesize -= sbt_fixcolumnwidth_marginlen + sbt_fixcolumnwidth_iconlen * hud_fontsize.x;
+               str = textShortenToWidth(str, namesize, hud_fontsize, stringwidth_colors);
+               sbt_fixcolumnwidth_len = stringwidth(str, true, hud_fontsize);
+       }
+       else
+               sbt_fixcolumnwidth_len = stringwidth(str, false, hud_fontsize);
+
+       f = sbt_fixcolumnwidth_len + sbt_fixcolumnwidth_marginlen + sbt_fixcolumnwidth_iconlen * hud_fontsize.x;
+       if(sbt_field_size[i] < f)
+               sbt_field_size[i] = f;
+
+       return str;
+}
+
+vector Scoreboard_DrawHeader(vector pos, vector rgb)
+{
+       int i;
+       vector column_dim = eY * panel_size.y;
+       vector text_offset = eY * (1.25 - 1) / 2 * hud_fontsize.y;
+       pos.x += hud_fontsize.x * 0.5;
+       for(i = 0; i < sbt_num_fields; ++i)
+       {
+               if(sbt_field[i] == SP_SEPARATOR)
+                       break;
+               column_dim.x = sbt_field_size[i] + hud_fontsize.x;
+               if (sbt_highlight)
+                       if (i % 2)
+                               drawfill(pos - eX * hud_fontsize.x * 0.5, column_dim, '0 0 0', sbt_highlight_alpha, DRAWFLAG_NORMAL);
+               drawstring(pos + text_offset, sbt_field_title[i], hud_fontsize, rgb * 1.5, sbt_fg_alpha, DRAWFLAG_NORMAL);
+               pos.x += column_dim.x;
+       }
+       if(sbt_field[i] == SP_SEPARATOR)
+       {
+               pos.x = panel_pos.x + panel_size.x - hud_fontsize.x * 0.5;
+               for(i = sbt_num_fields - 1; i > 0; --i)
+               {
+                       if(sbt_field[i] == SP_SEPARATOR)
+                               break;
+
+                       pos.x -= sbt_field_size[i];
+
+                       if (sbt_highlight)
+                               if (!(i % 2))
+                               {
+                                       if (i == sbt_num_fields-1)
+                                               column_dim.x = sbt_field_size[i] + hud_fontsize.x * 0.5;
+                                       else
+                                               column_dim.x = sbt_field_size[i] + hud_fontsize.x;
+                                       drawfill(pos - eX * hud_fontsize.x * 0.5, column_dim, '0 0 0', sbt_highlight_alpha, DRAWFLAG_NORMAL);
+                               }
+
+                       text_offset.x = sbt_field_size[i] - stringwidth(sbt_field_title[i], false, hud_fontsize);
+                       drawstring(pos + text_offset, sbt_field_title[i], hud_fontsize, rgb * 1.5, sbt_fg_alpha, DRAWFLAG_NORMAL);
+                       pos.x -= hud_fontsize.x;
+               }
+       }
+
+       pos.x = panel_pos.x;
+       pos.y += 1.25 * hud_fontsize.y;
+       return pos;
+}
+
+void Scoreboard_DrawItem(vector item_pos, vector rgb, entity pl, bool is_self, int pl_number)
+{
+    TC(bool, is_self); TC(int, pl_number);
+       string str;
+       bool is_spec = (entcs_GetTeam(pl.sv_entnum) == NUM_SPECTATOR);
+       if(is_spec && !is_self)
+               rgb = '0 0 0';
+
+       vector h_pos = item_pos;
+       vector h_size = eX * panel_size.x + eY * hud_fontsize.y * 1.25;
+       // alternated rows highlighting
+       if(is_self)
+               drawfill(h_pos, h_size, rgb, sbt_highlight_alpha_self, DRAWFLAG_NORMAL);
+       else if((sbt_highlight) && (!(pl_number % 2)))
+               drawfill(h_pos, h_size, rgb, sbt_highlight_alpha, DRAWFLAG_NORMAL);
+
+       vector pos = item_pos;
+       pos.x += hud_fontsize.x * 0.5;
+       pos.y += (1.25 - 1) / 2 * hud_fontsize.y; // center text vertically
+       vector tmp = '0 0 0';
+       int i;
+       PlayerScoreField field;
+       for(i = 0; i < sbt_num_fields; ++i)
+       {
+               field = sbt_field[i];
+               if(field == SP_SEPARATOR)
+                       break;
+
+               if(is_spec && field != SP_NAME && field != SP_PING) {
+                       pos.x += sbt_field_size[i] + hud_fontsize.x;
+                       continue;
+               }
+               str = Scoreboard_GetField(pl, field);
+               str = Scoreboard_FixColumnWidth(i, str);
+
+               pos.x += sbt_field_size[i] + hud_fontsize.x;
+
+               if(field == SP_NAME) {
+                       tmp.x = sbt_field_size[i] - hud_fontsize.x * sbt_fixcolumnwidth_iconlen - sbt_fixcolumnwidth_marginlen + hud_fontsize.x;
+                       if (is_self)
+                               drawcolorcodedstring(pos - tmp, str, hud_fontsize, sbt_fg_alpha_self, DRAWFLAG_NORMAL);
+                       else
+                               drawcolorcodedstring(pos - tmp, str, hud_fontsize, sbt_fg_alpha, DRAWFLAG_NORMAL);
+               } else {
+                       tmp.x = sbt_fixcolumnwidth_len + hud_fontsize.x;
+                       if (is_self)
+                               drawstring(pos - tmp, str, hud_fontsize, sbt_field_rgb, sbt_fg_alpha_self, DRAWFLAG_NORMAL);
+                       else
+                               drawstring(pos - tmp, str, hud_fontsize, sbt_field_rgb, sbt_fg_alpha, DRAWFLAG_NORMAL);
+               }
+
+               tmp.x = sbt_field_size[i] + hud_fontsize.x;
+               if(sbt_field_icon0 != "")
+                       if (is_self)
+                               drawpic(pos - tmp, sbt_field_icon0, eY * hud_fontsize.y + eX * hud_fontsize.x * sbt_fixcolumnwidth_iconlen, sbt_field_icon1_rgb, sbt_field_icon0_alpha * sbt_fg_alpha_self, DRAWFLAG_NORMAL);
+                       else
+                               drawpic(pos - tmp, sbt_field_icon0, eY * hud_fontsize.y + eX * hud_fontsize.x * sbt_fixcolumnwidth_iconlen, sbt_field_icon1_rgb, sbt_field_icon0_alpha * sbt_fg_alpha, DRAWFLAG_NORMAL);
+               if(sbt_field_icon1 != "")
+                       if (is_self)
+                               drawpic(pos - tmp, sbt_field_icon1, eY * hud_fontsize.y + eX * hud_fontsize.x * sbt_fixcolumnwidth_iconlen, sbt_field_icon1_rgb, sbt_field_icon1_alpha * sbt_fg_alpha_self, DRAWFLAG_NORMAL);
+                       else
+                               drawpic(pos - tmp, sbt_field_icon1, eY * hud_fontsize.y + eX * hud_fontsize.x * sbt_fixcolumnwidth_iconlen, sbt_field_icon1_rgb, sbt_field_icon1_alpha * sbt_fg_alpha, DRAWFLAG_NORMAL);
+               if(sbt_field_icon2 != "")
+                       if (is_self)
+                               drawpic(pos - tmp, sbt_field_icon2, eY * hud_fontsize.y + eX * hud_fontsize.x * sbt_fixcolumnwidth_iconlen, sbt_field_icon2_rgb, sbt_field_icon2_alpha * sbt_fg_alpha_self, DRAWFLAG_NORMAL);
+                       else
+                               drawpic(pos - tmp, sbt_field_icon2, eY * hud_fontsize.y + eX * hud_fontsize.x * sbt_fixcolumnwidth_iconlen, sbt_field_icon2_rgb, sbt_field_icon2_alpha * sbt_fg_alpha, DRAWFLAG_NORMAL);
+       }
+
+       if(sbt_field[i] == SP_SEPARATOR)
+       {
+               pos.x = item_pos.x + panel_size.x - hud_fontsize.x * 0.5;
+               for(i = sbt_num_fields-1; i > 0; --i)
+               {
+                       field = sbt_field[i];
+                       if(field == SP_SEPARATOR)
+                               break;
+
+                       if(is_spec && field != SP_NAME && field != SP_PING) {
+                               pos.x -= sbt_field_size[i] + hud_fontsize.x;
+                               continue;
+                       }
+
+                       str = Scoreboard_GetField(pl, field);
+                       str = Scoreboard_FixColumnWidth(i, str);
+
+                       if(field == SP_NAME) {
+                               tmp.x = sbt_fixcolumnwidth_len; // left or right aligned? let's put it right...
+                               if(is_self)
+                                       drawcolorcodedstring(pos - tmp, str, hud_fontsize, sbt_fg_alpha_self, DRAWFLAG_NORMAL);
+                               else
+                                       drawcolorcodedstring(pos - tmp, str, hud_fontsize, sbt_fg_alpha, DRAWFLAG_NORMAL);
+                       } else {
+                               tmp.x = sbt_fixcolumnwidth_len;
+                               if(is_self)
+                                       drawstring(pos - tmp, str, hud_fontsize, sbt_field_rgb, sbt_fg_alpha_self, DRAWFLAG_NORMAL);
+                               else
+                                       drawstring(pos - tmp, str, hud_fontsize, sbt_field_rgb, sbt_fg_alpha, DRAWFLAG_NORMAL);
+                       }
+
+                       tmp.x = sbt_field_size[i];
+                       if(sbt_field_icon0 != "")
+                               if (is_self)
+                                       drawpic(pos - tmp, sbt_field_icon0, eY * hud_fontsize.y + eX * hud_fontsize.x * sbt_fixcolumnwidth_iconlen, sbt_field_icon1_rgb, sbt_field_icon0_alpha * sbt_fg_alpha_self, DRAWFLAG_NORMAL);
+                               else
+                                       drawpic(pos - tmp, sbt_field_icon0, eY * hud_fontsize.y + eX * hud_fontsize.x * sbt_fixcolumnwidth_iconlen, sbt_field_icon1_rgb, sbt_field_icon0_alpha * sbt_fg_alpha, DRAWFLAG_NORMAL);
+                       if(sbt_field_icon1 != "")
+                               if (is_self)
+                                       drawpic(pos - tmp, sbt_field_icon1, eY * hud_fontsize.y + eX * hud_fontsize.x * sbt_fixcolumnwidth_iconlen, sbt_field_icon1_rgb, sbt_field_icon1_alpha * sbt_fg_alpha_self, DRAWFLAG_NORMAL);
+                               else
+                                       drawpic(pos - tmp, sbt_field_icon1, eY * hud_fontsize.y + eX * hud_fontsize.x * sbt_fixcolumnwidth_iconlen, sbt_field_icon1_rgb, sbt_field_icon1_alpha * sbt_fg_alpha, DRAWFLAG_NORMAL);
+                       if(sbt_field_icon2 != "")
+                               if (is_self)
+                                       drawpic(pos - tmp, sbt_field_icon2, eY * hud_fontsize.y + eX * hud_fontsize.x * sbt_fixcolumnwidth_iconlen, sbt_field_icon2_rgb, sbt_field_icon2_alpha * sbt_fg_alpha_self, DRAWFLAG_NORMAL);
+                               else
+                                       drawpic(pos - tmp, sbt_field_icon2, eY * hud_fontsize.y + eX * hud_fontsize.x * sbt_fixcolumnwidth_iconlen, sbt_field_icon2_rgb, sbt_field_icon2_alpha * sbt_fg_alpha, DRAWFLAG_NORMAL);
+                       pos.x -= sbt_field_size[i] + hud_fontsize.x;
+               }
+       }
+
+       if(pl.eliminated)
+               drawfill(h_pos, h_size, '0 0 0', 0.5 * panel_fg_alpha, DRAWFLAG_NORMAL);
+}
+
+vector Scoreboard_MakeTable(vector pos, entity tm, vector rgb, vector bg_size)
+{
+       entity pl;
+
+       panel_pos = pos;
+       panel_size.y = 1.25 * hud_fontsize.y * (1 + max(1, tm.team_size));
+       panel_size.y += panel_bg_padding * 2;
+       HUD_Panel_DrawBg(scoreboard_fade_alpha);
+
+       vector end_pos = panel_pos + eY * (panel_size.y + hud_fontsize.y);
+       if(panel.current_panel_bg != "0")
+               end_pos.y += panel_bg_border * 2;
+
+       if(panel_bg_padding)
+       {
+               panel_pos += '1 1 0' * panel_bg_padding;
+               panel_size -= '2 2 0' * panel_bg_padding;
+       }
+
+       pos = panel_pos;
+       vector tmp = eX * panel_size.x + eY * 1.25 * hud_fontsize.y;
+
+       // rounded header
+       if (sbt_bg_alpha)
+               drawpic(pos, "gfx/scoreboard/scoreboard_tableheader", tmp, rgb + '0.5 0.5 0.5', sbt_bg_alpha, DRAWFLAG_NORMAL);
+
+       pos.y += 1.25 * hud_fontsize.y;
+
+       // table background
+       tmp.y = panel_size.y - 1.25 * hud_fontsize.y;
+       if (sbt_bg_alpha)
+               drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb, sbt_bg_alpha, DRAWFLAG_NORMAL);
+
+
+       // print header row and highlight columns
+       pos = Scoreboard_DrawHeader(panel_pos, rgb);
+
+       // fill the table and draw the rows
+       int i = 0;
+       if (teamplay)
+               for(pl = players.sort_next; pl; pl = pl.sort_next)
+               {
+                       if(pl.team != tm.team)
+                               continue;
+                       Scoreboard_DrawItem(pos, rgb, pl, (pl.sv_entnum == player_localnum), i);
+                       pos.y += 1.25 * hud_fontsize.y;
+                       ++i;
+               }
+       else
+               for(pl = players.sort_next; pl; pl = pl.sort_next)
+               {
+                       if(pl.team == NUM_SPECTATOR)
+                               continue;
+                       Scoreboard_DrawItem(pos, rgb, pl, (pl.sv_entnum == player_localnum), i);
+                       pos.y += 1.25 * hud_fontsize.y;
+                       ++i;
+               }
+
+       panel_size.x += panel_bg_padding * 2; // restore initial width
+       return end_pos;
+}
+
+float Scoreboard_WouldDraw() {
+       if (QuickMenu_IsOpened())
+               return 0;
+       else if (HUD_Radar_Clickable())
+               return 0;
+       else if (scoreboard_showscores)
+               return 1;
+       else if (intermission == 1)
+               return 1;
+       else if (intermission == 2)
+               return 0;
+       else if (spectatee_status != -1 && STAT(HEALTH) <= 0 && autocvar_cl_deathscoreboard && gametype != MAPINFO_TYPE_CTS && !active_minigame)
+               return 1;
+       else if (scoreboard_showscores_force)
+               return 1;
+       return 0;
+}
+
+float average_accuracy;
+vector Scoreboard_AccuracyStats_Draw(vector pos, vector rgb, vector bg_size)
+{
+       WepSet weapons_stat = WepSet_GetFromStat();
+       WepSet weapons_inmap = WepSet_GetFromStat_InMap();
+       int disownedcnt = 0;
+       FOREACH(Weapons, it != WEP_Null, {
+               int weapon_stats = weapon_accuracy[i - WEP_FIRST];
+
+               WepSet set = it.m_wepset;
+               if (weapon_stats < 0 && !(weapons_stat & set || weapons_inmap & set))
+                       ++disownedcnt;
+       });
+
+       int weapon_cnt = (Weapons_COUNT - 1) - disownedcnt;
+       if (weapon_cnt <= 0) return pos;
+
+       int rows = 1;
+       if (autocvar_hud_panel_scoreboard_accuracy_doublerows && weapon_cnt >= floor((Weapons_COUNT - 1) * 0.5))
+               rows = 2;
+       int columnns = ceil(weapon_cnt / rows);
+
+       float height = 40;
+
+       drawstring(pos + eX * panel_bg_padding, sprintf(_("Accuracy stats (average %d%%)"), average_accuracy), hud_fontsize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+       pos.y += 1.25 * hud_fontsize.y;
+       if(panel.current_panel_bg != "0")
+               pos.y += panel_bg_border;
+
+       panel_pos = pos;
+       panel_size.y = height * rows;
+       panel_size.y += panel_bg_padding * 2;
+       HUD_Panel_DrawBg(scoreboard_fade_alpha);
+
+       vector end_pos = panel_pos + eY * (panel_size.y + hud_fontsize.y);
+       if(panel.current_panel_bg != "0")
+               end_pos.y += panel_bg_border * 2;
+
+       if(panel_bg_padding)
+       {
+               panel_pos += '1 1 0' * panel_bg_padding;
+               panel_size -= '2 2 0' * panel_bg_padding;
+       }
+
+       pos = panel_pos;
+       vector tmp = panel_size;
+
+       float fontsize = height * 1/3;
+       float weapon_height = height * 2/3;
+       float weapon_width = tmp.x / columnns / rows;
+
+       if (sbt_bg_alpha)
+               drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb, sbt_bg_alpha, DRAWFLAG_NORMAL);
+
+       if(sbt_highlight)
+       {
+               // column highlighting
+               for (int i = 0; i < columnns; ++i)
+                       if ((i % 2) == 0)
+                               drawfill(pos + eX * weapon_width * rows * i, eY * height * rows + eX * weapon_width * rows, '0 0 0', sbt_highlight_alpha, DRAWFLAG_NORMAL);
+
+               // row highlighting
+               for (int i = 0; i < rows; ++i)
+                       drawfill(pos + eY * weapon_height + eY * height * i, eX * tmp.x + eY * fontsize, '1 1 1', sbt_highlight_alpha, DRAWFLAG_NORMAL);
+       }
+
+       average_accuracy = 0;
+       int weapons_with_stats = 0;
+       if (rows == 2)
+               pos.x += weapon_width / 2;
+
+       if (autocvar_hud_panel_scoreboard_accuracy_nocolors)
+               rgb = '1 1 1';
+       else
+               Accuracy_LoadColors();
+
+       float oldposx = pos.x;
+       vector tmpos = pos;
+
+       int column = 0;
+       FOREACH(Weapons, it != WEP_Null, {
+               int weapon_stats = weapon_accuracy[i - WEP_FIRST];
+
+               WepSet set = it.m_wepset;
+               if (weapon_stats < 0 && !(weapons_stat & set || weapons_inmap & set))
+                       continue;
+
+               float weapon_alpha;
+               if (weapon_stats >= 0)
+                       weapon_alpha = sbt_fg_alpha;
+               else
+                       weapon_alpha = 0.2 * sbt_fg_alpha;
+
+               // weapon icon
+               drawpic_aspect_skin(tmpos, it.model2, eX * weapon_width + eY * weapon_height, '1 1 1', weapon_alpha, DRAWFLAG_NORMAL);
+               // the accuracy
+               if (weapon_stats >= 0) {
+                       weapons_with_stats += 1;
+                       average_accuracy += weapon_stats; // store sum of all accuracies in average_accuracy
+
+                       string s;
+                       s = sprintf("%d%%", weapon_stats * 100);
+
+                       float padding;
+                       padding = (weapon_width - stringwidth(s, false, eX * fontsize)) / 2; // center the accuracy value
+
+                       if(!autocvar_hud_panel_scoreboard_accuracy_nocolors)
+                               rgb = Accuracy_GetColor(weapon_stats);
+
+                       drawstring(tmpos + eX * padding + eY * weapon_height, s, '1 1 0' * fontsize, rgb, sbt_fg_alpha, DRAWFLAG_NORMAL);
+               }
+               tmpos.x += weapon_width * rows;
+               pos.x += weapon_width * rows;
+               if (rows == 2 && column == columnns - 1) {
+                       tmpos.x = oldposx;
+                       tmpos.y += height;
+                       pos.y += height;
+               }
+               ++column;
+       });
+
+       if (weapons_with_stats)
+               average_accuracy = floor((average_accuracy * 100 / weapons_with_stats) + 0.5);
+
+       panel_size.x += panel_bg_padding * 2; // restore initial width
+       return end_pos;
+}
+
+vector MapStats_DrawKeyValue(vector pos, string key, string value) {
+       float px = pos.x;
+       pos.x += hud_fontsize.x * 0.25;
+       drawstring(pos, key, hud_fontsize, '1 1 1', sbt_fg_alpha, DRAWFLAG_NORMAL);
+       pos.x = panel_pos.x + panel_size.x - stringwidth(value, false, hud_fontsize) - hud_fontsize.x * 0.25;
+       drawstring(pos, value, hud_fontsize, '1 1 1', sbt_fg_alpha, DRAWFLAG_NORMAL);
+       pos.x = px;
+       pos.y += hud_fontsize.y;
+
+       return pos;
+}
+
+vector Scoreboard_MapStats_Draw(vector pos, vector rgb, vector bg_size) {
+       float stat_secrets_found, stat_secrets_total;
+       float stat_monsters_killed, stat_monsters_total;
+       float rows = 0;
+       string val;
+
+       // get monster stats
+       stat_monsters_killed = STAT(MONSTERS_KILLED);
+       stat_monsters_total = STAT(MONSTERS_TOTAL);
+
+       // get secrets stats
+       stat_secrets_found = STAT(SECRETS_FOUND);
+       stat_secrets_total = STAT(SECRETS_TOTAL);
+
+       // get number of rows
+       if(stat_secrets_total)
+               rows += 1;
+       if(stat_monsters_total)
+               rows += 1;
+
+       // if no rows, return
+       if (!rows)
+               return pos;
+
+       //  draw table header
+       drawstring(pos + eX * panel_bg_padding, _("Map stats:"), hud_fontsize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+       pos.y += 1.25 * hud_fontsize.y;
+       if(panel.current_panel_bg != "0")
+               pos.y += panel_bg_border;
+
+       panel_pos = pos;
+       panel_size.y = hud_fontsize.y * rows;
+       panel_size.y += panel_bg_padding * 2;
+       HUD_Panel_DrawBg(scoreboard_fade_alpha);
+
+       vector end_pos = panel_pos + eY * (panel_size.y + hud_fontsize.y);
+       if(panel.current_panel_bg != "0")
+               end_pos.y += panel_bg_border * 2;
+
+       if(panel_bg_padding)
+       {
+               panel_pos += '1 1 0' * panel_bg_padding;
+               panel_size -= '2 2 0' * panel_bg_padding;
+       }
+
+       pos = panel_pos;
+       vector tmp = panel_size;
+
+       if (sbt_bg_alpha)
+               drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb, sbt_bg_alpha, DRAWFLAG_NORMAL);
+
+       // draw monsters
+       if(stat_monsters_total)
+       {
+               val = sprintf("%d/%d", stat_monsters_killed, stat_monsters_total);
+               pos = MapStats_DrawKeyValue(pos, _("Monsters killed:"), val);
+       }
+
+       // draw secrets
+       if(stat_secrets_total)
+       {
+               val = sprintf("%d/%d", stat_secrets_found, stat_secrets_total);
+               pos = MapStats_DrawKeyValue(pos, _("Secrets found:"), val);
+       }
+
+       panel_size.x += panel_bg_padding * 2; // restore initial width
+       return end_pos;
+}
+
+
+vector Scoreboard_Rankings_Draw(vector pos, entity pl, vector rgb, vector bg_size)
+{
+       int i;
+       RANKINGS_RECEIVED_CNT = 0;
+       for (i=RANKINGS_CNT-1; i>=0; --i)
+               if (grecordtime[i])
+                       ++RANKINGS_RECEIVED_CNT;
+
+       if (RANKINGS_RECEIVED_CNT == 0)
+               return pos;
+
+       vector hl_rgb = rgb + '0.5 0.5 0.5';
+
+       pos.y += hud_fontsize.y;
+       drawstring(pos + eX * panel_bg_padding, _("Rankings"), hud_fontsize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+       pos.y += 1.25 * hud_fontsize.y;
+       if(panel.current_panel_bg != "0")
+               pos.y += panel_bg_border;
+
+       panel_pos = pos;
+       panel_size.y = 1.25 * hud_fontsize.y * RANKINGS_RECEIVED_CNT;
+       panel_size.y += panel_bg_padding * 2;
+       HUD_Panel_DrawBg(scoreboard_fade_alpha);
+
+       vector end_pos = panel_pos + eY * (panel_size.y + hud_fontsize.y);
+       if(panel.current_panel_bg != "0")
+               end_pos.y += panel_bg_border * 2;
+
+       if(panel_bg_padding)
+       {
+               panel_pos += '1 1 0' * panel_bg_padding;
+               panel_size -= '2 2 0' * panel_bg_padding;
+       }
+
+       pos = panel_pos;
+       vector tmp = panel_size;
+
+       if (sbt_bg_alpha)
+               drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb, sbt_bg_alpha, DRAWFLAG_NORMAL);
+
+       // row highlighting
+       for(i = 0; i < RANKINGS_RECEIVED_CNT; ++i)
+       {
+               string n, p;
+               float t;
+               t = grecordtime[i];
+               if (t == 0)
+                       continue;
+               n = grecordholder[i];
+               p = count_ordinal(i+1);
+               if(grecordholder[i] == entcs_GetName(player_localnum))
+                       drawfill(pos, eX * panel_size.x + '0 1.25 0' * hud_fontsize.y, hl_rgb, sbt_highlight_alpha_self, DRAWFLAG_NORMAL);
+               else if(!(i % 2) && sbt_highlight)
+                       drawfill(pos, eX * panel_size.x + '0 1.25 0' * hud_fontsize.y, hl_rgb, sbt_highlight_alpha, DRAWFLAG_NORMAL);
+               drawstring(pos, p, '1 1 0' * hud_fontsize.y, '1 1 1', sbt_fg_alpha, DRAWFLAG_NORMAL);
+               drawstring(pos + '3 0 0' * hud_fontsize.y, TIME_ENCODED_TOSTRING(t), '1 1 0' * hud_fontsize.y, '1 1 1', sbt_fg_alpha, DRAWFLAG_NORMAL);
+               drawcolorcodedstring(pos + '8 0 0' * hud_fontsize.y, n, '1 1 0' * hud_fontsize.y, sbt_fg_alpha, DRAWFLAG_NORMAL);
+               pos.y += 1.25 * hud_fontsize.y;
+       }
+
+       panel_size.x += panel_bg_padding * 2; // restore initial width
+       return end_pos;
+}
+
+void Scoreboard_Draw()
+{
+       if(!autocvar__hud_configure)
+       {
+               // frametime checks allow to toggle the scoreboard even when the game is paused
+               if(scoreboard_active) {
+                       if(hud_configure_menu_open == 1)
+                               scoreboard_fade_alpha = 1;
+                       float scoreboard_fadeinspeed = autocvar_hud_panel_scoreboard_fadeinspeed;
+                       if (scoreboard_fadeinspeed && frametime)
+                               scoreboard_fade_alpha = min(1, scoreboard_fade_alpha + frametime * scoreboard_fadeinspeed);
+                       else
+                               scoreboard_fade_alpha = 1;
+               }
+               else {
+                       float scoreboard_fadeoutspeed = autocvar_hud_panel_scoreboard_fadeoutspeed;
+                       if (scoreboard_fadeoutspeed && frametime)
+                               scoreboard_fade_alpha = max(0, scoreboard_fade_alpha - frametime * scoreboard_fadeoutspeed);
+                       else
+                               scoreboard_fade_alpha = 0;
+               }
+
+               if (!scoreboard_fade_alpha)
+                       return;
+       }
+       else
+               scoreboard_fade_alpha = 0;
+
+       if (autocvar_hud_panel_scoreboard_dynamichud)
+               HUD_Scale_Enable();
+       else
+               HUD_Scale_Disable();
+
+       float hud_fade_alpha_save = hud_fade_alpha;
+       if(hud_configure_menu_open == 1)
+               hud_fade_alpha = 1;
+       else
+               hud_fade_alpha = scoreboard_fade_alpha * (1 - autocvar__menu_alpha);
+       HUD_Panel_UpdateCvars();
+
+       sbt_bg_alpha = autocvar_hud_panel_scoreboard_table_bg_alpha * panel_fg_alpha;
+       sbt_highlight = autocvar_hud_panel_scoreboard_table_highlight;
+       sbt_highlight_alpha = autocvar_hud_panel_scoreboard_table_highlight_alpha * panel_fg_alpha;
+       sbt_highlight_alpha_self = autocvar_hud_panel_scoreboard_table_highlight_alpha_self * panel_fg_alpha;
+       sbt_fg_alpha = autocvar_hud_panel_scoreboard_table_fg_alpha * panel_fg_alpha;
+       sbt_fg_alpha_self = autocvar_hud_panel_scoreboard_table_fg_alpha_self * panel_fg_alpha;
+
+       hud_fade_alpha = hud_fade_alpha_save;
+
+       // don't overlap with con_notify
+       if(!autocvar__hud_configure)
+               panel_pos.y = max((autocvar_con_notify * autocvar_con_notifysize), panel_pos.y);
+
+       Scoreboard_UpdatePlayerTeams();
+
+       vector pos, tmp;
+       entity pl, tm;
+       string str;
+
+       // Initializes position
+       pos = panel_pos;
+
+       // Heading
+       vector sb_heading_fontsize;
+       sb_heading_fontsize = hud_fontsize * 2;
+       draw_beginBoldFont();
+       drawstring(pos + eX * panel_bg_padding, _("Scoreboard"), sb_heading_fontsize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+       draw_endBoldFont();
+
+       pos.y += sb_heading_fontsize.y;
+       if(panel.current_panel_bg != "0")
+               pos.y += panel_bg_border;
+
+       // Draw the scoreboard
+       float scale = autocvar_hud_panel_scoreboard_table_bg_scale;
+       if(scale <= 0)
+               scale = 0.25;
+       vector bg_size = draw_getimagesize("gfx/scoreboard/scoreboard_bg") * scale;
+
+       if(teamplay)
+       {
+               vector panel_bg_color_save = panel_bg_color;
+               vector team_score_baseoffset = eY * hud_fontsize.y - eX * hud_fontsize.x * 0.5;
+               if(panel.current_panel_bg != "0")
+                       team_score_baseoffset.x -= panel_bg_border;
+               for(tm = teams.sort_next; tm; tm = tm.sort_next)
+               {
+                       if(tm.team == NUM_SPECTATOR)
+                               continue;
+                       if(!tm.team)
+                               continue;
+
+                       draw_beginBoldFont();
+                       vector rgb = Team_ColorRGB(tm.team);
+                       str = ftos(tm.(teamscores(ts_primary)));
+                       drawstring(pos + team_score_baseoffset - eX * stringwidth(str, false, hud_fontsize * 1.5), str, hud_fontsize * 1.5, rgb, panel_fg_alpha, DRAWFLAG_NORMAL);
+
+                       if(ts_primary != ts_secondary)
+                       {
+                               str = ftos(tm.(teamscores(ts_secondary)));
+                               drawstring(pos + team_score_baseoffset - eX * stringwidth(str, false, hud_fontsize) + eY * hud_fontsize.y * 1.5, str, hud_fontsize, rgb, panel_fg_alpha, DRAWFLAG_NORMAL);
+                       }
+                       draw_endBoldFont();
+                       if(autocvar_hud_panel_scoreboard_bg_teams_color_team > 0)
+                               panel_bg_color = rgb * autocvar_hud_panel_scoreboard_bg_teams_color_team;
+                       else if(panel_bg_color_team > 0)
+                               panel_bg_color = rgb * panel_bg_color_team;
+                       else
+                               panel_bg_color = rgb;
+                       pos = Scoreboard_MakeTable(pos, tm, panel_bg_color, bg_size);
+               }
+               panel_bg_color = panel_bg_color_save;
+       }
+       else
+       {
+               for(tm = teams.sort_next; tm; tm = tm.sort_next)
+               {
+                       if(tm.team == NUM_SPECTATOR)
+                               continue;
+
+                       pos = Scoreboard_MakeTable(pos, tm, panel_bg_color, bg_size);
+               }
+       }
+
+       if(gametype == MAPINFO_TYPE_CTS || gametype == MAPINFO_TYPE_RACE) {
+               if(race_speedaward) {
+                       drawcolorcodedstring(pos, sprintf(_("Speed award: %d%s ^7(%s^7)"), race_speedaward, race_speedaward_unit, race_speedaward_holder), hud_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
+                       pos.y += 1.25 * hud_fontsize.y;
+               }
+               if(race_speedaward_alltimebest) {
+                       drawcolorcodedstring(pos, sprintf(_("All-time fastest: %d%s ^7(%s^7)"), race_speedaward_alltimebest, race_speedaward_alltimebest_unit, race_speedaward_alltimebest_holder), hud_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
+                       pos.y += 1.25 * hud_fontsize.y;
+               }
+               pos = Scoreboard_Rankings_Draw(pos, playerslots[player_localnum], panel_bg_color, bg_size);
+       }
+       else if (autocvar_hud_panel_scoreboard_accuracy && !warmup_stage && gametype != MAPINFO_TYPE_NEXBALL)
+               pos = Scoreboard_AccuracyStats_Draw(pos, panel_bg_color, bg_size);
+
+       pos = Scoreboard_MapStats_Draw(pos, panel_bg_color, bg_size);
+
+       // List spectators
+       float specs = 0;
+       tmp = pos;
+       for(pl = players.sort_next; pl; pl = pl.sort_next)
+       {
+               if(pl.team != NUM_SPECTATOR)
+                       continue;
+               pos.y += 1.25 * hud_fontsize.y;
+               Scoreboard_DrawItem(pos, panel_bg_color, pl, (pl.sv_entnum == player_localnum), specs);
+               ++specs;
+       }
+
+       if(specs)
+       {
+               draw_beginBoldFont();
+               drawstring(tmp, _("Spectators"), hud_fontsize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+               draw_endBoldFont();
+               pos.y += 1.25 * hud_fontsize.y;
+       }
+
+       // Print info string
+       float tl, fl, ll;
+       str = sprintf(_("playing ^3%s^7 on ^2%s^7"), MapInfo_Type_ToText(gametype), shortmapname);
+       tl = STAT(TIMELIMIT);
+       fl = STAT(FRAGLIMIT);
+       ll = STAT(LEADLIMIT);
+       if(gametype == MAPINFO_TYPE_LMS)
+       {
+               if(tl > 0)
+                       str = strcat(str, sprintf(_(" for up to ^1%1.0f minutes^7"), tl));
+       }
+       else
+       {
+               if(tl > 0)
+                       str = strcat(str, sprintf(_(" for up to ^1%1.0f minutes^7"), tl));
+               if(fl > 0)
+               {
+                       if(tl > 0)
+                               str = strcat(str, _(" or"));
+                       if(teamplay)
+                       {
+                               str = strcat(str, sprintf(_(" until ^3%s %s^7"), ScoreString(teamscores_flags(ts_primary), fl),
+                                       (teamscores_label(ts_primary) == "score")   ? CTX(_("SCO^points")) :
+                                       (teamscores_label(ts_primary) == "fastest") ? CTX(_("SCO^is beaten")) :
+                                       TranslateScoresLabel(teamscores_label(ts_primary))));
+                       }
+                       else
+                       {
+                               str = strcat(str, sprintf(_(" until ^3%s %s^7"), ScoreString(scores_flags(ps_primary), fl),
+                                       (scores_label(ps_primary) == "score")   ? CTX(_("SCO^points")) :
+                                       (scores_label(ps_primary) == "fastest") ? CTX(_("SCO^is beaten")) :
+                                       TranslateScoresLabel(scores_label(ps_primary))));
+                       }
+               }
+               if(ll > 0)
+               {
+                       if(tl > 0 || fl > 0)
+                               str = strcat(str, _(" or"));
+                       if(teamplay)
+                       {
+                               str = strcat(str, sprintf(_(" until a lead of ^3%s %s^7"), ScoreString(teamscores_flags(ts_primary), ll),
+                                       (teamscores_label(ts_primary) == "score")   ? CTX(_("SCO^points")) :
+                                       (teamscores_label(ts_primary) == "fastest") ? CTX(_("SCO^is beaten")) :
+                                       TranslateScoresLabel(teamscores_label(ts_primary))));
+                       }
+                       else
+                       {
+                               str = strcat(str, sprintf(_(" until a lead of ^3%s %s^7"), ScoreString(scores_flags(ps_primary), ll),
+                                       (scores_label(ps_primary) == "score")   ? CTX(_("SCO^points")) :
+                                       (scores_label(ps_primary) == "fastest") ? CTX(_("SCO^is beaten")) :
+                                       TranslateScoresLabel(scores_label(ps_primary))));
+                       }
+               }
+       }
+
+       pos.y += 1.2 * hud_fontsize.y;
+       drawcolorcodedstring(pos + '0.5 0 0' * (panel_size.x - stringwidth(str, true, hud_fontsize)), str, hud_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
+
+       // print information about respawn status
+       float respawn_time = STAT(RESPAWN_TIME);
+       if(!intermission)
+       if(respawn_time)
+       {
+               if(respawn_time < 0)
+               {
+                       // a negative number means we are awaiting respawn, time value is still the same
+                       respawn_time *= -1; // remove mark now that we checked it
+
+                       if(respawn_time < time) // it happens for a few frames when server is respawning the player
+                               str = ""; // draw an empty string to not change suddenly scoreboard_bottom
+                       else
+                               str = sprintf(_("^1Respawning in ^3%s^1..."),
+                                       (autocvar_hud_panel_scoreboard_respawntime_decimals ?
+                                               count_seconds_decs(respawn_time - time, autocvar_hud_panel_scoreboard_respawntime_decimals)
+                                               :
+                                               count_seconds(ceil(respawn_time - time))
+                                       )
+                               );
+               }
+               else if(time < respawn_time)
+               {
+                       str = sprintf(_("You are dead, wait ^3%s^7 before respawning"),
+                               (autocvar_hud_panel_scoreboard_respawntime_decimals ?
+                                       count_seconds_decs(respawn_time - time, autocvar_hud_panel_scoreboard_respawntime_decimals)
+                                       :
+                                       count_seconds(ceil(respawn_time - time))
+                               )
+                       );
+               }
+               else if(time >= respawn_time)
+                       str = sprintf(_("You are dead, press ^2%s^7 to respawn"), getcommandkey("jump", "+jump"));
+
+               pos.y += 1.2 * hud_fontsize.y;
+               drawcolorcodedstring(pos + '0.5 0 0' * (panel_size.x - stringwidth(str, true, hud_fontsize)), str, hud_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
+       }
+
+       scoreboard_bottom = pos.y + 2 * hud_fontsize.y;
+}
diff --git a/qcsrc/client/hud/panel/scoreboard.qh b/qcsrc/client/hud/panel/scoreboard.qh
new file mode 100644 (file)
index 0000000..2c8c77d
--- /dev/null
@@ -0,0 +1,12 @@
+#pragma once
+#include "../panel.qh"
+
+float scoreboard_active;
+float scoreboard_fade_alpha;
+
+void Cmd_Scoreboard_SetFields(float argc);
+void Scoreboard_Draw();
+void Scoreboard_InitScores();
+void Scoreboard_UpdatePlayerPos(entity pl);
+void Scoreboard_UpdateTeamPos(entity Team);
+float Scoreboard_WouldDraw();
index d7d4d252bec67441f178311e5f593bde24220536..a732b0c5ee7a2073c8a32e00ca054633fcb2c320 100644 (file)
@@ -72,7 +72,6 @@ void HUD_Vote()
                panel_size = eX * 0.4 * vid_conwidth + eY * 0.3 * vid_conheight;
        }
 
-    // these must be below above block
        vector pos, mySize;
        pos = panel_pos;
        mySize = panel_size;
@@ -119,10 +118,10 @@ void HUD_Vote()
        drawcolorcodedstring_aspect(pos + eY * (2/8) * mySize.y, s, eX * mySize.x + eY * (1.75/8) * mySize.y, a, DRAWFLAG_NORMAL);
 
        // print the yes/no counts
-    s = sprintf(_("Yes (%s): %d"), getcommandkey("vyes", "vyes"), vote_yescount);
-       drawstring_aspect(pos + eY * (4/8) * mySize.y, s, eX * 0.5 * mySize.x + eY * (1.5/8) * mySize.y, '0 1 0', a, DRAWFLAG_NORMAL);
-    s = sprintf(_("No (%s): %d"), getcommandkey("vno", "vno"), vote_nocount);
-       drawstring_aspect(pos + eX * 0.5 * mySize.x + eY * (4/8) * mySize.y, s, eX * 0.5 * mySize.x + eY * (1.5/8) * mySize.y, '1 0 0', a, DRAWFLAG_NORMAL);
+       s = sprintf("^2%s ^7(%d)", getcommandkey_forcename(_("Yes"), "vyes"), vote_yescount);
+       drawcolorcodedstring_aspect(pos + eY * (4/8) * mySize.y, s, eX * 0.5 * mySize.x + eY * (1.5/8) * mySize.y, a, DRAWFLAG_NORMAL);
+       s = sprintf("^1%s ^7(%d)", getcommandkey_forcename(_("No"), "vno"), vote_nocount);
+       drawcolorcodedstring_aspect(pos + eX * 0.5 * mySize.x + eY * (4/8) * mySize.y, s, eX * 0.5 * mySize.x + eY * (1.5/8) * mySize.y, a, DRAWFLAG_NORMAL);
 
        // draw the progress bar backgrounds
        drawpic_skin(pos + eY * (5/8) * mySize.y, "voteprogress_back", eX * mySize.x + eY * (3/8) * mySize.y, '1 1 1', a, DRAWFLAG_NORMAL);
index a30006c26377f7b93f3fdd9d37f35d934cd73221..fe2aefc60d1c3fe5f123c49386a235ccb3cc2b8b 100644 (file)
@@ -70,6 +70,8 @@ void HUD_Weapons()
        {
                if((!autocvar_hud_panel_weapons) || (spectatee_status == -1))
                        return;
+               if(STAT(HEALTH) <= 0 && autocvar_hud_panel_weapons_hide_ondeath)
+                       return;
                if(timeout && time >= weapontime + timeout + timeout_effect_length)
                if(autocvar_hud_panel_weapons_timeout_effect == 3 || (autocvar_hud_panel_weapons_timeout_effect == 1 && !(autocvar_hud_panel_weapons_timeout_fadebgmin + autocvar_hud_panel_weapons_timeout_fadefgmin)))
                {
@@ -149,7 +151,7 @@ void HUD_Weapons()
        {
                if(autocvar__hud_configure)
                {
-                       if(menu_enabled != 2)
+                       if(hud_configure_menu_open != 2)
                                HUD_Panel_DrawBg(1); // also draw the bg of the entire panel
                }
 
@@ -358,7 +360,6 @@ void HUD_Weapons()
        vector label_size = '1 1 0' * min(weapon_size.x, weapon_size.y) * bound(0, autocvar_hud_panel_weapons_label_scale, 1);
        vector noncurrent_size = weapon_size * bound(0.01, autocvar_hud_panel_weapons_noncurrent_scale, 1);
        float noncurrent_alpha = panel_fg_alpha * bound(0, autocvar_hud_panel_weapons_noncurrent_alpha, 1);
-       bool isCurrent;
        static vector weapon_pos_current = '-1 0 0';
        if(weapon_pos_current.x == -1)
                weapon_pos_current = panel_pos;
@@ -370,7 +371,9 @@ void HUD_Weapons()
                switch_speed = frametime * autocvar_hud_panel_weapons_selection_speed;
        vector radius_size = weapon_size * (autocvar_hud_panel_weapons_selection_radius + 1);
 
-       if(!panel_switchweapon)
+       if(switchweapon == WEP_Null)
+               panel_switchweapon = NULL;
+       else if(!panel_switchweapon)
                panel_switchweapon = switchweapon;
 
        // draw background behind currently selected weapon
@@ -403,8 +406,7 @@ void HUD_Weapons()
                weapon_pos = (panel_pos + eX * column * weapon_size.x + eY * row * weapon_size.y);
 
                // update position of the currently selected weapon
-               isCurrent = (it == panel_switchweapon);
-               if(isCurrent)
+               if(it == panel_switchweapon)
                {
                        if(weapon_pos_current.y > weapon_pos.y)
                                weapon_pos_current.y = max(weapon_pos.y, weapon_pos_current.y - switch_speed * (weapon_pos_current.y - weapon_pos.y));
index bd9e82ed21dac1c9af805b844ba63767bd2878cc..c5e47237b17b995a16d29cf06a5d5c9964c769df 100644 (file)
@@ -4,8 +4,8 @@
 #include "hud/all.qh"
 #include "mapvoting.qh"
 #include "mutators/events.qh"
+#include "hud/panel/scoreboard.qh"
 #include "hud/panel/quickmenu.qh"
-#include "scoreboard.qh"
 #include "shownames.qh"
 #include <common/t_items.qh>
 #include "wall.qh"
@@ -108,7 +108,6 @@ void CSQC_Init()
        binddb = db_create();
        tempdb = db_create();
        ClientProgsDB = db_load("client.db");
-       compressShortVector_init();
 
        draw_endBoldFont();
 
@@ -131,13 +130,13 @@ void CSQC_Init()
 
        registercvar("cl_spawn_near_teammate", "1");
 
-       gametype = 0;
+       gametype = NULL;
 
-       // hud_fields uses strunzone on the titles!
-       for(int i = 0; i < MAX_HUD_FIELDS; ++i)
-               hud_title[i] = strzone("(null)");
+       // sbt_fields uses strunzone on the titles!
+       for(int i = 0; i < MAX_SBT_FIELDS; ++i)
+               sbt_field_title[i] = strzone("(null)");
 
-       Cmd_HUD_SetFields(0);
+       Cmd_Scoreboard_SetFields(0);
 
        postinit = false;
 
@@ -185,8 +184,8 @@ void Shutdown()
 {
        WarpZone_Shutdown();
 
-       remove(teams);
-       remove(players);
+       delete(teams);
+       delete(players);
        db_close(binddb);
        db_close(tempdb);
        if(autocvar_cl_db_saveasdump)
@@ -235,7 +234,7 @@ float SetTeam(entity o, int Team)
                        default:
                                if(GetTeam(Team, false) == NULL)
                                {
-                                       LOG_TRACEF("trying to switch to unsupported team %d\n", Team);
+                                       LOG_TRACEF("trying to switch to unsupported team %d", Team);
                                        Team = NUM_SPECTATOR;
                                }
                                break;
@@ -251,7 +250,7 @@ float SetTeam(entity o, int Team)
                        default:
                                if(GetTeam(Team, false) == NULL)
                                {
-                                       LOG_TRACEF("trying to switch to unsupported team %d\n", Team);
+                                       LOG_TRACEF("trying to switch to unsupported team %d", Team);
                                        Team = NUM_SPECTATOR;
                                }
                                break;
@@ -323,9 +322,9 @@ void Playerchecker_Think(entity this)
                                e.ping_movementloss = 0;
                                //e.gotscores = 0; // we might already have the scores...
                                int t = entcs_GetScoreTeam(i);
-                               if (t) SetTeam(e, t); // will not hurt; later updates come with HUD_UpdatePlayerTeams
+                               if (t) SetTeam(e, t); // will not hurt; later updates come with Scoreboard_UpdatePlayerTeams
                                RegisterPlayer(e);
-                               HUD_UpdatePlayerPos(e);
+                               Scoreboard_UpdatePlayerPos(e);
                        }
                }
        }
@@ -385,23 +384,21 @@ void Ent_RemovePlayerScore(entity this)
        if(this.owner) {
                SetTeam(this.owner, -1);
                this.owner.gotscores = 0;
-               for(int i = 0; i < MAX_SCORE; ++i) {
-                       this.owner.(scores[i]) = 0; // clear all scores
-               }
+               FOREACH(Scores, true, {
+                       this.owner.(scores(it)) = 0; // clear all scores
+               });
        }
 }
 
 NET_HANDLE(ENT_CLIENT_SCORES, bool isnew)
 {
        make_pure(this);
-       int i, n;
-       bool isNew;
        entity o;
 
        // damnit -.- don't want to go change every single .sv_entnum in hud.qc AGAIN
        // (no I've never heard of M-x replace-string, sed, or anything like that)
-       isNew = !this.owner; // workaround for DP bug
-       n = ReadByte()-1;
+       bool isNew = !this.owner; // workaround for DP bug
+       int n = ReadByte()-1;
 
 #ifdef DP_CSQC_ENTITY_REMOVE_IS_B0RKED
        if(!isNew && n != this.sv_entnum)
@@ -429,27 +426,23 @@ NET_HANDLE(ENT_CLIENT_SCORES, bool isnew)
        //playerchecker will do this for us later, if it has not already done so
 
     int sf, lf;
-#if MAX_SCORE <= 8
-       sf = ReadByte();
-       lf = ReadByte();
-#else
        sf = ReadShort();
        lf = ReadShort();
-#endif
-    int p;
-       for(i = 0, p = 1; i < MAX_SCORE; ++i, p *= 2)
-               if(sf & p)
+       FOREACH(Scores, true, {
+        int p = 1 << (i % 16);
+               if (sf & p)
                {
-                       if(lf & p)
-                               o.(scores[i]) = ReadInt24_t();
+                       if (lf & p)
+                               o.(scores(it)) = ReadInt24_t();
                        else
-                               o.(scores[i]) = ReadChar();
+                               o.(scores(it)) = ReadChar();
                }
+    });
 
        return = true;
 
        if(o.sort_prev)
-               HUD_UpdatePlayerPos(o); // if not registered, we cannot do this yet!
+               Scoreboard_UpdatePlayerPos(o); // if not registered, we cannot do this yet!
 
        this.entremove = Ent_RemovePlayerScore;
 }
@@ -476,14 +469,14 @@ NET_HANDLE(ENT_CLIENT_TEAMSCORES, bool isnew)
                if(sf & p)
                {
                        if(lf & p)
-                               o.(teamscores[i]) = ReadInt24_t();
+                               o.(teamscores(i)) = ReadInt24_t();
                        else
-                               o.(teamscores[i]) = ReadChar();
+                               o.(teamscores(i)) = ReadChar();
                }
 
        return = true;
 
-       HUD_UpdateTeamPos(o);
+       Scoreboard_UpdateTeamPos(o);
 }
 
 NET_HANDLE(ENT_CLIENT_CLIENTDATA, bool isnew)
@@ -516,6 +509,22 @@ NET_HANDLE(ENT_CLIENT_CLIENTDATA, bool isnew)
        else
                angles_held_status = 0;
 
+       if(f & 16)
+       {
+               num_spectators = ReadByte();
+
+               float i, slot;
+
+               for(i = 0; i < MAX_SPECTATORS; ++i)
+                       spectatorlist[i] = 0; // reset list first
+
+               for(i = 0; i < num_spectators; ++i)
+               {
+                       slot = ReadByte();
+                       spectatorlist[i] = slot - 1;
+               }
+       }
+
        return = true;
 
        if(newspectatee_status != spectatee_status)
@@ -835,7 +844,7 @@ void CSQC_Ent_Update(entity this, bool isnew)
        time = savetime;
        if (!done)
        {
-               LOG_FATALF("CSQC_Ent_Update(%d) at %f with this=%i {.entnum=%d, .enttype=%d} t=%s (%d)\n", isnew, savetime, this, this.entnum, this.enttype, this.classname, t);
+               LOG_FATALF("CSQC_Ent_Update(%d) at %f with this=%i {.entnum=%d, .enttype=%d} t=%s (%d)", isnew, savetime, this, this.entnum, this.enttype, this.classname, t);
        }
 }
 
@@ -870,11 +879,11 @@ void CSQC_Ent_Remove(entity this)
        if (autocvar_developer_csqcentities) LOG_INFOF("CSQC_Ent_Remove() with this=%i {.entnum=%d, .enttype=%d}\n", this, this.entnum, this.enttype);
        if (wasfreed(this))
        {
-               LOG_WARNING("CSQC_Ent_Remove called for already removed entity. Packet loss?\n");
+               LOG_WARN("CSQC_Ent_Remove called for already removed entity. Packet loss?");
                return;
        }
        if (this.enttype) Ent_Remove(this);
-       remove(this);
+       delete(this);
 }
 
 void Gamemode_Init()
@@ -940,22 +949,21 @@ void Gamemode_Init();
 NET_HANDLE(ENT_CLIENT_SCORES_INFO, bool isnew)
 {
        make_pure(this);
-       gametype = ReadInt24_t();
+       gametype = ReadRegistered(Gametypes);
        HUD_ModIcons_SetFunc();
-       for (int i = 0; i < MAX_SCORE; ++i)
-       {
-               if (scores_label[i]) strunzone(scores_label[i]);
-               scores_label[i] = strzone(ReadString());
-               scores_flags[i] = ReadByte();
-       }
+       FOREACH(Scores, true, {
+               if (scores_label(it)) strunzone(scores_label(it));
+               scores_label(it) = strzone(ReadString());
+               scores_flags(it) = ReadByte();
+       });
        for (int i = 0; i < MAX_TEAMSCORE; ++i)
        {
-               if (teamscores_label[i]) strunzone(teamscores_label[i]);
-               teamscores_label[i] = strzone(ReadString());
-               teamscores_flags[i] = ReadByte();
+               if (teamscores_label(i)) strunzone(teamscores_label(i));
+               teamscores_label(i) = strzone(ReadString());
+               teamscores_flags(i) = ReadByte();
        }
        return = true;
-       HUD_InitScores();
+       Scoreboard_InitScores();
        Gamemode_Init();
 }
 
@@ -1222,13 +1230,13 @@ NET_HANDLE(TE_CSQC_WEAPONCOMPLAIN, bool isNew)
        }
 }
 
-string getcommandkey(string text, string command)
+string _getcommandkey(string cmd_name, string command, bool forcename)
 {
        string keys;
        float n, j, k, l = 0;
 
        if (!autocvar_hud_showbinds)
-               return text;
+               return cmd_name;
 
        keys = db_get(binddb, command);
        if (keys == "")
@@ -1262,12 +1270,12 @@ string getcommandkey(string text, string command)
 
        if (keys == "NO_KEY") {
                if (autocvar_hud_showbinds > 1)
-                       return sprintf(_("%s (not bound)"), text);
+                       return sprintf(_("%s (not bound)"), cmd_name);
                else
-                       return text;
+                       return cmd_name;
        }
-       else if (autocvar_hud_showbinds > 1)
-               return sprintf("%s (%s)", text, keys);
+       else if (autocvar_hud_showbinds > 1 || forcename)
+               return sprintf("%s (%s)", cmd_name, keys);
        else
                return keys;
 }
index e1cbbe79c39673d2fd36c8d65019f4ec8fe9a7e2..afd0b5e38c96be69d22b400022a0be49429a786a 100644 (file)
@@ -19,7 +19,7 @@ string minimapname;
 // General stuff
 
 float postinit;
-float gametype;
+entity gametype;
 
 //float sorted_players;
 //float sorted_teams;
@@ -40,35 +40,12 @@ void LoadMenuSkinValues();
 // --------------------------------------------------------------------------
 // Scoreboard stuff
 
-const int MAX_HUD_FIELDS = 16;
-
-const int SP_END = -1;
-
-const int SP_PING = -2;
-const int SP_NAME = -3;
-const int SP_KDRATIO = -4;
-const int SP_CLRATIO = -5;
-const int SP_PL = -6;
-const int SP_FRAGS = -7;
-const int SP_SUM = -8;
-
-const int SP_SEPARATOR = -100;
-
-float hud_field[MAX_HUD_FIELDS + 1];
-float hud_size[MAX_HUD_FIELDS + 1];
-string hud_title[MAX_HUD_FIELDS + 1];
-int hud_num_fields;
-
-string scores_label[MAX_SCORE];
-int scores_flags[MAX_SCORE];
-string teamscores_label[MAX_SCORE];
-int teamscores_flags[MAX_SCORE];
-.int scores[MAX_SCORE];
-.float teamscores[MAX_TEAMSCORE];
-
-#define IS_INCREASING(x) ( (x)&SFL_LOWER_IS_BETTER )
-#define IS_DECREASING(x) ( !((x)&SFL_LOWER_IS_BETTER) )
+const int MAX_SBT_FIELDS = MAX_SCORE;
 
+PlayerScoreField sbt_field[MAX_SBT_FIELDS + 1];
+float sbt_field_size[MAX_SBT_FIELDS + 1];
+string sbt_field_title[MAX_SBT_FIELDS + 1];
+int sbt_num_fields;
 
 vector hud_fontsize;
 
@@ -112,7 +89,9 @@ float warmup_stage;
 
 void Fog_Force();
 
-string getcommandkey(string text, string command);
+string _getcommandkey(string text, string command, bool forcename);
+#define getcommandkey(cmd_name, command) _getcommandkey(cmd_name, command, false)
+#define getcommandkey_forcename(cmd_name, command) _getcommandkey(cmd_name, command, true)
 
 string vote_called_vote;
 float ready_waiting;
@@ -149,6 +128,11 @@ float g_trueaim_minrange;
 
 float hud;
 float view_quality;
+
+int num_spectators;
+const int MAX_SPECTATORS = 7;
+int spectatorlist[MAX_SPECTATORS];
+
 int framecount;
 .float health;
 
index bfc25e99c134116524b39fe0934773484e1627f7..19c128a7da6db459c14e59c4b3737dd6cb965a36 100644 (file)
@@ -1,7 +1,7 @@
 #include "mapvoting.qh"
 
 #include "hud/all.qh"
-#include "scoreboard.qh"
+#include "hud/panel/scoreboard.qh"
 
 #include <common/mapinfo.qh>
 
@@ -88,10 +88,10 @@ void GameTypeVote_DrawGameTypeItem(vector pos, float maxh, float tsize, string g
        // Bounding box details
        float rect_margin = hud_fontsize.y / 2;
 
-       pos.x += rect_margin + autocvar_scoreboard_border_thickness;
-       pos.y += rect_margin + autocvar_scoreboard_border_thickness;
-       maxh -= 2 * (rect_margin + autocvar_scoreboard_border_thickness);
-       tsize -= 2 * (rect_margin + autocvar_scoreboard_border_thickness);
+       pos.x += rect_margin + autocvar_hud_panel_mapvote_highlight_border;
+       pos.y += rect_margin + autocvar_hud_panel_mapvote_highlight_border;
+       maxh -= 2 * (rect_margin + autocvar_hud_panel_mapvote_highlight_border);
+       tsize -= 2 * (rect_margin + autocvar_hud_panel_mapvote_highlight_border);
 
        vector rect_pos = pos - '0.5 0.5 0' * rect_margin;
        vector rect_size = '1 1 0';
@@ -109,7 +109,7 @@ void GameTypeVote_DrawGameTypeItem(vector pos, float maxh, float tsize, string g
        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);
+               drawborderlines(autocvar_hud_panel_mapvote_highlight_border, rect_pos, rect_size, rgb, alpha, DRAWFLAG_NORMAL);
        }
 
        vector offset = pos;
@@ -177,11 +177,11 @@ void GameTypeVote_DrawGameTypeItem(vector pos, float maxh, float tsize, string g
                drawstring(last.origin+offset, last.message, gtv_text_size_small, '1 1 1', alpha, DRAWFLAG_NORMAL);
                next = last;
                last = last.chain;
-               remove(next);
+               delete(next);
        }
 
        // Cleanup
-       remove(title);
+       delete(title);
 }
 
 void MapVote_DrawMapItem(vector pos, float isize, float tsize, string map, string pic, float _count, int id)
@@ -193,10 +193,10 @@ void MapVote_DrawMapItem(vector pos, float isize, float tsize, string map, strin
 
        float rect_margin = hud_fontsize.y / 2;
 
-       pos.x += rect_margin + autocvar_scoreboard_border_thickness;
-       pos.y += rect_margin + autocvar_scoreboard_border_thickness;
-       isize -= 2 * (rect_margin + autocvar_scoreboard_border_thickness);
-       tsize -= 2 * (rect_margin + autocvar_scoreboard_border_thickness);
+       pos.x += rect_margin + autocvar_hud_panel_mapvote_highlight_border;
+       pos.y += rect_margin + autocvar_hud_panel_mapvote_highlight_border;
+       isize -= 2 * (rect_margin + autocvar_hud_panel_mapvote_highlight_border);
+       tsize -= 2 * (rect_margin + autocvar_hud_panel_mapvote_highlight_border);
 
        vector rect_pos = pos - '0.5 0.5 0' * rect_margin;
        vector rect_size = '1 1 0';
@@ -240,7 +240,7 @@ void MapVote_DrawMapItem(vector pos, float isize, float tsize, string map, strin
        if(id == mv_ownvote)
        {
                drawfill(rect_pos, rect_size, rgb, 0.1*theAlpha, DRAWFLAG_NORMAL);
-               drawborderlines(autocvar_scoreboard_border_thickness, rect_pos, rect_size, rgb, theAlpha, DRAWFLAG_NORMAL);
+               drawborderlines(autocvar_hud_panel_mapvote_highlight_border, rect_pos, rect_size, rgb, theAlpha, DRAWFLAG_NORMAL);
        }
 
        drawstring(text_pos, label, hud_fontsize, rgb, theAlpha, DRAWFLAG_NORMAL);
@@ -627,7 +627,7 @@ void GameTypeVote_ReadOption(int i)
        }
        else
        {
-               int type = MapInfo_Type_FromString(gt);
+               Gametype type = MapInfo_Type_FromString(gt);
                mv_pk3[i] = strzone(MapInfo_Type_ToText(type));
                mv_desc[i] = MapInfo_Type_Description(type);
        }
index ebc107a0b2584196023b052fdb82c02470ed16f5..2f95102a990bf84571b8010cff9b55c674991dca 100644 (file)
@@ -10,3 +10,4 @@ float MapVote_InputEvent(float bInputType, float nPrimary, float nSecondary);
 void Net_MapVote_Picture();
 
 float mv_active;
+float xmin, xmax, ymin, ymax;
index 85a798f3f427f39e122f7f6187161d4e00d859ec..146e306a08fd091a852d3b8097a84a23e56626c3 100644 (file)
@@ -50,7 +50,7 @@ void skeleton_loadinfo(entity e)
                }
        }
        else
-               LOG_TRACE("No model parameters for ", e.model, "\n");
+               LOG_TRACE("No model parameters for ", e.model);
        //dprint(e.model, " uses ", ftos(e.bone_upperbody), " ", ftos(e.fixbone), "\n");
        get_model_parameters(string_null, 0);
        e.skeleton_info_modelindex = e.modelindex;
diff --git a/qcsrc/client/scoreboard.qc b/qcsrc/client/scoreboard.qc
deleted file mode 100644 (file)
index b86e0d8..0000000
+++ /dev/null
@@ -1,1517 +0,0 @@
-#include "scoreboard.qh"
-
-#include "hud/panel/quickmenu.qh"
-#include "hud/all.qh"
-
-#include <common/ent_cs.qh>
-#include <common/constants.qh>
-#include <common/mapinfo.qh>
-#include <common/minigames/cl_minigames.qh>
-#include <common/stats.qh>
-#include <common/teams.qh>
-
-float scoreboard_alpha_bg;
-float scoreboard_alpha_fg;
-float scoreboard_highlight;
-float scoreboard_highlight_alpha;
-float scoreboard_highlight_alpha_self;
-float scoreboard_alpha_name;
-float scoreboard_alpha_name_self;
-
-void drawstringright(vector, string, vector, vector, float, float);
-void drawstringcenter(vector, string, vector, vector, float, float);
-
-const float SCOREBOARD_OFFSET = 50;
-
-// wrapper to put all possible scores titles through gettext
-string TranslateScoresLabel(string l)
-{
-       switch(l)
-       {
-               case "bckills": return CTX(_("SCO^bckills"));
-               case "bctime": return CTX(_("SCO^bctime"));
-               case "caps": return CTX(_("SCO^caps"));
-               case "captime": return CTX(_("SCO^captime"));
-               case "deaths": return CTX(_("SCO^deaths"));
-               case "destroyed": return CTX(_("SCO^destroyed"));
-               case "dmg": return CTX(_("SCO^dmg"));
-               case "dmgtaken": return CTX(_("SCO^dmgtaken"));
-               case "drops": return CTX(_("SCO^drops"));
-               case "faults": return CTX(_("SCO^faults"));
-               case "fckills": return CTX(_("SCO^fckills"));
-               case "goals": return CTX(_("SCO^goals"));
-               case "kckills": return CTX(_("SCO^kckills"));
-               case "kdratio": return CTX(_("SCO^kdratio"));
-               case "k/d": return CTX(_("SCO^k/d"));
-               case "kd": return CTX(_("SCO^kd"));
-               case "kdr": return CTX(_("SCO^kdr"));
-               case "kills": return CTX(_("SCO^kills"));
-               case "laps": return CTX(_("SCO^laps"));
-               case "lives": return CTX(_("SCO^lives"));
-               case "losses": return CTX(_("SCO^losses"));
-               case "name": return CTX(_("SCO^name"));
-               case "sum": return CTX(_("SCO^sum"));
-               case "nick": return CTX(_("SCO^nick"));
-               case "objectives": return CTX(_("SCO^objectives"));
-               case "pickups": return CTX(_("SCO^pickups"));
-               case "ping": return CTX(_("SCO^ping"));
-               case "pl": return CTX(_("SCO^pl"));
-               case "pushes": return CTX(_("SCO^pushes"));
-               case "rank": return CTX(_("SCO^rank"));
-               case "returns": return CTX(_("SCO^returns"));
-               case "revivals": return CTX(_("SCO^revivals"));
-               case "score": return CTX(_("SCO^score"));
-               case "suicides": return CTX(_("SCO^suicides"));
-               case "takes": return CTX(_("SCO^takes"));
-               case "ticks": return CTX(_("SCO^ticks"));
-               default: return l;
-       }
-}
-
-void HUD_InitScores()
-{
-       int i, f;
-
-       ps_primary = ps_secondary = ts_primary = ts_secondary = -1;
-       for(i = 0; i < MAX_SCORE; ++i)
-       {
-               f = (scores_flags[i] & SFL_SORT_PRIO_MASK);
-               if(f == SFL_SORT_PRIO_PRIMARY)
-                       ps_primary = i;
-               if(f == SFL_SORT_PRIO_SECONDARY)
-                       ps_secondary = i;
-       }
-       if(ps_secondary == -1)
-               ps_secondary = ps_primary;
-
-       for(i = 0; i < MAX_TEAMSCORE; ++i)
-       {
-               f = (teamscores_flags[i] & SFL_SORT_PRIO_MASK);
-               if(f == SFL_SORT_PRIO_PRIMARY)
-                       ts_primary = i;
-               if(f == SFL_SORT_PRIO_SECONDARY)
-                       ts_secondary = i;
-       }
-       if(ts_secondary == -1)
-               ts_secondary = ts_primary;
-
-       Cmd_HUD_SetFields(0);
-}
-
-float SetTeam(entity pl, float Team);
-//float lastpnum;
-void HUD_UpdatePlayerTeams()
-{
-       float Team;
-       entity pl, tmp;
-       float num;
-
-       num = 0;
-       for(pl = players.sort_next; pl; pl = pl.sort_next)
-       {
-               num += 1;
-               Team = entcs_GetScoreTeam(pl.sv_entnum);
-               if(SetTeam(pl, Team))
-               {
-                       tmp = pl.sort_prev;
-                       HUD_UpdatePlayerPos(pl);
-                       if(tmp)
-                               pl = tmp;
-                       else
-                               pl = players.sort_next;
-               }
-       }
-       /*
-       if(num != lastpnum)
-               print(strcat("PNUM: ", ftos(num), "\n"));
-       lastpnum = num;
-       */
-}
-
-int HUD_CompareScore(int vl, int vr, int f)
-{
-    TC(int, vl); TC(int, vr); TC(int, f);
-       if(f & SFL_ZERO_IS_WORST)
-       {
-               if(vl == 0 && vr != 0)
-                       return 1;
-               if(vl != 0 && vr == 0)
-                       return 0;
-       }
-       if(vl > vr)
-               return IS_INCREASING(f);
-       if(vl < vr)
-               return IS_DECREASING(f);
-       return -1;
-}
-
-float HUD_ComparePlayerScores(entity left, entity right)
-{
-       float vl, vr, r;
-       vl = entcs_GetTeam(left.sv_entnum);
-       vr = entcs_GetTeam(right.sv_entnum);
-
-       if(!left.gotscores)
-               vl = NUM_SPECTATOR;
-       if(!right.gotscores)
-               vr = NUM_SPECTATOR;
-
-       if(vl > vr)
-               return true;
-       if(vl < vr)
-               return false;
-
-       if(vl == NUM_SPECTATOR)
-       {
-               // FIRST the one with scores (spectators), THEN the ones without (downloaders)
-               // no other sorting
-               if(!left.gotscores && right.gotscores)
-                       return true;
-               return false;
-       }
-
-       r = HUD_CompareScore(left.scores[ps_primary], right.scores[ps_primary], scores_flags[ps_primary]);
-       if (r >= 0)
-               return r;
-
-       r = HUD_CompareScore(left.scores[ps_secondary], right.scores[ps_secondary], scores_flags[ps_secondary]);
-       if (r >= 0)
-               return r;
-
-       int i;
-       for(i = 0; i < MAX_SCORE; ++i)
-       {
-               r = HUD_CompareScore(left.scores[i], right.scores[i], scores_flags[i]);
-               if (r >= 0)
-                       return r;
-       }
-
-       if (left.sv_entnum < right.sv_entnum)
-               return true;
-
-       return false;
-}
-
-void HUD_UpdatePlayerPos(entity player)
-{
-       entity ent;
-       for(ent = player.sort_next; ent && HUD_ComparePlayerScores(player, ent); ent = player.sort_next)
-       {
-               SORT_SWAP(player, ent);
-       }
-       for(ent = player.sort_prev; ent != players && HUD_ComparePlayerScores(ent, player); ent = player.sort_prev)
-       {
-               SORT_SWAP(ent, player);
-       }
-}
-
-float HUD_CompareTeamScores(entity left, entity right)
-{
-       int i, r;
-
-       if(left.team == NUM_SPECTATOR)
-               return 1;
-       if(right.team == NUM_SPECTATOR)
-               return 0;
-
-       r = HUD_CompareScore(left.teamscores[ts_primary], right.teamscores[ts_primary], teamscores_flags[ts_primary]);
-       if (r >= 0)
-               return r;
-
-       r = HUD_CompareScore(left.teamscores[ts_secondary], right.teamscores[ts_secondary], teamscores_flags[ts_secondary]);
-       if (r >= 0)
-               return r;
-
-       for(i = 0; i < MAX_SCORE; ++i)
-       {
-               r = HUD_CompareScore(left.teamscores[i], right.teamscores[i], teamscores_flags[i]);
-               if (r >= 0)
-                       return r;
-       }
-
-       if (left.team < right.team)
-               return true;
-
-       return false;
-}
-
-void HUD_UpdateTeamPos(entity Team)
-{
-       entity ent;
-       for(ent = Team.sort_next; ent && HUD_CompareTeamScores(Team, ent); ent = Team.sort_next)
-       {
-               SORT_SWAP(Team, ent);
-       }
-       for(ent = Team.sort_prev; ent != teams && HUD_CompareTeamScores(ent, Team); ent = Team.sort_prev)
-       {
-               SORT_SWAP(ent, Team);
-       }
-}
-
-void Cmd_HUD_Help()
-{
-       LOG_INFO(_("You can modify the scoreboard using the ^2scoreboard_columns_set command.\n"));
-       LOG_INFO(_("^3|---------------------------------------------------------------|\n"));
-       LOG_INFO(_("Usage:\n"));
-       LOG_INFO(_("^2scoreboard_columns_set default\n"));
-       LOG_INFO(_("^2scoreboard_columns_set ^7field1 field2 ...\n"));
-       LOG_INFO(_("The following field names are recognized (case insensitive):\n"));
-       LOG_INFO(_("You can use a ^3|^7 to start the right-aligned fields.\n\n"));
-
-       LOG_INFO(_("^3name^7 or ^3nick^7             Name of a player\n"));
-       LOG_INFO(_("^3ping^7                     Ping time\n"));
-       LOG_INFO(_("^3pl^7                       Packet loss\n"));
-       LOG_INFO(_("^3kills^7                    Number of kills\n"));
-       LOG_INFO(_("^3deaths^7                   Number of deaths\n"));
-       LOG_INFO(_("^3suicides^7                 Number of suicides\n"));
-       LOG_INFO(_("^3frags^7                    kills - suicides\n"));
-       LOG_INFO(_("^3kd^7                       The kill-death ratio\n"));
-       LOG_INFO(_("^3dmg^7                      The total damage done\n"));
-       LOG_INFO(_("^3dmgtaken^7                 The total damage taken\n"));
-       LOG_INFO(_("^3sum^7                      frags - deaths\n"));
-       LOG_INFO(_("^3caps^7                     How often a flag (CTF) or a key (KeyHunt) was captured\n"));
-       LOG_INFO(_("^3pickups^7                  How often a flag (CTF) or a key (KeyHunt) or a ball (Keepaway) was picked up\n"));
-       LOG_INFO(_("^3captime^7                  Time of fastest cap (CTF)\n"));
-       LOG_INFO(_("^3fckills^7                  Number of flag carrier kills\n"));
-       LOG_INFO(_("^3returns^7                  Number of flag returns\n"));
-       LOG_INFO(_("^3drops^7                    Number of flag drops\n"));
-       LOG_INFO(_("^3lives^7                    Number of lives (LMS)\n"));
-       LOG_INFO(_("^3rank^7                     Player rank\n"));
-       LOG_INFO(_("^3pushes^7                   Number of players pushed into void\n"));
-       LOG_INFO(_("^3destroyed^7                Number of keys destroyed by pushing them into void\n"));
-       LOG_INFO(_("^3kckills^7                  Number of keys carrier kills\n"));
-       LOG_INFO(_("^3losses^7                   Number of times a key was lost\n"));
-       LOG_INFO(_("^3laps^7                     Number of laps finished (race/cts)\n"));
-       LOG_INFO(_("^3time^7                     Total time raced (race/cts)\n"));
-       LOG_INFO(_("^3fastest^7                  Time of fastest lap (race/cts)\n"));
-       LOG_INFO(_("^3ticks^7                    Number of ticks (DOM)\n"));
-       LOG_INFO(_("^3takes^7                    Number of domination points taken (DOM)\n"));
-       LOG_INFO(_("^3bckills^7                  Number of ball carrier kills\n"));
-       LOG_INFO(_("^3bctime^7                   Total amount of time holding the ball in Keepaway\n"));
-       LOG_INFO(_("^3score^7                    Total score\n\n"));
-
-       LOG_INFO(_("Before a field you can put a + or - sign, then a comma separated list\n"
-               "of game types, then a slash, to make the field show up only in these\n"
-               "or in all but these game types. You can also specify 'all' as a\n"
-               "field to show all fields available for the current game mode.\n\n"));
-
-       LOG_INFO(_("The special game type names 'teams' and 'noteams' can be used to\n"
-               "include/exclude ALL teams/noteams game modes.\n\n"));
-
-       LOG_INFO(_("Example: scoreboard_columns_set name ping pl | +ctf/field3 -dm/field4\n"));
-       LOG_INFO(_("will display name, ping and pl aligned to the left, and the fields\n"
-               "right of the vertical bar aligned to the right.\n"));
-       LOG_INFO(_("'field3' will only be shown in CTF, and 'field4' will be shown in all\n"
-               "other gamemodes except DM.\n"));
-}
-
-// NOTE: adding a gametype with ? to not warn for an optional field
-// make sure it's excluded in a previous exclusive rule, if any
-// otherwise the previous exclusive rule warns anyway
-// e.g. -teams,rc,cts,lms/kills ?+rc/kills
-#define SCOREBOARD_DEFAULT_COLUMNS \
-"ping pl name |" \
-" -teams,rc,cts,inv,lms/kills +ft,tdm/kills ?+rc,inv/kills" \
-" -teams,lms/deaths +ft,tdm/deaths" \
-" -teams,lms,rc,cts,inv,ka/suicides +ft,tdm/suicides ?+rc,inv/suicides" \
-" -cts,dm,tdm,ka,ft/frags" /* tdm already has this in "score" */ \
-" -rc,cts,nb/dmg -rc,cts,nb/dmgtaken" \
-" +ctf/caps +ctf/pickups +ctf/fckills +ctf/returns +ons/caps +ons/takes" \
-" +lms/lives +lms/rank" \
-" +kh/caps +kh/pushes +kh/destroyed" \
-" ?+rc/laps ?+rc/time +rc,cts/fastest" \
-" +as/objectives +nb/faults +nb/goals" \
-" +ka/pickups +ka/bckills +ka/bctime +ft/revivals" \
-" -lms,rc,cts,inv,nb/score"
-
-void Cmd_HUD_SetFields(int argc)
-{
-    TC(int, argc);
-       int i, j, slash;
-       string str, pattern;
-       float have_name = 0, have_primary = 0, have_secondary = 0, have_separator = 0;
-       float missing;
-
-       if(!gametype)
-       {
-               // set up a temporary scoreboard layout
-               // no layout can be properly set up until score_info data haven't been received
-               argc = tokenizebyseparator("0 1 ping pl name | score", " ");
-               ps_primary = 0;
-               scores_label[ps_primary] = strzone("score");
-               scores_flags[ps_primary] = SFL_ALLOW_HIDE;
-       }
-
-       // TODO: re enable with gametype dependant cvars?
-       if(argc < 3) // no arguments provided
-               argc = tokenizebyseparator(strcat("0 1 ", autocvar_scoreboard_columns), " ");
-
-       if(argc < 3)
-               argc = tokenizebyseparator(strcat("0 1 ", SCOREBOARD_DEFAULT_COLUMNS), " ");
-
-       if(argc == 3)
-       {
-               if(argv(2) == "default")
-                       argc = tokenizebyseparator(strcat("0 1 ", SCOREBOARD_DEFAULT_COLUMNS), " ");
-               else if(argv(2) == "all")
-               {
-                       string s;
-                       s = "ping pl name |";
-                       for(i = 0; i < MAX_SCORE; ++i)
-                       {
-                               if(i != ps_primary)
-                               if(i != ps_secondary)
-                               if(scores_label[i] != "")
-                                       s = strcat(s, " ", scores_label[i]);
-                       }
-                       if(ps_secondary != ps_primary)
-                               s = strcat(s, " ", scores_label[ps_secondary]);
-                       s = strcat(s, " ", scores_label[ps_primary]);
-                       argc = tokenizebyseparator(strcat("0 1 ", s), " ");
-               }
-       }
-
-
-       hud_num_fields = 0;
-
-       hud_fontsize = HUD_GetFontsize("hud_fontsize");
-
-       for(i = 1; i < argc - 1; ++i)
-       {
-               float nocomplain;
-               str = argv(i+1);
-
-               nocomplain = false;
-               if(substring(str, 0, 1) == "?")
-               {
-                       nocomplain = true;
-                       str = substring(str, 1, strlen(str) - 1);
-               }
-
-               slash = strstrofs(str, "/", 0);
-               if(slash >= 0)
-               {
-                       pattern = substring(str, 0, slash);
-                       str = substring(str, slash + 1, strlen(str) - (slash + 1));
-
-                       if (!isGametypeInFilter(gametype, teamplay, false, pattern))
-                               continue;
-               }
-
-               strunzone(hud_title[hud_num_fields]);
-               hud_title[hud_num_fields] = strzone(TranslateScoresLabel(str));
-               hud_size[hud_num_fields] = stringwidth(hud_title[hud_num_fields], false, hud_fontsize);
-               str = strtolower(str);
-
-               switch(str)
-               {
-                       case "ping": hud_field[hud_num_fields] = SP_PING; break;
-                       case "pl": hud_field[hud_num_fields] = SP_PL; break;
-                       case "kd": case "kdr": case "kdratio": case "k/d": hud_field[hud_num_fields] = SP_KDRATIO; break;
-                       case "sum": case "diff": case "k-d": hud_field[hud_num_fields] = SP_SUM; break;
-                       case "name": case "nick": hud_field[hud_num_fields] = SP_NAME; have_name = true; break;
-                       case "|": hud_field[hud_num_fields] = SP_SEPARATOR; have_separator = true; break;
-                       case "dmg": hud_field[hud_num_fields] = SP_DMG; break;
-                       case "dmgtaken": hud_field[hud_num_fields] = SP_DMGTAKEN; break;
-                       default:
-                       {
-                               for(j = 0; j < MAX_SCORE; ++j)
-                                       if(str == strtolower(scores_label[j]))
-                                               goto found; // sorry, but otherwise fteqcc -O3 miscompiles this and warns about "unreachable code"
-
-LABEL(notfound)
-                               if(str == "frags")
-                                       j = SP_FRAGS;
-                               else
-                               {
-                                       if(!nocomplain)
-                                               LOG_INFOF("^1Error:^7 Unknown score field: '%s'\n", str);
-                                       continue;
-                               }
-LABEL(found)
-                               hud_field[hud_num_fields] = j;
-                               if(j == ps_primary)
-                                       have_primary = 1;
-                               if(j == ps_secondary)
-                                       have_secondary = 1;
-
-                       }
-               }
-               ++hud_num_fields;
-               if(hud_num_fields >= MAX_HUD_FIELDS)
-                       break;
-       }
-
-       if(scores_flags[ps_primary] & SFL_ALLOW_HIDE)
-               have_primary = 1;
-       if(scores_flags[ps_secondary] & SFL_ALLOW_HIDE)
-               have_secondary = 1;
-       if(ps_primary == ps_secondary)
-               have_secondary = 1;
-       missing = (!have_primary) + (!have_secondary) + (!have_separator) + (!have_name);
-
-       if(hud_num_fields+missing < MAX_HUD_FIELDS)
-       {
-               if(!have_name)
-               {
-                       strunzone(hud_title[hud_num_fields]);
-                       for(i = hud_num_fields; i > 0; --i)
-                       {
-                               hud_title[i] = hud_title[i-1];
-                               hud_size[i] = hud_size[i-1];
-                               hud_field[i] = hud_field[i-1];
-                       }
-                       hud_title[0] = strzone(TranslateScoresLabel("name"));
-                       hud_field[0] = SP_NAME;
-                       ++hud_num_fields;
-                       LOG_INFO("fixed missing field 'name'\n");
-
-                       if(!have_separator)
-                       {
-                               strunzone(hud_title[hud_num_fields]);
-                               for(i = hud_num_fields; i > 1; --i)
-                               {
-                                       hud_title[i] = hud_title[i-1];
-                                       hud_size[i] = hud_size[i-1];
-                                       hud_field[i] = hud_field[i-1];
-                               }
-                               hud_title[1] = strzone("|");
-                               hud_field[1] = SP_SEPARATOR;
-                               hud_size[1] = stringwidth("|", false, hud_fontsize);
-                               ++hud_num_fields;
-                               LOG_INFO("fixed missing field '|'\n");
-                       }
-               }
-               else if(!have_separator)
-               {
-                       strunzone(hud_title[hud_num_fields]);
-                       hud_title[hud_num_fields] = strzone("|");
-                       hud_size[hud_num_fields] = stringwidth("|", false, hud_fontsize);
-                       hud_field[hud_num_fields] = SP_SEPARATOR;
-                       ++hud_num_fields;
-                       LOG_INFO("fixed missing field '|'\n");
-               }
-               if(!have_secondary)
-               {
-                       strunzone(hud_title[hud_num_fields]);
-                       hud_title[hud_num_fields] = strzone(TranslateScoresLabel(scores_label[ps_secondary]));
-                       hud_size[hud_num_fields] = stringwidth(hud_title[hud_num_fields], false, hud_fontsize);
-                       hud_field[hud_num_fields] = ps_secondary;
-                       ++hud_num_fields;
-                       LOG_INFOF("fixed missing field '%s'\n", scores_label[ps_secondary]);
-               }
-               if(!have_primary)
-               {
-                       strunzone(hud_title[hud_num_fields]);
-                       hud_title[hud_num_fields] = strzone(TranslateScoresLabel(scores_label[ps_primary]));
-                       hud_size[hud_num_fields] = stringwidth(hud_title[hud_num_fields], false, hud_fontsize);
-                       hud_field[hud_num_fields] = ps_primary;
-                       ++hud_num_fields;
-                       LOG_INFOF("fixed missing field '%s'\n", scores_label[ps_primary]);
-               }
-       }
-
-       hud_field[hud_num_fields] = SP_END;
-}
-
-// MOVEUP::
-vector hud_field_rgb;
-string hud_field_icon0;
-string hud_field_icon1;
-string hud_field_icon2;
-vector hud_field_icon0_rgb;
-vector hud_field_icon1_rgb;
-vector hud_field_icon2_rgb;
-float hud_field_icon0_alpha;
-float hud_field_icon1_alpha;
-float hud_field_icon2_alpha;
-string HUD_GetField(entity pl, int field)
-{
-    TC(int, field);
-       float tmp, num, denom;
-       int f;
-       string str;
-       hud_field_rgb = '1 1 1';
-       hud_field_icon0 = "";
-       hud_field_icon1 = "";
-       hud_field_icon2 = "";
-       hud_field_icon0_rgb = '1 1 1';
-       hud_field_icon1_rgb = '1 1 1';
-       hud_field_icon2_rgb = '1 1 1';
-       hud_field_icon0_alpha = 1;
-       hud_field_icon1_alpha = 1;
-       hud_field_icon2_alpha = 1;
-       switch(field)
-       {
-               case SP_PING:
-                       if (!pl.gotscores)
-                               return "\xE2\x96\xB6\xE2\x96\xB6\xE2\x96\xB6"; // >>> sign using U+25B6
-                       //str = getplayerkeyvalue(pl.sv_entnum, "ping");
-                       f = pl.ping;
-                       if(f == 0)
-                               return _("N/A");
-                       tmp = max(0, min(220, f-80)) / 220;
-                       hud_field_rgb = '1 1 1' - '0 1 1'*tmp;
-                       return ftos(f);
-
-               case SP_PL:
-                       if (!pl.gotscores)
-                               return _("N/A");
-                       f = pl.ping_packetloss;
-                       tmp = pl.ping_movementloss;
-                       if(f == 0 && tmp == 0)
-                               return "";
-                       str = ftos(ceil(f * 100));
-                       if(tmp != 0)
-                               str = strcat(str, "~", ftos(ceil(tmp * 100)));
-                       tmp = bound(0, f / 0.2 + tmp / 0.04, 1); // 20% is REALLY BAD pl
-                       hud_field_rgb = '1 0.5 0.5' - '0 0.5 0.5'*tmp;
-                       return str;
-
-               case SP_NAME:
-                       if(ready_waiting && pl.ready)
-                       {
-                               hud_field_icon0 = "gfx/scoreboard/player_ready";
-                       }
-                       else if(!teamplay)
-                       {
-                               f = stof(getplayerkeyvalue(pl.sv_entnum, "colors"));
-                               {
-                                       hud_field_icon0 = "gfx/scoreboard/playercolor_base";
-                                       hud_field_icon1 = "gfx/scoreboard/playercolor_shirt";
-                                       hud_field_icon1_rgb = colormapPaletteColor(floor(f / 16), 0);
-                                       hud_field_icon2 = "gfx/scoreboard/playercolor_pants";
-                                       hud_field_icon2_rgb = colormapPaletteColor(f % 16, 1);
-                               }
-                       }
-                       return entcs_GetName(pl.sv_entnum);
-
-               case SP_FRAGS:
-                       f = pl.(scores[SP_KILLS]);
-                       f -= pl.(scores[SP_SUICIDES]);
-                       return ftos(f);
-
-               case SP_KDRATIO:
-                       num = pl.(scores[SP_KILLS]);
-                       denom = pl.(scores[SP_DEATHS]);
-
-                       if(denom == 0) {
-                               hud_field_rgb = '0 1 0';
-                               str = sprintf("%d", num);
-                       } else if(num <= 0) {
-                               hud_field_rgb = '1 0 0';
-                               str = sprintf("%.1f", num/denom);
-                       } else
-                               str = sprintf("%.1f", num/denom);
-                       return str;
-
-               case SP_SUM:
-                       f = pl.(scores[SP_KILLS]);
-                       f -= pl.(scores[SP_DEATHS]);
-
-                       if(f > 0) {
-                               hud_field_rgb = '0 1 0';
-                       } else if(f == 0) {
-                               hud_field_rgb = '1 1 1';
-                       } else {
-                               hud_field_rgb = '1 0 0';
-                       }
-                       return ftos(f);
-
-               case SP_DMG:
-                       num = pl.(scores[SP_DMG]);
-                       denom = 1000;
-
-                       str = sprintf("%.1f k", num/denom);
-                       return str;
-
-               case SP_DMGTAKEN:
-                       num = pl.(scores[SP_DMGTAKEN]);
-                       denom = 1000;
-
-                       str = sprintf("%.1f k", num/denom);
-                       return str;
-
-               default:
-                       tmp = pl.(scores[field]);
-                       f = scores_flags[field];
-                       if(field == ps_primary)
-                               hud_field_rgb = '1 1 0';
-                       else if(field == ps_secondary)
-                               hud_field_rgb = '0 1 1';
-                       else
-                               hud_field_rgb = '1 1 1';
-                       return ScoreString(f, tmp);
-       }
-       //return "error";
-}
-
-float hud_fixscoreboardcolumnwidth_len;
-float hud_fixscoreboardcolumnwidth_iconlen;
-float hud_fixscoreboardcolumnwidth_marginlen;
-
-string HUD_FixScoreboardColumnWidth(int i, string str)
-{
-    TC(int, i);
-       float field, f;
-       vector sz;
-       field = hud_field[i];
-
-       hud_fixscoreboardcolumnwidth_iconlen = 0;
-
-       if(hud_field_icon0 != "")
-       {
-               sz = draw_getimagesize(hud_field_icon0);
-               f = sz.x / sz.y;
-               if(hud_fixscoreboardcolumnwidth_iconlen < f)
-                       hud_fixscoreboardcolumnwidth_iconlen = f;
-       }
-
-       if(hud_field_icon1 != "")
-       {
-               sz = draw_getimagesize(hud_field_icon1);
-               f = sz.x / sz.y;
-               if(hud_fixscoreboardcolumnwidth_iconlen < f)
-                       hud_fixscoreboardcolumnwidth_iconlen = f;
-       }
-
-       if(hud_field_icon2 != "")
-       {
-               sz = draw_getimagesize(hud_field_icon2);
-               f = sz.x / sz.y;
-               if(hud_fixscoreboardcolumnwidth_iconlen < f)
-                       hud_fixscoreboardcolumnwidth_iconlen = f;
-       }
-
-       hud_fixscoreboardcolumnwidth_iconlen *= hud_fontsize.y / hud_fontsize.x; // fix icon aspect
-
-       if(hud_fixscoreboardcolumnwidth_iconlen != 0)
-               hud_fixscoreboardcolumnwidth_marginlen = stringwidth(" ", false, hud_fontsize);
-       else
-               hud_fixscoreboardcolumnwidth_marginlen = 0;
-
-       if(field == SP_NAME) // name gets all remaining space
-       {
-               int j;
-               float namesize;
-               namesize = sbwidth;// / hud_fontsize_x;
-               for(j = 0; j < hud_num_fields; ++j)
-                       if(j != i)
-                               if (hud_field[i] != SP_SEPARATOR)
-                                       namesize -= hud_size[j] + hud_fontsize.x;
-               namesize += hud_fontsize.x;
-               hud_size[i] = namesize;
-
-               if (hud_fixscoreboardcolumnwidth_iconlen != 0)
-                       namesize -= hud_fixscoreboardcolumnwidth_marginlen + hud_fixscoreboardcolumnwidth_iconlen;
-               str = textShortenToWidth(str, namesize, hud_fontsize, stringwidth_colors);
-               hud_fixscoreboardcolumnwidth_len = stringwidth(str, true, hud_fontsize);
-       }
-       else
-               hud_fixscoreboardcolumnwidth_len = stringwidth(str, false, hud_fontsize);
-
-       f = hud_fixscoreboardcolumnwidth_len + hud_fixscoreboardcolumnwidth_marginlen + hud_fixscoreboardcolumnwidth_iconlen;
-       if(hud_size[i] < f)
-               hud_size[i] = f;
-
-       return str;
-}
-
-void HUD_PrintScoreboardItem(vector pos, vector item_size, entity pl, bool is_self, int pl_number)
-{
-    TC(bool, is_self); TC(int, pl_number);
-       vector tmp, rgb;
-       rgb = Team_ColorRGB(pl.team);
-       string str;
-       int field;
-       float is_spec;
-       is_spec = (entcs_GetTeam(pl.sv_entnum) == NUM_SPECTATOR);
-
-       if((rgb == '1 1 1') && (!is_spec)) {
-               rgb.x = autocvar_scoreboard_color_bg_r + 0.5;
-               rgb.y = autocvar_scoreboard_color_bg_g + 0.5;
-               rgb.z = autocvar_scoreboard_color_bg_b + 0.5; }
-
-       vector h_pos = pos - '1 1 0';
-       vector h_size = item_size + '2 0 0';
-       // alternated rows highlighting
-       if(is_self)
-               drawfill(h_pos, h_size, rgb, scoreboard_highlight_alpha_self, DRAWFLAG_NORMAL);
-       else if((scoreboard_highlight) && (!(pl_number % 2)))
-               drawfill(h_pos, h_size, rgb, scoreboard_highlight_alpha, DRAWFLAG_NORMAL);
-
-       tmp.x = item_size.x;
-       tmp.y = 0;
-       tmp.z = 0;
-       int i;
-       for(i = 0; i < hud_num_fields; ++i)
-       {
-               field = hud_field[i];
-               if(field == SP_SEPARATOR)
-                       break;
-
-               if(is_spec && field != SP_NAME && field != SP_PING) {
-                       pos.x += hud_size[i] + hud_fontsize.x;
-                       continue;
-               }
-               str = HUD_GetField(pl, field);
-               str = HUD_FixScoreboardColumnWidth(i, str);
-
-               pos.x += hud_size[i] + hud_fontsize.x;
-
-               if(field == SP_NAME) {
-                       tmp.x = hud_size[i] - hud_fontsize.x*hud_fixscoreboardcolumnwidth_iconlen - hud_fixscoreboardcolumnwidth_marginlen + hud_fontsize.x;
-                       if (is_self)
-                               drawcolorcodedstring(pos - tmp, str, hud_fontsize, scoreboard_alpha_name_self, DRAWFLAG_NORMAL);
-                       else
-                               drawcolorcodedstring(pos - tmp, str, hud_fontsize, scoreboard_alpha_name, DRAWFLAG_NORMAL);
-               } else {
-                       tmp.x = hud_fixscoreboardcolumnwidth_len + hud_fontsize.x;
-                       if (is_self)
-                               drawstring(pos - tmp, str, hud_fontsize, hud_field_rgb, scoreboard_alpha_name_self, DRAWFLAG_NORMAL);
-                       else
-                               drawstring(pos - tmp, str, hud_fontsize, hud_field_rgb, scoreboard_alpha_name, DRAWFLAG_NORMAL);
-               }
-
-               tmp.x = hud_size[i] + hud_fontsize.x;
-               if(hud_field_icon0 != "")
-                       if (is_self)
-                               drawpic(pos - tmp, hud_field_icon0, '0 1 0' * hud_fontsize.y + '1 0 0' * hud_fontsize.x * hud_fixscoreboardcolumnwidth_iconlen, hud_field_icon1_rgb, hud_field_icon0_alpha * scoreboard_alpha_name_self, DRAWFLAG_NORMAL);
-                       else
-                               drawpic(pos - tmp, hud_field_icon0, '0 1 0' * hud_fontsize.y + '1 0 0' * hud_fontsize.x * hud_fixscoreboardcolumnwidth_iconlen, hud_field_icon1_rgb, hud_field_icon0_alpha * scoreboard_alpha_name, DRAWFLAG_NORMAL);
-               if(hud_field_icon1 != "")
-                       if (is_self)
-                               drawpic(pos - tmp, hud_field_icon1, '0 1 0' * hud_fontsize.y + '1 0 0' * hud_fontsize.x * hud_fixscoreboardcolumnwidth_iconlen, hud_field_icon1_rgb, hud_field_icon1_alpha * scoreboard_alpha_name_self, DRAWFLAG_NORMAL);
-                       else
-                               drawpic(pos - tmp, hud_field_icon1, '0 1 0' * hud_fontsize.y + '1 0 0' * hud_fontsize.x * hud_fixscoreboardcolumnwidth_iconlen, hud_field_icon1_rgb, hud_field_icon1_alpha * scoreboard_alpha_name, DRAWFLAG_NORMAL);
-               if(hud_field_icon2 != "")
-                       if (is_self)
-                               drawpic(pos - tmp, hud_field_icon2, '0 1 0' * hud_fontsize.y + '1 0 0' * hud_fontsize.x * hud_fixscoreboardcolumnwidth_iconlen, hud_field_icon2_rgb, hud_field_icon2_alpha * scoreboard_alpha_name_self, DRAWFLAG_NORMAL);
-                       else
-                               drawpic(pos - tmp, hud_field_icon2, '0 1 0' * hud_fontsize.y + '1 0 0' * hud_fontsize.x * hud_fixscoreboardcolumnwidth_iconlen, hud_field_icon2_rgb, hud_field_icon2_alpha * scoreboard_alpha_name, DRAWFLAG_NORMAL);
-       }
-
-       if(hud_field[i] == SP_SEPARATOR)
-       {
-               pos.x = xmax;
-               for(i = hud_num_fields-1; i > 0; --i)
-               {
-                       field = hud_field[i];
-                       if(field == SP_SEPARATOR)
-                               break;
-
-                       if(is_spec && field != SP_NAME && field != SP_PING) {
-                               pos.x -= hud_size[i] + hud_fontsize.x;
-                               continue;
-                       }
-
-                       str = HUD_GetField(pl, field);
-                       str = HUD_FixScoreboardColumnWidth(i, str);
-
-                       if(field == SP_NAME) {
-                               tmp.x = hud_fixscoreboardcolumnwidth_len; // left or right aligned? let's put it right...
-                               if(is_self)
-                                       drawcolorcodedstring(pos - tmp, str, hud_fontsize, scoreboard_alpha_name_self, DRAWFLAG_NORMAL);
-                               else
-                                       drawcolorcodedstring(pos - tmp, str, hud_fontsize, scoreboard_alpha_name, DRAWFLAG_NORMAL);
-                       } else {
-                               tmp.x = hud_fixscoreboardcolumnwidth_len;
-                               if(is_self)
-                                       drawstring(pos - tmp, str, hud_fontsize, hud_field_rgb, scoreboard_alpha_name_self, DRAWFLAG_NORMAL);
-                               else
-                                       drawstring(pos - tmp, str, hud_fontsize, hud_field_rgb, scoreboard_alpha_name, DRAWFLAG_NORMAL);
-                       }
-
-                       tmp.x = hud_size[i];
-                       if(hud_field_icon0 != "")
-                               if (is_self)
-                                       drawpic(pos - tmp, hud_field_icon0, '0 1 0' * hud_fontsize.y + '1 0 0' * hud_fontsize.x * hud_fixscoreboardcolumnwidth_iconlen, hud_field_icon1_rgb, hud_field_icon0_alpha * scoreboard_alpha_name_self, DRAWFLAG_NORMAL);
-                               else
-                                       drawpic(pos - tmp, hud_field_icon0, '0 1 0' * hud_fontsize.y + '1 0 0' * hud_fontsize.x * hud_fixscoreboardcolumnwidth_iconlen, hud_field_icon1_rgb, hud_field_icon0_alpha * scoreboard_alpha_name, DRAWFLAG_NORMAL);
-                       if(hud_field_icon1 != "")
-                               if (is_self)
-                                       drawpic(pos - tmp, hud_field_icon1, '0 1 0' * hud_fontsize.y + '1 0 0' * hud_fontsize.x * hud_fixscoreboardcolumnwidth_iconlen, hud_field_icon1_rgb, hud_field_icon1_alpha * scoreboard_alpha_name_self, DRAWFLAG_NORMAL);
-                               else
-                                       drawpic(pos - tmp, hud_field_icon1, '0 1 0' * hud_fontsize.y + '1 0 0' * hud_fontsize.x * hud_fixscoreboardcolumnwidth_iconlen, hud_field_icon1_rgb, hud_field_icon1_alpha * scoreboard_alpha_name, DRAWFLAG_NORMAL);
-                       if(hud_field_icon2 != "")
-                               if (is_self)
-                                       drawpic(pos - tmp, hud_field_icon2, '0 1 0' * hud_fontsize.y + '1 0 0' * hud_fontsize.x * hud_fixscoreboardcolumnwidth_iconlen, hud_field_icon2_rgb, hud_field_icon2_alpha * scoreboard_alpha_name_self, DRAWFLAG_NORMAL);
-                               else
-                                       drawpic(pos - tmp, hud_field_icon2, '0 1 0' * hud_fontsize.y + '1 0 0' * hud_fontsize.x * hud_fixscoreboardcolumnwidth_iconlen, hud_field_icon2_rgb, hud_field_icon2_alpha * scoreboard_alpha_name, DRAWFLAG_NORMAL);
-                       pos.x -= hud_size[i] + hud_fontsize.x;
-               }
-       }
-
-       if(pl.eliminated)
-               drawfill(h_pos, h_size, '0 0 0', 0.5, DRAWFLAG_NORMAL);
-}
-
-/*
- * HUD_Scoreboard_MakeTable
- *
- * Makes a table for a team (for all playing players in DM) and fills it
- */
-
-vector HUD_Scoreboard_MakeTable(vector pos, entity tm, vector rgb, vector bg_size)
-{
-       float body_table_height;
-       vector tmp = '0 0 0', column_dim = '0 0 0';
-       entity pl;
-
-       body_table_height = 1.25 * hud_fontsize.y * max(1, tm.team_size); // no player? show 1 empty line
-
-       pos.y += autocvar_scoreboard_border_thickness;
-       pos -= '1 1 0';
-
-       tmp.x = sbwidth + 2;
-       tmp.y = 1.25 * hud_fontsize.y;
-
-       // rounded header
-       if (teamplay)
-               drawpic(pos, "gfx/scoreboard/scoreboard_tableheader", tmp, (rgb * autocvar_scoreboard_color_bg_team) + '0.5 0.5 0.5', scoreboard_alpha_bg, DRAWFLAG_NORMAL);
-       else
-               drawpic(pos, "gfx/scoreboard/scoreboard_tableheader", tmp, rgb + '0.5 0.5 0.5', scoreboard_alpha_bg, DRAWFLAG_NORMAL);
-
-       // table border
-       tmp.y += autocvar_scoreboard_border_thickness;
-       tmp.y += body_table_height;
-       drawborderlines(autocvar_scoreboard_border_thickness, pos, tmp, '0 0 0', scoreboard_alpha_bg, DRAWFLAG_NORMAL); // more transparency for the scoreboard
-
-       // separator header/table
-       pos.y += 1.25 * hud_fontsize.y;
-       tmp.y = autocvar_scoreboard_border_thickness;
-       drawfill(pos, tmp, '0 0 0', scoreboard_alpha_bg, DRAWFLAG_NORMAL);
-
-       pos.y += autocvar_scoreboard_border_thickness;
-
-       // table background
-       tmp.y = body_table_height;
-       if (teamplay)
-               drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb * autocvar_scoreboard_color_bg_team, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
-       else
-               drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
-
-       // anyway, apply some color
-       //drawfill(pos, tmp + '2 0 0', rgb, 0.1, DRAWFLAG_NORMAL);
-
-       // go back to the top to make alternated columns highlighting and to print the strings
-       pos.y -= 1.25 * hud_fontsize.y;
-       pos.y -= autocvar_scoreboard_border_thickness;
-
-       pos += '1 1 0';
-
-       if (scoreboard_highlight)
-       {
-               column_dim.y = 1.25 * hud_fontsize.y; // header
-               column_dim.y += autocvar_scoreboard_border_thickness;
-               column_dim.y += body_table_height;
-       }
-
-       // print the strings of the columns headers and draw the columns
-       int i;
-       for(i = 0; i < hud_num_fields; ++i)
-       {
-               if(hud_field[i] == SP_SEPARATOR)
-                       break;
-               column_dim.x = hud_size[i] + hud_fontsize.x;
-               if (scoreboard_highlight)
-               {
-                       if (i % 2)
-                               drawfill(pos - '0 1 0' - hud_fontsize.x / 2 * '1 0 0', column_dim, '0 0 0', scoreboard_alpha_bg * 0.2, DRAWFLAG_NORMAL);
-               }
-               drawstring(pos, hud_title[i], hud_fontsize, rgb * 1.5, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
-               pos.x += column_dim.x;
-       }
-       if(hud_field[i] == SP_SEPARATOR)
-       {
-               pos.x = xmax;
-               tmp.y = 0;
-               for(i = hud_num_fields-1; i > 0; --i)
-               {
-                       if(hud_field[i] == SP_SEPARATOR)
-                               break;
-
-                       pos.x -= hud_size[i];
-
-                       if (scoreboard_highlight)
-                       {
-                               if (!(i % 2))
-                               {
-                                       if (i == hud_num_fields-1)
-                                               column_dim.x = hud_size[i] + hud_fontsize.x / 2 + 1;
-                                       else
-                                               column_dim.x = hud_size[i] + hud_fontsize.x;
-                                       drawfill(pos - '0 1 0' - hud_fontsize.x / 2 * '1 0 0', column_dim, '0 0 0', scoreboard_alpha_bg * 0.2, DRAWFLAG_NORMAL);
-                               }
-                       }
-
-                       tmp.x = stringwidth(hud_title[i], false, hud_fontsize);
-                       tmp.x = (hud_size[i] - tmp.x);
-                       drawstring(pos + tmp, hud_title[i], hud_fontsize, rgb * 1.5, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
-                       pos.x -= hud_fontsize.x;
-               }
-       }
-
-       pos.x = xmin;
-       pos.y += 1.25 * hud_fontsize.y; // skip the header
-       pos.y += autocvar_scoreboard_border_thickness;
-
-       // item size
-       tmp.x = sbwidth;
-       tmp.y = hud_fontsize.y * 1.25;
-
-       // fill the table and draw the rows
-       i = 0;
-       if (teamplay)
-               for(pl = players.sort_next; pl; pl = pl.sort_next)
-               {
-                       if(pl.team != tm.team)
-                               continue;
-                       HUD_PrintScoreboardItem(pos, tmp, pl, (pl.sv_entnum == player_localnum), i);
-                       pos.y += 1.25 * hud_fontsize.y;
-                       ++i;
-               }
-       else
-               for(pl = players.sort_next; pl; pl = pl.sort_next)
-               {
-                       if(pl.team == NUM_SPECTATOR)
-                               continue;
-                       HUD_PrintScoreboardItem(pos, tmp, pl, (pl.sv_entnum == player_localnum), i);
-                       pos.y += 1.25 * hud_fontsize.y;
-                       ++i;
-               }
-
-       if (i == 0)
-               pos.y += 1.25 * hud_fontsize.y; // move to the end of the table
-       pos.y += 1.25 * hud_fontsize.y; // move empty row (out of the table)
-
-       return pos;
-}
-
-float HUD_WouldDrawScoreboard() {
-       if (autocvar__hud_configure)
-               return 0;
-       else if (QuickMenu_IsOpened())
-               return 0;
-       else if (HUD_Radar_Clickable())
-               return 0;
-       else if (scoreboard_showscores)
-               return 1;
-       else if (intermission == 1)
-               return 1;
-       else if (intermission == 2)
-               return 0;
-       else if (spectatee_status != -1 && STAT(HEALTH) <= 0 && autocvar_cl_deathscoreboard && gametype != MAPINFO_TYPE_CTS && !active_minigame)
-               return 1;
-       else if (scoreboard_showscores_force)
-               return 1;
-       return 0;
-}
-
-float average_accuracy;
-vector HUD_DrawScoreboardAccuracyStats(vector pos, vector rgb, vector bg_size)
-{
-       WepSet weapons_stat = WepSet_GetFromStat();
-       WepSet weapons_inmap = WepSet_GetFromStat_InMap();
-       float initial_posx = pos.x;
-       int disownedcnt = 0;
-       FOREACH(Weapons, it != WEP_Null, {
-               int weapon_stats = weapon_accuracy[i - WEP_FIRST];
-
-               WepSet set = it.m_wepset;
-               if (weapon_stats < 0 && !(weapons_stat & set || weapons_inmap & set))
-                       ++disownedcnt;
-       });
-
-       int weapon_cnt = (Weapons_COUNT - 1) - disownedcnt;
-       if (weapon_cnt <= 0) return pos;
-
-       int rows = 1;
-       if (autocvar_scoreboard_accuracy_doublerows && weapon_cnt >= floor((Weapons_COUNT - 1) * 0.5))
-               rows = 2;
-       int columnns = ceil(weapon_cnt / rows);
-
-       float height = 40;
-       float fontsize = height * 1/3;
-       float weapon_height = height * 2/3;
-       float weapon_width = sbwidth / columnns / rows;
-
-       drawstring(pos, sprintf(_("Accuracy stats (average %d%%)"), average_accuracy), hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
-       pos.y += 1.25 * hud_fontsize.y + autocvar_scoreboard_border_thickness;
-       vector tmp = '0 0 0';
-       tmp.x = sbwidth;
-       tmp.y = height * rows;
-
-       if (teamplay)
-               drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb * autocvar_scoreboard_color_bg_team, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
-       else
-               drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
-       drawborderlines(autocvar_scoreboard_border_thickness, pos, tmp, '0 0 0', scoreboard_alpha_bg * 0.75, DRAWFLAG_NORMAL);
-
-       // column highlighting
-       for (int i = 0; i < columnns; ++i)
-       {
-               if ((i % 2) == 0)
-                       drawfill(pos + '1 0 0' * weapon_width * rows * i, '0 1 0' * height * rows + '1 0 0' * weapon_width * rows, '0 0 0', scoreboard_alpha_bg * 0.2, DRAWFLAG_NORMAL);
-       }
-
-       // row highlighting
-       for (int i = 0; i < rows; ++i)
-       {
-               drawfill(pos + '0 1 0' * weapon_height + '0 1 0' * height * i, '1 0 0' * sbwidth + '0 1 0' * fontsize, '1 1 1', scoreboard_highlight_alpha, DRAWFLAG_NORMAL);
-       }
-
-       average_accuracy = 0;
-       int weapons_with_stats = 0;
-       if (rows == 2)
-               pos.x += weapon_width / 2;
-
-       if (autocvar_scoreboard_accuracy_nocolors)
-               rgb = '1 1 1';
-       else
-               Accuracy_LoadColors();
-
-       float oldposx = pos.x;
-       vector tmpos = pos;
-
-       int column = 0;
-       FOREACH(Weapons, it != WEP_Null, {
-               int weapon_stats = weapon_accuracy[i - WEP_FIRST];
-
-               WepSet set = it.m_wepset;
-               if (weapon_stats < 0 && !(weapons_stat & set || weapons_inmap & set))
-                       continue;
-
-               float weapon_alpha;
-               if (weapon_stats >= 0)
-                       weapon_alpha = scoreboard_alpha_fg;
-               else
-                       weapon_alpha = 0.2 * scoreboard_alpha_fg;
-
-               // weapon icon
-               drawpic_aspect_skin(tmpos, it.model2, '1 0 0' * weapon_width + '0 1 0' * weapon_height, '1 1 1', weapon_alpha, DRAWFLAG_NORMAL);
-               // the accuracy
-               if (weapon_stats >= 0) {
-                       weapons_with_stats += 1;
-                       average_accuracy += weapon_stats; // store sum of all accuracies in average_accuracy
-
-                       string s;
-                       s = sprintf("%d%%", weapon_stats*100);
-
-                       float padding;
-                       padding = (weapon_width - stringwidth(s, false, '1 0 0' * fontsize)) / 2; // center the accuracy value
-
-                       if(!autocvar_scoreboard_accuracy_nocolors)
-                               rgb = Accuracy_GetColor(weapon_stats);
-
-                       drawstring(tmpos + '1 0 0' * padding + '0 1 0' * weapon_height, s, '1 1 0' * fontsize, rgb, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
-               }
-               tmpos.x += weapon_width * rows;
-               pos.x += weapon_width * rows;
-               if (rows == 2 && column == columnns - 1) {
-                       tmpos.x = oldposx;
-                       tmpos.y += height;
-                       pos.y += height;
-               }
-               ++column;
-       });
-
-       if (weapons_with_stats)
-               average_accuracy = floor((average_accuracy * 100 / weapons_with_stats) + 0.5);
-
-       pos.y += height;
-       pos.y += 1.25 * hud_fontsize.y;
-       pos.x = initial_posx;
-       return pos;
-}
-
-vector HUD_DrawKeyValue(vector pos, string key, string value) {
-       float px = pos.x;
-       pos.x += hud_fontsize.x * 0.25;
-       drawstring(pos, key, hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
-       pos.x = xmax - stringwidth(value, false, hud_fontsize) - hud_fontsize.x * 0.25;
-       drawstring(pos, value, hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
-       pos.x = px;
-       pos.y+= hud_fontsize.y;
-
-       return pos;
-}
-
-vector HUD_DrawMapStats(vector pos, vector rgb, vector bg_size) {
-       float stat_secrets_found, stat_secrets_total;
-       float stat_monsters_killed, stat_monsters_total;
-       float rows = 0;
-       string val;
-
-       // get monster stats
-       stat_monsters_killed = STAT(MONSTERS_KILLED);
-       stat_monsters_total = STAT(MONSTERS_TOTAL);
-
-       // get secrets stats
-       stat_secrets_found = STAT(SECRETS_FOUND);
-       stat_secrets_total = STAT(SECRETS_TOTAL);
-
-       // get number of rows
-       if(stat_secrets_total)
-               rows += 1;
-       if(stat_monsters_total)
-               rows += 1;
-
-       // if no rows, return
-       if (!rows)
-               return pos;
-
-       //  draw table header
-       drawstring(pos, _("Map stats:"), hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
-       pos.y += 1.25 * hud_fontsize.y + autocvar_scoreboard_border_thickness;
-
-       // draw table
-       vector tmp = '0 0 0';
-       tmp.x = sbwidth;
-       tmp.y = hud_fontsize.y * rows;
-
-       if (teamplay)
-               drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb * autocvar_scoreboard_color_bg_team, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
-       else
-               drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
-       drawborderlines(autocvar_scoreboard_border_thickness, pos, tmp, '0 0 0', scoreboard_alpha_bg * 0.75, DRAWFLAG_NORMAL);
-
-       // draw monsters
-       if(stat_monsters_total)
-       {
-               val = sprintf("%d/%d", stat_monsters_killed, stat_monsters_total);
-               pos = HUD_DrawKeyValue(pos, _("Monsters killed:"), val);
-       }
-
-       // draw secrets
-       if(stat_secrets_total)
-       {
-               val = sprintf("%d/%d", stat_secrets_found, stat_secrets_total);
-               pos = HUD_DrawKeyValue(pos, _("Secrets found:"), val);
-       }
-
-       // update position
-       pos.y += 1.25 * hud_fontsize.y;
-       return pos;
-}
-
-
-vector HUD_DrawScoreboardRankings(vector pos, entity pl,  vector rgb, vector bg_size)
-{
-       int i;
-       RANKINGS_RECEIVED_CNT = 0;
-       for (i=RANKINGS_CNT-1; i>=0; --i)
-               if (grecordtime[i])
-                       ++RANKINGS_RECEIVED_CNT;
-
-       if (RANKINGS_RECEIVED_CNT == 0)
-               return pos;
-
-       float is_spec;
-       is_spec = (entcs_GetTeam(pl.sv_entnum) == NUM_SPECTATOR);
-       vector hl_rgb;
-       hl_rgb.x = autocvar_scoreboard_color_bg_r + 0.5;
-       hl_rgb.y = autocvar_scoreboard_color_bg_g + 0.5;
-       hl_rgb.z = autocvar_scoreboard_color_bg_b + 0.5;
-
-       pos.y += hud_fontsize.y;
-       drawstring(pos, _("Rankings"), hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
-       pos.y += hud_fontsize.y + autocvar_scoreboard_border_thickness;
-       vector tmp = '0 0 0';
-       tmp.x = sbwidth;
-       tmp.y = 1.25 * hud_fontsize.y * RANKINGS_RECEIVED_CNT;
-
-       if (teamplay)
-               drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb * autocvar_scoreboard_color_bg_team, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
-       else
-               drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
-       drawborderlines(autocvar_scoreboard_border_thickness, pos, tmp, '0 0 0', scoreboard_alpha_bg * 0.75, DRAWFLAG_NORMAL);
-
-       // row highlighting
-       for(i = 0; i<RANKINGS_RECEIVED_CNT; ++i)
-       {
-               string n, p;
-               float t;
-               t = grecordtime[i];
-               if (t == 0)
-                       continue;
-               n = grecordholder[i];
-               p = count_ordinal(i+1);
-               if(grecordholder[i] == entcs_GetName(player_localnum))
-                       drawfill(pos, '1 0 0' * sbwidth + '0 1.25 0' * hud_fontsize.y, hl_rgb, scoreboard_highlight_alpha_self, DRAWFLAG_NORMAL);
-               else if(!(i % 2) && scoreboard_highlight)
-                       drawfill(pos, '1 0 0' * sbwidth + '0 1.25 0' * hud_fontsize.y, hl_rgb, scoreboard_highlight_alpha, DRAWFLAG_NORMAL);
-               drawstring(pos, p, '1 1 0' * hud_fontsize.y, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
-               drawstring(pos + '3 0 0' * hud_fontsize.y, TIME_ENCODED_TOSTRING(t), '1 1 0' * hud_fontsize.y, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
-               drawcolorcodedstring(pos + '8 0 0' * hud_fontsize.y, n, '1 1 0' * hud_fontsize.y, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
-               pos.y += 1.25 * hud_fontsize.y;
-       }
-       pos.y += autocvar_scoreboard_border_thickness;
-
-       return pos;
-}
-
-float hud_woulddrawscoreboard_prev;
-float hud_woulddrawscoreboard_change; // "time" at which HUD_WouldDrawScoreboard() changed
-void HUD_DrawScoreboard()
-{
-       float hud_woulddrawscoreboard;
-       hud_woulddrawscoreboard = scoreboard_active;
-       if(hud_woulddrawscoreboard != hud_woulddrawscoreboard_prev) {
-               hud_woulddrawscoreboard_change = time;
-               hud_woulddrawscoreboard_prev = hud_woulddrawscoreboard;
-       }
-
-       if(hud_woulddrawscoreboard) {
-               float scoreboard_fadeinspeed = autocvar_scoreboard_fadeinspeed;
-               if (scoreboard_fadeinspeed)
-                       scoreboard_fade_alpha = bound (0, (time - hud_woulddrawscoreboard_change) * scoreboard_fadeinspeed, 1);
-               else
-                       scoreboard_fade_alpha = 1;
-       }
-       else {
-               float scoreboard_fadeoutspeed = autocvar_scoreboard_fadeoutspeed;
-               if (scoreboard_fadeoutspeed)
-                       scoreboard_fade_alpha = bound (0, (1/scoreboard_fadeoutspeed - (time - hud_woulddrawscoreboard_change)) * scoreboard_fadeoutspeed, 1);
-               else
-                       scoreboard_fade_alpha = 0;
-       }
-
-       if (!scoreboard_fade_alpha)
-               return;
-
-       if (autocvar_scoreboard_dynamichud)
-               HUD_Scale_Enable();
-       else
-               HUD_Scale_Disable();
-
-       HUD_UpdatePlayerTeams();
-
-       scoreboard_alpha_bg = autocvar_scoreboard_alpha_bg * scoreboard_fade_alpha * (1 - autocvar__menu_alpha);
-       scoreboard_alpha_fg = autocvar_scoreboard_alpha_fg * scoreboard_fade_alpha * (1 - autocvar__menu_alpha);
-       scoreboard_highlight = autocvar_scoreboard_highlight;
-       scoreboard_highlight_alpha = autocvar_scoreboard_highlight_alpha * scoreboard_alpha_fg;
-       scoreboard_highlight_alpha_self = autocvar_scoreboard_highlight_alpha_self * scoreboard_alpha_fg;
-       scoreboard_alpha_name = autocvar_scoreboard_alpha_name * scoreboard_alpha_fg;
-       scoreboard_alpha_name_self = autocvar_scoreboard_alpha_name_self * scoreboard_alpha_fg;
-
-       vector rgb, pos, tmp;
-       entity pl, tm;
-       string str;
-
-       xmin = (autocvar_scoreboard_offset_left * vid_conwidth);
-       ymin = max((autocvar_con_notify * autocvar_con_notifysize), (autocvar_scoreboard_offset_vertical * vid_conwidth));
-
-       xmax = ((1 - autocvar_scoreboard_offset_right) * vid_conwidth);
-       ymax = (vid_conheight - ymin);
-
-       sbwidth = xmax - xmin;
-
-       // Initializes position
-       pos.x = xmin;
-       pos.y = ymin;
-       pos.z = 0;
-
-       // Heading
-       vector sb_heading_fontsize;
-       sb_heading_fontsize = hud_fontsize * 2;
-       draw_beginBoldFont();
-       drawstring(pos, _("Scoreboard"), sb_heading_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
-       draw_endBoldFont();
-
-       pos.y += sb_heading_fontsize.y + hud_fontsize.y * 0.25;
-
-       // Draw the scoreboard
-       vector bg_size = draw_getimagesize("gfx/scoreboard/scoreboard_bg") * ((autocvar_scoreboard_bg_scale > 0) ? autocvar_scoreboard_bg_scale : 0.25);
-
-       if(teamplay)
-       {
-               vector team_score_baseoffset;
-               team_score_baseoffset = eY * (2 * autocvar_scoreboard_border_thickness + hud_fontsize.y) - eX * (autocvar_scoreboard_border_thickness + hud_fontsize.x * 0.25);
-               for(tm = teams.sort_next; tm; tm = tm.sort_next)
-               {
-                       if(tm.team == NUM_SPECTATOR)
-                               continue;
-                       if(!tm.team && teamplay)
-                               continue;
-
-                       draw_beginBoldFont();
-                       rgb = Team_ColorRGB(tm.team);
-                       str = ftos(tm.(teamscores[ts_primary]));
-                       drawstring(pos + team_score_baseoffset - eX * stringwidth(str, false, hud_fontsize * 1.5), str, hud_fontsize * 1.5, rgb, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
-
-                       if(ts_primary != ts_secondary)
-                       {
-                               str = ftos(tm.(teamscores[ts_secondary]));
-                               drawstring(pos + team_score_baseoffset - eX * stringwidth(str, false, hud_fontsize) + eY * hud_fontsize.y * 1.5, str, hud_fontsize, rgb, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
-                       }
-                       draw_endBoldFont();
-
-                       pos = HUD_Scoreboard_MakeTable(pos, tm, rgb, bg_size);
-               }
-               rgb.x = autocvar_scoreboard_color_bg_r;
-               rgb.y = autocvar_scoreboard_color_bg_g;
-               rgb.z = autocvar_scoreboard_color_bg_b;
-       }
-       else
-       {
-               rgb.x = autocvar_scoreboard_color_bg_r;
-               rgb.y = autocvar_scoreboard_color_bg_g;
-               rgb.z = autocvar_scoreboard_color_bg_b;
-
-               for(tm = teams.sort_next; tm; tm = tm.sort_next)
-               {
-                       if(tm.team == NUM_SPECTATOR)
-                               continue;
-                       if(!tm.team && teamplay)
-                               continue;
-
-                       pos = HUD_Scoreboard_MakeTable(pos, tm, rgb, bg_size);
-               }
-       }
-
-       if(gametype == MAPINFO_TYPE_CTS || gametype == MAPINFO_TYPE_RACE) {
-               if(race_speedaward) {
-                       drawcolorcodedstring(pos, sprintf(_("Speed award: %d%s ^7(%s^7)"), race_speedaward, race_speedaward_unit, race_speedaward_holder), hud_fontsize, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
-                       pos.y += 1.25 * hud_fontsize.y;
-               }
-               if(race_speedaward_alltimebest) {
-                       drawcolorcodedstring(pos, sprintf(_("All-time fastest: %d%s ^7(%s^7)"), race_speedaward_alltimebest, race_speedaward_alltimebest_unit, race_speedaward_alltimebest_holder), hud_fontsize, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
-                       pos.y += 1.25 * hud_fontsize.y;
-               }
-               pos = HUD_DrawScoreboardRankings(pos, playerslots[player_localnum], rgb, bg_size);
-       }
-       else if (autocvar_scoreboard_accuracy && !warmup_stage && gametype != MAPINFO_TYPE_NEXBALL) {
-               if(teamplay)
-                       pos = HUD_DrawScoreboardAccuracyStats(pos, Team_ColorRGB(myteam), bg_size);
-               else
-                       pos = HUD_DrawScoreboardAccuracyStats(pos, rgb, bg_size);
-       }
-
-
-       if(teamplay)
-               pos = HUD_DrawMapStats(pos, Team_ColorRGB(myteam), bg_size);
-       else
-               pos = HUD_DrawMapStats(pos, rgb, bg_size);
-
-       // List spectators
-       float specs;
-       specs = 0;
-       tmp = pos;
-       vector item_size;
-       item_size.x = sbwidth;
-       item_size.y = hud_fontsize.y * 1.25;
-       item_size.z = 0;
-       for(pl = players.sort_next; pl; pl = pl.sort_next)
-       {
-               if(pl.team != NUM_SPECTATOR)
-                       continue;
-               pos.y += 1.25 * hud_fontsize.y;
-               HUD_PrintScoreboardItem(pos, item_size, pl, (pl.sv_entnum == player_localnum), specs);
-               ++specs;
-       }
-
-       if(specs)
-       {
-               draw_beginBoldFont();
-               drawstring(tmp, _("Spectators"), hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
-               draw_endBoldFont();
-               pos.y += 1.25 * hud_fontsize.y;
-       }
-
-       // Print info string
-       float tl, fl, ll;
-       str = sprintf(_("playing ^3%s^7 on ^2%s^7"), MapInfo_Type_ToText(gametype), shortmapname);
-       tl = STAT(TIMELIMIT);
-       fl = STAT(FRAGLIMIT);
-       ll = STAT(LEADLIMIT);
-       if(gametype == MAPINFO_TYPE_LMS)
-       {
-               if(tl > 0)
-                       str = strcat(str, sprintf(_(" for up to ^1%1.0f minutes^7"), tl));
-       }
-       else
-       {
-               if(tl > 0)
-                       str = strcat(str, sprintf(_(" for up to ^1%1.0f minutes^7"), tl));
-               if(fl > 0)
-               {
-                       if(tl > 0)
-                               str = strcat(str, _(" or"));
-                       if(teamplay)
-                       {
-                               str = strcat(str, sprintf(_(" until ^3%s %s^7"), ScoreString(teamscores_flags[ts_primary], fl),
-                                       (teamscores_label[ts_primary] == "score")   ? CTX(_("SCO^points")) :
-                                       (teamscores_label[ts_primary] == "fastest") ? CTX(_("SCO^is beaten")) :
-                                       TranslateScoresLabel(teamscores_label[ts_primary])));
-                       }
-                       else
-                       {
-                               str = strcat(str, sprintf(_(" until ^3%s %s^7"), ScoreString(scores_flags[ps_primary], fl),
-                                       (scores_label[ps_primary] == "score")   ? CTX(_("SCO^points")) :
-                                       (scores_label[ps_primary] == "fastest") ? CTX(_("SCO^is beaten")) :
-                                       TranslateScoresLabel(scores_label[ps_primary])));
-                       }
-               }
-               if(ll > 0)
-               {
-                       if(tl > 0 || fl > 0)
-                               str = strcat(str, _(" or"));
-                       if(teamplay)
-                       {
-                               str = strcat(str, sprintf(_(" until a lead of ^3%s %s^7"), ScoreString(teamscores_flags[ts_primary], ll),
-                                       (teamscores_label[ts_primary] == "score")   ? CTX(_("SCO^points")) :
-                                       (teamscores_label[ts_primary] == "fastest") ? CTX(_("SCO^is beaten")) :
-                                       TranslateScoresLabel(teamscores_label[ts_primary])));
-                       }
-                       else
-                       {
-                               str = strcat(str, sprintf(_(" until a lead of ^3%s %s^7"), ScoreString(scores_flags[ps_primary], ll),
-                                       (scores_label[ps_primary] == "score")   ? CTX(_("SCO^points")) :
-                                       (scores_label[ps_primary] == "fastest") ? CTX(_("SCO^is beaten")) :
-                                       TranslateScoresLabel(scores_label[ps_primary])));
-                       }
-               }
-       }
-
-       pos.y += 1.2 * hud_fontsize.y;
-       drawcolorcodedstring(pos + '0.5 0 0' * (sbwidth - stringwidth(str, true, hud_fontsize)), str, hud_fontsize, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
-
-       // print information about respawn status
-       float respawn_time = STAT(RESPAWN_TIME);
-       if(!intermission)
-       if(respawn_time)
-       {
-               if(respawn_time < 0)
-               {
-                       // a negative number means we are awaiting respawn, time value is still the same
-                       respawn_time *= -1; // remove mark now that we checked it
-                       respawn_time = max(time, respawn_time); // don't show a negative value while the server is respawning the player (lag)
-
-                       str = sprintf(_("^1Respawning in ^3%s^1..."),
-                               (autocvar_scoreboard_respawntime_decimals ?
-                                       count_seconds_decs(respawn_time - time, autocvar_scoreboard_respawntime_decimals)
-                                       :
-                                       count_seconds(respawn_time - time)
-                               )
-                       );
-               }
-               else if(time < respawn_time)
-               {
-                       str = sprintf(_("You are dead, wait ^3%s^7 before respawning"),
-                               (autocvar_scoreboard_respawntime_decimals ?
-                                       count_seconds_decs(respawn_time - time, autocvar_scoreboard_respawntime_decimals)
-                                       :
-                                       count_seconds(respawn_time - time)
-                               )
-                       );
-               }
-               else if(time >= respawn_time)
-                       str = sprintf(_("You are dead, press ^2%s^7 to respawn"), getcommandkey("jump", "+jump"));
-
-               pos.y += 1.2 * hud_fontsize.y;
-               drawcolorcodedstring(pos + '0.5 0 0' * (sbwidth - stringwidth(str, true, hud_fontsize)), str, hud_fontsize, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
-       }
-
-       scoreboard_bottom = pos.y + 2 * hud_fontsize.y;
-}
diff --git a/qcsrc/client/scoreboard.qh b/qcsrc/client/scoreboard.qh
deleted file mode 100644 (file)
index 8fccae9..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-#pragma once
-
-float xmin, xmax, ymin, ymax, sbwidth;
-
-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);
-float HUD_WouldDrawScoreboard();
index 1458efe15f13563e9e869cb653c9e5c80791318c..339d05209d2e891dbc195458fecfd2ed7574838e 100644 (file)
@@ -3,8 +3,8 @@
 #include "announcer.qh"
 #include "hud/all.qh"
 #include "mapvoting.qh"
-#include "scoreboard.qh"
 #include "shownames.qh"
+#include "hud/panel/scoreboard.qh"
 #include "hud/panel/quickmenu.qh"
 
 #include "mutators/events.qh"
@@ -710,7 +710,7 @@ float TrueAimCheck()
 
 void PostInit();
 void CSQC_Demo_Camera();
-float HUD_WouldDrawScoreboard();
+float Scoreboard_WouldDraw();
 float camera_mode;
 const float CAMERA_FREE = 1;
 const float CAMERA_CHASE = 2;
@@ -792,7 +792,7 @@ void UpdateDamage()
        if (damage_dealt_time != damage_dealt_time_prev)
        {
                unaccounted_damage += unaccounted_damage_new;
-               LOG_TRACE("dmg total: ", ftos(unaccounted_damage), " (+", ftos(unaccounted_damage_new), ")", "\n");
+               LOG_TRACE("dmg total: ", ftos(unaccounted_damage), " (+", ftos(unaccounted_damage_new), ")");
        }
        damage_dealt_time_prev = damage_dealt_time;
 
@@ -832,7 +832,7 @@ void HitSound()
                                pitch_shift = mirror_value + (mirror_value - pitch_shift);
                        }
 
-                       LOG_TRACE("dmg total (dmg): ", ftos(unaccounted_damage), " , pitch shift: ", ftos(pitch_shift), "\n");
+                       LOG_TRACE("dmg total (dmg): ", ftos(unaccounted_damage), " , pitch shift: ", ftos(pitch_shift));
 
                        // todo: avoid very long and very short sounds from wave stretching using different sound files? seems unnecessary
                        // todo: normalize sound pressure levels? seems unnecessary
@@ -1350,7 +1350,6 @@ void HUD_Draw(entity this)
                                Accuracy_LoadLevels();
 
                        HUD_Main();
-                       HUD_DrawScoreboard();
                        HUD_Scale_Disable();
                }
 
@@ -1408,10 +1407,6 @@ void CSQC_UpdateView(entity this, float w, float h)
        else
                view_quality = 1;
 
-       // this needs to be updated manually now due to the destruction of engine physics stats
-       if(!isdemo() && autocvar_slowmo != STAT(MOVEVARS_TIMESCALE))
-               cvar_set("slowmo", ftos(STAT(MOVEVARS_TIMESCALE)));
-
        button_attack2 = PHYS_INPUT_BUTTON_ATCK2(this);
        button_zoom = PHYS_INPUT_BUTTON_ZOOM(this);
 
@@ -1777,7 +1772,7 @@ void CSQC_UpdateView(entity this, float w, float h)
        if(f != teamplay)
        {
                teamplay = f;
-               HUD_InitScores();
+               Scoreboard_InitScores();
        }
 
        if(last_switchweapon != switchweapon)
@@ -2206,7 +2201,7 @@ void CSQC_UpdateView(entity this, float w, float h)
        Draw_ShowNames_All();
        Debug_Draw();
 
-       scoreboard_active = HUD_WouldDrawScoreboard();
+       scoreboard_active = Scoreboard_WouldDraw();
 
        HUD_Draw(this); // this parameter for deep vehicle function
 
index 4015828e555fc6a41db87329254197072e3d9d58..6d58ac77a2d1a01f72688513ecc2708750d93622 100644 (file)
@@ -19,7 +19,7 @@
 void SUB_Stop(entity this, entity toucher)
 {
        this.velocity = this.avelocity = '0 0 0';
-       this.move_movetype = MOVETYPE_NONE;
+       set_movetype(this, MOVETYPE_NONE);
 }
 
 void Projectile_ResetTrail(entity this, vector to)
@@ -330,7 +330,7 @@ NET_HANDLE(ENT_CLIENT_PROJECTILE, bool isnew)
                this.maxs = '0 0 0';
                this.colormod = '0 0 0';
                settouch(this, SUB_Stop);
-               this.move_movetype = MOVETYPE_TOSS;
+               set_movetype(this, MOVETYPE_TOSS);
                this.alphamod = 1;
 
                switch (this.cnt)
@@ -340,7 +340,7 @@ NET_HANDLE(ENT_CLIENT_PROJECTILE, bool isnew)
                                loopsound(this, CH_SHOTS_SINGLE, SND(ELECTRO_FLY), VOL_BASE, ATTEN_NORM);
                                this.mins = '-4 -4 -4';
                                this.maxs = '4 4 4';
-                               this.move_movetype = MOVETYPE_BOUNCE;
+                               set_movetype(this, MOVETYPE_BOUNCE);
                                settouch(this, func_null);
                                this.bouncefactor = WEP_CVAR_SEC(electro, bouncefactor);
                                this.bouncestop = WEP_CVAR_SEC(electro, bouncestop);
@@ -358,7 +358,7 @@ NET_HANDLE(ENT_CLIENT_PROJECTILE, bool isnew)
                        case PROJECTILE_GRENADE_BOUNCING:
                                this.mins = '-3 -3 -3';
                                this.maxs = '3 3 3';
-                               this.move_movetype = MOVETYPE_BOUNCE;
+                               set_movetype(this, MOVETYPE_BOUNCE);
                                settouch(this, func_null);
                                this.bouncefactor = WEP_CVAR(mortar, bouncefactor);
                                this.bouncestop = WEP_CVAR(mortar, bouncestop);
@@ -376,21 +376,21 @@ NET_HANDLE(ENT_CLIENT_PROJECTILE, bool isnew)
                        case PROJECTILE_PORTO_RED:
                                this.colormod = '2 1 1';
                                this.alphamod = 0.5;
-                               this.move_movetype = MOVETYPE_BOUNCE;
+                               set_movetype(this, MOVETYPE_BOUNCE);
                                settouch(this, func_null);
                                break;
                        case PROJECTILE_PORTO_BLUE:
                                this.colormod = '1 1 2';
                                this.alphamod = 0.5;
-                               this.move_movetype = MOVETYPE_BOUNCE;
+                               set_movetype(this, MOVETYPE_BOUNCE);
                                settouch(this, func_null);
                                break;
                        case PROJECTILE_HAGAR_BOUNCING:
-                               this.move_movetype = MOVETYPE_BOUNCE;
+                               set_movetype(this, MOVETYPE_BOUNCE);
                                settouch(this, func_null);
                                break;
                        case PROJECTILE_CRYLINK_BOUNCING:
-                               this.move_movetype = MOVETYPE_BOUNCE;
+                               set_movetype(this, MOVETYPE_BOUNCE);
                                settouch(this, func_null);
                                break;
                        case PROJECTILE_FIREBALL:
@@ -400,7 +400,7 @@ NET_HANDLE(ENT_CLIENT_PROJECTILE, bool isnew)
                                break;
                        case PROJECTILE_FIREMINE:
                                loopsound(this, CH_SHOTS_SINGLE, SND(FIREBALL_FLY), VOL_BASE, ATTEN_NORM);
-                               this.move_movetype = MOVETYPE_BOUNCE;
+                               set_movetype(this, MOVETYPE_BOUNCE);
                                settouch(this, func_null);
                                this.mins = '-4 -4 -4';
                                this.maxs = '4 4 4';
@@ -460,16 +460,16 @@ NET_HANDLE(ENT_CLIENT_PROJECTILE, bool isnew)
        if (this.gravity)
        {
                if (this.move_movetype == MOVETYPE_FLY)
-                       this.move_movetype = MOVETYPE_TOSS;
+                       set_movetype(this, MOVETYPE_TOSS);
                if (this.move_movetype == MOVETYPE_BOUNCEMISSILE)
-                       this.move_movetype = MOVETYPE_BOUNCE;
+                       set_movetype(this, MOVETYPE_BOUNCE);
        }
        else
        {
                if (this.move_movetype == MOVETYPE_TOSS)
-                       this.move_movetype = MOVETYPE_FLY;
+                       set_movetype(this, MOVETYPE_FLY);
                if (this.move_movetype == MOVETYPE_BOUNCE)
-                       this.move_movetype = MOVETYPE_BOUNCEMISSILE;
+                       set_movetype(this, MOVETYPE_BOUNCEMISSILE);
        }
 
        if (!(this.count & 0x80))
index acf6735f37924df3ed97fb5602150d56ffa51831..84d59720d467c199bc2593aee5ce540ec4ad0903 100644 (file)
@@ -1,5 +1,4 @@
-#ifndef ANIM_H
-#define ANIM_H
+#pragma once
 
 // begin engine fields
 
@@ -46,5 +45,3 @@ void anim_set(entity e, vector anim, bool looping, bool override, bool restart);
 #define setanim(...) anim_set(__VA_ARGS__)
 void anim_update(entity e);
 #define updateanim(...) anim_update(__VA_ARGS__)
-
-#endif
index 39ca54ff2f7783514755385f4e3af49b557d54c9..16feb948c35d5c2264b9bdc21329c531c47ae2d9 100644 (file)
@@ -1,5 +1,4 @@
-#ifndef ANIMDECIDE_H
-#define ANIMDECIDE_H
+#pragma once
 
 // must be called at least once to initialize, or when modelindex is changed
 void animdecide_load_if_needed(entity e);
@@ -9,7 +8,7 @@ void animdecide_setimplicitstate(entity e, float onground);
 void animdecide_setframes(entity e, bool support_blending, .int fld_frame, .int fld_frame1time, .int fld_frame2, .int fld_frame2time);
 
 CLASS(Animation, Object)
-       ATTRIB(Animation, m_framenames, string, string_null)
+       ATTRIB(Animation, m_framenames, string);
        STATIC_METHOD(Animation, getframe, int(Animation this, int mdlidx))
        {
                FOREACH_WORD(this.m_framenames, true, {
@@ -17,7 +16,7 @@ CLASS(Animation, Object)
                        if (f != -1) return f;
                });
 #ifdef CSQC
-               LOG_DEBUGF("Missing animation for %s: %s\n", modelnameforindex(mdlidx), this.registered_id);
+               LOG_DEBUGF("Missing animation for %s: %s", modelnameforindex(mdlidx), this.registered_id);
 #endif
                return -1;
        }
@@ -145,4 +144,3 @@ const int ANIMACTION_PAIN2 = 3; // pain
 const int ANIMACTION_SHOOT = 4; // shoot
 const int ANIMACTION_TAUNT = 5; // taunt
 const int ANIMACTION_MELEE = 6; // melee
-#endif
index 3f494a4639b723a310a26682d7d743e05971eaa6..3bdc8725c2803b5c9c27f6f0f30c9841d6ea8294 100644 (file)
@@ -1,5 +1,4 @@
-#ifndef CAMPAIGN_COMMON_H
-#define CAMPAIGN_COMMON_H
+#pragma once
 
 #ifndef CAMPAIGN_MAX_ENTRIES
 #define CAMPAIGN_MAX_ENTRIES 64
@@ -31,4 +30,3 @@ void CampaignFile_Unload();
 // Sets up the campaign for the n-th array item (meaning: campaign_offset+nth
 // level) using localcmd()
 void CampaignSetup(float n);
-#endif
index 129090d3ab442b0bfeaf468434a778fbe4f7147a..15285b92ecac7e33144040d0ffbbb26b58ba992e 100644 (file)
@@ -1,5 +1,4 @@
-#ifndef COMMON_COMMANDS_ALL_H
-#define COMMON_COMMANDS_ALL_H
+#pragma once
 
 #include "command.qh"
 REGISTRY(GENERIC_COMMANDS, BITS(7))
@@ -22,5 +21,3 @@ STATIC_INIT(GENERIC_COMMANDS_aliases) {
 #include "generic.qh"
 #include "markup.qh"
 #include "rpn.qh"
-
-#endif
index 72eaa18dabb3189c7185ced9e66eeb686ddab832..349d492da82b4169113ecde8989e764f06690f22 100644 (file)
@@ -1,16 +1,13 @@
-#ifndef COMMAND_H
-#define COMMAND_H
+#pragma once
 
 const int CMD_REQUEST_COMMAND = 1;
 const int CMD_REQUEST_USAGE = 2;
 
 CLASS(Command, Object)
-       ATTRIB(Command, m_name, string, string_null);
-       ATTRIB(Command, m_description, string, string_null);
+       ATTRIB(Command, m_name, string);
+       ATTRIB(Command, m_description, string);
        METHOD(Command, m_invokecmd, void(Command this, int request, entity caller, int arguments, string command))
        {
         TC(Command, this);
        }
 ENDCLASS(Command)
-
-#endif
index 90d6cefe7bb4d0ac7819f9eecdb5edd859ab966b..8f3449b3e16cfaef91bcc8b0b0bd47171deb8523 100644 (file)
@@ -36,7 +36,7 @@ void Curl_URI_Get_Callback(int id, float status, string data)
        string do_cvar = curl_uri_get_cvar[i];
        if(status != 0)
        {
-               LOG_TRACEF("error: status is %d\n", status);
+               LOG_TRACEF("error: status is %d", status);
                if(do_cvar)
                        strunzone(do_cvar);
                return;
@@ -426,9 +426,9 @@ void GenericCommand_settemp(float request, float argc)
                        {
                                float f = cvar_settemp(argv(1), argv(2));
                                if(f == 1)
-                                       LOG_TRACE("Creating new settemp tracker for ", argv(1), " and setting it to \"", argv(2), "\" temporarily.\n");
+                                       LOG_TRACE("Creating new settemp tracker for ", argv(1), " and setting it to \"", argv(2), "\" temporarily.");
                                else if(f == -1)
-                                       LOG_TRACE("Already had a tracker for ", argv(1), ", updating it to \"", argv(2), "\".\n");
+                                       LOG_TRACE("Already had a tracker for ", argv(1), ", updating it to \"", argv(2), "\".");
                                // else cvar_settemp itself errors out
 
                                return;
@@ -456,9 +456,9 @@ void GenericCommand_settemp_restore(float request, float argc)
                        float i = cvar_settemp_restore();
 
                        if(i)
-                               LOG_TRACE("Restored ", ftos(i), " temporary cvar settings to their original values.\n");
+                               LOG_TRACE("Restored ", ftos(i), " temporary cvar settings to their original values.");
                        else
-                               LOG_TRACE("Nothing to restore.\n");
+                               LOG_TRACE("Nothing to restore.");
 
                        return;
                }
index f8139aaf47e4a894bb803645628683b1168d5c96..b39c79901457de6a77b18d42ed93ac5113d71d61 100644 (file)
@@ -1,5 +1,4 @@
-#ifndef COMMAND_GENERIC_H
-#define COMMAND_GENERIC_H
+#pragma once
 
 #include <common/constants.qh>
 
@@ -39,4 +38,3 @@ void Curl_URI_Get_Callback(int id, float status, string data);
 int curl_uri_get_pos;
 float curl_uri_get_exec[URI_GET_CURL_END - URI_GET_CURL + 1];
 string curl_uri_get_cvar[URI_GET_CURL_END - URI_GET_CURL + 1];
-#endif
index 9f0883bd61ba0ea6696dc9a9e443f1f1e733addb..583c61e5517d89d046869c1d3ca3050714beeff0 100644 (file)
@@ -53,7 +53,6 @@ void GenericCommand_markup_init()
        markup_from[i] = "&.."; markup_to[i] = "\x9e"; ++i;
        markup_from[i] = "&.)"; markup_to[i] = "\x9f"; ++i;
        markup_from[i] = "&<|"; markup_to[i] = "\xff"; ++i;
-       unused_float = i;
 }
 
 string GenericCommand_markup(string s2)
index bccc78d0bcd3537d43c4aaa1c91410d47fad7a26..7a1b3876af07e726b3d120678562214f399e2f3e 100644 (file)
@@ -1,5 +1,4 @@
-#ifndef COMMAND_MARKUP_H
-#define COMMAND_MARKUP_H
+#pragma once
 
 // ==========================================================
 //  Declarations for markup command code, reworked by Samual
@@ -12,4 +11,3 @@ string markup_from[NUM_MARKUPS];
 string markup_to[NUM_MARKUPS];
 
 string GenericCommand_markup(string s2);
-#endif
index 3c5a8019b2a0cfee52c3ab8e9c500edde24563fa..ba028e248431806131679777bf116d8430d4f07a 100644 (file)
@@ -1,5 +1,4 @@
-#ifndef COMMAND_RPN_H
-#define COMMAND_RPN_H
+#pragma once
 
 // =========================================================
 //  Declarations for RPN command code, written by divVerent
@@ -13,5 +12,3 @@ int rpn_sp;
 string rpn_stack[MAX_RPN_STACK];
 
 void GenericCommand_rpn(float request, float argc, string command);
-
-#endif
index 28db23dc11a13fd08b5365a30ca670e2b8638701..6c775560394259816e14622b1584cb2843b34d59 100644 (file)
@@ -1,5 +1,4 @@
-#ifndef CONSTANTS_H
-#define CONSTANTS_H
+#pragma once
 
 REGISTER_NET_TEMP(TE_CSQC_PICTURE)
 REGISTER_NET_TEMP(TE_CSQC_RACE)
@@ -123,19 +122,115 @@ const int SFL_SORT_PRIO_SECONDARY = 4;
 const int SFL_SORT_PRIO_PRIMARY = 8;
 const int SFL_SORT_PRIO_MASK = 12;
 
-/**
+/*
  * Score indices
  */
-#define MAX_SCORE 12
+
+#ifndef MENUQC
+
+#define IS_INCREASING(x) ( (x) & SFL_LOWER_IS_BETTER )
+#define IS_DECREASING(x) ( !((x) & SFL_LOWER_IS_BETTER) )
+
+
+#define MAX_SCORE 64
+
+#define REGISTER_SP(id) REGISTER(Scores, SP, id, m_id, new_pure(PlayerScoreField))
+REGISTRY(Scores, MAX_SCORE);
+#define Scores_from(i) _Scores_from(i, NULL)
+REGISTER_REGISTRY(Scores)
+REGISTRY_SORT(Scores);
+REGISTRY_CHECK(Scores);
+STATIC_INIT(Scores_renumber) { FOREACH(Scores, true, it.m_id = i); }
+
+USING(PlayerScoreField, entity);
+.int _scores[MAX_SCORE];
+.string m_name;
+.int m_flags;
+
+#define scores(this) _scores[(this).m_id]
+#define scores_label(this) ((this).m_name)
+#define scores_flags(this) ((this).m_flags)
+
+REGISTER_SP(END);
+
+REGISTER_SP(PING);
+REGISTER_SP(NAME);
+REGISTER_SP(KDRATIO);
+REGISTER_SP(CLRATIO);
+REGISTER_SP(PL);
+REGISTER_SP(SUM);
+
+REGISTER_SP(SEPARATOR);
+
+REGISTER_SP(SCORE);
+
+REGISTER_SP(DMG);
+REGISTER_SP(DMGTAKEN);
+
+REGISTER_SP(KILLS);
+REGISTER_SP(DEATHS);
+REGISTER_SP(SUICIDES);
+REGISTER_SP(FRAGS);
+
+REGISTER_SP(ELO);
+
+// TODO: move to common mutators
+
+REGISTER_SP(RACE_TIME);
+REGISTER_SP(RACE_LAPS);
+REGISTER_SP(RACE_FASTEST);
+
+REGISTER_SP(CTS_TIME);
+REGISTER_SP(CTS_LAPS);
+REGISTER_SP(CTS_FASTEST);
+
+REGISTER_SP(ASSAULT_OBJECTIVES);
+
+REGISTER_SP(CTF_PICKUPS);
+REGISTER_SP(CTF_FCKILLS);
+REGISTER_SP(CTF_RETURNS);
+REGISTER_SP(CTF_CAPS);
+REGISTER_SP(CTF_CAPTIME);
+REGISTER_SP(CTF_DROPS);
+
+REGISTER_SP(DOM_TAKES);
+REGISTER_SP(DOM_TICKS);
+
+REGISTER_SP(FREEZETAG_REVIVALS);
+
+REGISTER_SP(KEEPAWAY_PICKUPS);
+REGISTER_SP(KEEPAWAY_BCTIME);
+REGISTER_SP(KEEPAWAY_CARRIERKILLS);
+
+REGISTER_SP(KH_PICKUPS);
+REGISTER_SP(KH_CAPS);
+REGISTER_SP(KH_KCKILLS);
+REGISTER_SP(KH_PUSHES);
+REGISTER_SP(KH_DESTROYS);
+REGISTER_SP(KH_LOSSES);
+
+REGISTER_SP(LMS_RANK);
+REGISTER_SP(LMS_LIVES);
+
+REGISTER_SP(NEXBALL_GOALS);
+REGISTER_SP(NEXBALL_FAULTS);
+
+REGISTER_SP(ONS_TAKES);
+REGISTER_SP(ONS_CAPS);
+
 #define MAX_TEAMSCORE 2
+USING(ScoreTeam, string);
+.int _teamscores[MAX_TEAMSCORE];
+#define teamscores(i) _teamscores[i]
+string _teamscores_label[MAX_TEAMSCORE];
+#define teamscores_label(i) _teamscores_label[i]
+int _teamscores_flags[MAX_TEAMSCORE];
+#define teamscores_flags(i) _teamscores_flags[i]
+
+#endif
 
 const int ST_SCORE = 0;
-const int SP_KILLS = 0;
-const int SP_DEATHS = 1;
-const int SP_SUICIDES = 2;
-const int SP_SCORE = 3;
-const int SP_DMG = 10;
-const int SP_DMGTAKEN = 11;
+
 // game mode specific indices are not in common/, but in server/scores_rules.qc!
 
 // WEAPONTODO: move this into separate/new projectile handling code // this sets sounds and other properties of the projectiles in csqc
@@ -230,4 +325,3 @@ const int SPAWN_PRIO_GOOD_DISTANCE = 10;
 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 39cec43225ea9ff430422133ea0d7ae91df4a844..9c8dd42917a9e85de2a97c863230273cacd26c2c 100644 (file)
@@ -1,5 +1,4 @@
-#ifndef CSQCMODEL_SETTINGS_H
-#define CSQCMODEL_SETTINGS_H
+#pragma once
 
 // define this if svqc code wants to use .frame2 and .lerpfrac
 //#define CSQCMODEL_HAVE_TWO_FRAMES
@@ -94,4 +93,3 @@
 #endif
 
 #define CSQCMODEL_EF_RESPAWNGHOST EF_SELECTABLE
-#endif
index 903087947416dfe6978a24900a72020fa3af3354..0466c230ab3b709f40343ce3d2bba3c2c3442894 100644 (file)
@@ -1,5 +1,4 @@
-#ifndef DEATHTYPES_ALL_H
-#define DEATHTYPES_ALL_H
+#pragma once
 
 #include <common/notifications/all.qh>
 
@@ -47,5 +46,3 @@ const int DT_FIRST = BIT(13);
 string Deathtype_Name(int deathtype);
 
 #include "all.inc"
-
-#endif
index b6f378d47221e8892c85503685ab7b539c0f61a6..d229b05100a751fb50a8795dbc11997d52a953c9 100644 (file)
@@ -76,7 +76,7 @@ void Send_Effect(entity eff, vector eff_loc, vector eff_vel, int eff_cnt)
        net_eff.eent_eff_trail = eff.eent_eff_trail;
 
        FOREACH_CLIENT(IS_REAL_CLIENT(it), Net_Write_Effect(net_eff, it, 0));
-       remove(net_eff);
+       delete(net_eff);
 }
 
 void Send_Effect_(string eff_name, vector eff_loc, vector eff_vel, int eff_cnt)
index e0e9a3ca869d16b85734356e49802dba3fc706b9..7581618375bd5bfc0b949b0b023435db4bebdd8e 100644 (file)
@@ -1,5 +1,4 @@
-#ifndef EFFECTS_ALL_H
-#define EFFECTS_ALL_H
+#pragma once
 
 #include "effect.qh"
 
@@ -17,5 +16,3 @@ REGISTRY_CHECK(Effects)
 
 EFFECT(0, Null, string_null)
 #include "all.inc"
-
-#endif
index e58d42ca7b4ba55f9ed82af6b623bd1d21a6b883..7802f0a91be3f3ad464e41b69ad62d1a2b09c0da 100644 (file)
@@ -1,5 +1,4 @@
-#ifndef EFFECT_H
-#define EFFECT_H
+#pragma once
 
 #define particleeffectnum(e) \
        _particleeffectnum(e.eent_eff_name)
@@ -32,5 +31,3 @@ entity Create_Effect_Entity(string eff_name, bool eff_trail)
        this.eent_eff_trail = eff_trail;
        return this;
 }
-
-#endif
index 07d76c480a07627cddc8b284c1e614c89e804e16..cf6d5fca9395a29b8985a1e059522bd1a5f8206e 100644 (file)
     /**/
 
 CLASS(EffectInfo, Object)
-    ATTRIB(EffectInfo, effectinfo_name, string, string_null)
+    ATTRIB(EffectInfo, effectinfo_name, string);
     CONSTRUCTOR(EffectInfo, string s) {
         CONSTRUCT(EffectInfo);
         this.effectinfo_name = s;
@@ -193,7 +193,7 @@ CLASS(EffectInfo, Object)
     MY(velocityoffset, vector, '0 0 0') \
     /**/
 
-    #define MY(f, type, val) ATTRIB(EffectInfo, effectinfo_##f, type, val)
+    #define MY(f, type, val) ATTRIB(EffectInfo, effectinfo_##f, type, val);
     FIELDS(MY)
     #undef MY
 
@@ -227,8 +227,8 @@ CLASS(EffectInfo, Object)
 ENDCLASS(EffectInfo)
 
 CLASS(EffectInfoGroup, Object)
-    ATTRIBARRAY(EffectInfoGroup, children, EffectInfo, 16)
-    ATTRIB(EffectInfoGroup, children_count, int, 0)
+    ATTRIBARRAY(EffectInfoGroup, children, EffectInfo, 16);
+    ATTRIB(EffectInfoGroup, children_count, int, 0);
 ENDCLASS(EffectInfoGroup)
 
 void effectinfo_read()
@@ -253,7 +253,7 @@ void effectinfo_read()
             #undef p
             #undef MY
             default:
-                LOG_WARNINGF("Unknown property '%s'\n", k);
+                LOG_WARNF("Unknown property '%s'", k);
                 break;
         }
     }
@@ -306,7 +306,7 @@ GENERIC_COMMAND(dumpeffectinfo, "Dump all effectinfo to effectinfo_dump.txt")
                                LOG_INFOF("Reload with ^2cl_particles_reloadeffects data/%s^7.\n", filename);
                 fclose(fh);
             } else {
-                LOG_WARNINGF("Could not open file '%s'!\n", filename);
+                LOG_WARNF("Could not open file '%s'!", filename);
             }
             return;
         }
index 5b9b364313cea105d933bd2516bb6abdaaaf9b9a..54cf6b6ff007b674b5b0225f74b054e61863fe43 100644 (file)
@@ -1,4 +1,3 @@
-#ifndef EFFECTS_QC
-#define EFFECTS_QC
+#pragma once
+
 #include "all.inc"
-#endif
index a4ade38366e709e8a14e90d086fb60258c4ceeca..f92df7cd0edba6770769114dba75f8a4d4970fd9 100644 (file)
@@ -1,5 +1,5 @@
 #ifdef SVQC
-void SpawnCasing(vector vel, float randomvel, vector ang, vector avel, float randomavel, int casingtype, entity casingowner);
+void SpawnCasing(vector vel, float randomvel, vector ang, vector avel, float randomavel, int casingtype, entity casingowner, .entity weaponentity);
 #endif
 
 #ifdef IMPLEMENTATION
@@ -14,9 +14,8 @@ void SpawnCasing(vector vel, float randomvel, vector ang, vector avel, float ran
 REGISTER_NET_TEMP(casings)
 
 #ifdef SVQC
-void SpawnCasing(vector vel, float randomvel, vector ang, vector avel, float randomavel, int casingtype, entity casingowner)
+void SpawnCasing(vector vel, float randomvel, vector ang, vector avel, float randomavel, int casingtype, entity casingowner, .entity weaponentity)
 {
-    .entity weaponentity = weaponentities[0]; // TODO: parameter
     entity wep = casingowner.(weaponentity);
     vector org = casingowner.origin + casingowner.view_ofs + wep.spawnorigin.x * v_forward - wep.spawnorigin.y * v_right + wep.spawnorigin.z * v_up;
 
@@ -44,7 +43,7 @@ class(Casing) .float cnt;
 
 void Casing_Delete(entity this)
 {
-    remove(this);
+    delete(this);
 }
 
 void Casing_Draw(entity this)
@@ -154,7 +153,7 @@ NET_HANDLE(casings, bool isNew)
     if (isNew) IL_PUSH(g_drawables, casing);
     casing.velocity = casing.velocity + 2 * prandomvec();
     casing.avelocity = '0 250 0' + 100 * prandomvec();
-    casing.move_movetype = MOVETYPE_BOUNCE;
+    set_movetype(casing, MOVETYPE_BOUNCE);
     settouch(casing, Casing_Touch);
     casing.move_time = time;
     casing.event_damage = Casing_Damage;
index b53b605058a1fc340322ca225dcd33b500a044bc..d17502e81ba99fcf0c11eb49c2182c0a0c4fce1d 100644 (file)
@@ -81,7 +81,7 @@ void DamageEffect_Think(entity this)
        {
                // time is up or the player got gibbed / disconnected
                this.owner.total_damages = max(0, this.owner.total_damages - 1);
-               remove(this);
+               delete(this);
                return;
        }
        if(this.state && !this.owner.csqcmodel_isdead)
@@ -89,7 +89,7 @@ void DamageEffect_Think(entity this)
                // if the player was dead but is now alive, it means he respawned
                // if so, clear his damage effects, or damages from his dead body will be copied back
                this.owner.total_damages = max(0, this.owner.total_damages - 1);
-               remove(this);
+               delete(this);
                return;
        }
        this.state = this.owner.csqcmodel_isdead;
index 78f1a27cc6c0a0eba824fa7899e1a099d117b3e3..d1e3d9880da4244206e9ea38ef037c38a828653b 100644 (file)
@@ -46,7 +46,7 @@ void Violence_GibSplash_At(vector org, vector dir, float type, float amount, ent
        e.oldorigin_x = compressShortVector(e.velocity);
 
        FOREACH_CLIENT(IS_REAL_CLIENT(it), Violence_GibSplash_SendEntity(e, it, 0));
-       remove(e);
+       delete(e);
 }
 
 void Violence_GibSplash(entity source, float type, float amount, entity attacker)
@@ -70,7 +70,7 @@ void Violence_GibSplash(entity source, float type, float amount, entity attacker
 
 void Gib_Delete(entity this)
 {
-       remove(this);
+       delete(this);
 }
 
 string species_prefix(int specnum);
@@ -170,7 +170,7 @@ void TossGib (string mdlname, vector safeorg, vector org, vector vconst, vector
 
        // TODO remove some gibs according to cl_nogibs
        gib = RubbleNew("gib");
-       gib.move_movetype = MOVETYPE_BOUNCE;
+       set_movetype(gib, MOVETYPE_BOUNCE);
        gib.gravity = 1;
        gib.solid = SOLID_CORPSE;
        gib.cnt = specnum;
@@ -311,7 +311,7 @@ NET_HANDLE(net_gibsplash, bool isNew)
                        // no gibs in gentle mode, sorry
                        break;
        }
-       remove(this);
+       delete(this);
 }
 #endif
 
index 8c1ed1ca8305759ef85ee3a7cb691975c51ca7f7..573b52f22cc83986e0755f87b76ff44dabdda777 100644 (file)
                        else
                        {
                                // Can this happen?
-                               LOG_WARNINGF("Missing entcs data for player %d\n", who);
+                               LOG_WARNF("Missing entcs data for player %d", who);
                                sound8(e, o, chan, sample, vol, atten, 0, 0);
                        }
                        return true;
                        else
                        {
                                // Can this happen?
-                               LOG_WARNINGF("Missing entcs data for player %d\n", who);
+                               LOG_WARNF("Missing entcs data for player %d", who);
                                sound8(e, o, chan, sample, vol, atten, 0, 0);
                        }
                        return true;
                int fh = fopen(f, FILE_READ);
                if (fh < 0)
                {
-                       LOG_WARNINGF("Player sound file not found: %s\n", f);
+                       LOG_WARNF("Player sound file not found: %s", f);
                        return;
                }
                for (string s; (s = fgets(fh)); )
                        int n = tokenize_console(s);
                        if (n != 3)
                        {
-                               if (n != 0) LOG_WARNINGF("Invalid sound info line: %s\n", s);
+                               if (n != 0) LOG_WARNF("Invalid sound info line: %s", s);
                                continue;
                        }
                        string file = argv(1);
                        int fh = fopen(f, FILE_READ);
                        if (fh < 0)
                        {
-                               if (strict) LOG_WARNINGF("Player sound file not found: %s\n", f);
+                               if (strict) LOG_WARNF("Player sound file not found: %s", f);
                                return false;
                        }
                        for (string s; (s = fgets(fh)); )
                                int n = tokenize_console(s);
                                if (n != 3)
                                {
-                                       if (n != 0) LOG_WARNINGF("Invalid sound info line: %s\n", s);
+                                       if (n != 0) LOG_WARNF("Invalid sound info line: %s", s);
                                        continue;
                                }
                                string key = argv(0);
                                if (GetPlayerSoundSampleField_notFound) field = GetVoiceMessageSampleField(key);
                                if (GetPlayerSoundSampleField_notFound)
                                {
-                                       LOG_TRACEF("Invalid sound info field: %s\n", key);
+                                       LOG_TRACEF("Invalid sound info field: %s", key);
                                        continue;
                                }
                                string file = argv(1);
index 640d330f1c0cc139d46266e77b05115507c7cc9d..1df0b1a42b1145eeeea104092fec1a98d5b5b25d 100644 (file)
@@ -1,5 +1,4 @@
-#ifndef GLOBALSOUND_H
-#define GLOBALSOUND_H
+#pragma once
 
 #ifdef SVQC
        /** Use new sound handling. TODO: use when sounds play correctly on clients */
@@ -148,5 +147,3 @@ STATIC_INIT(allvoicesamples)
     FOREACH(PlayerSounds, it.instanceOfVoiceMessage, allvoicesamples = strcat(allvoicesamples, " ", it.m_playersoundstr));
     allvoicesamples = strzone(substring(allvoicesamples, 1, -1));
 }
-
-#endif
index 28b8bb496bc6438f81367081ec6f28e54be9cc9b..8fbef5b587e9c56a7ed1f7cbc20d445cd32dab4f 100644 (file)
@@ -103,7 +103,7 @@ void ModelEffect_Draw(entity this)
        this.alpha = this.cnt * bound(0, 1 - (time - this.lifetime) / this.fadetime, 1);
        if(this.alpha < ALPHA_MIN_VISIBLE)
        {
-               remove(this);
+               delete(this);
                return;
        }
        this.drawmask = MASK_NORMAL;
@@ -158,7 +158,7 @@ NET_HANDLE(ENT_CLIENT_MODELEFFECT, bool isnew)
        e.draw = ModelEffect_Draw;
        if (isnew) IL_PUSH(g_drawables, e);
 
-       if (!isnew) remove(e); // yes, this IS stupid, but I don't need to duplicate all the read* stuff then
+       if (!isnew) delete(e); // yes, this IS stupid, but I don't need to duplicate all the read* stuff then
        return true;
 }
 #endif
index 1665e4ccef38e8c37db1d984dacea596214ff6b2..83a6941213d627dbeca64e0174cc9e662696310e 100644 (file)
@@ -1,5 +1,4 @@
-#ifndef RUBBLE_H
-#define RUBBLE_H
+#pragma once
 
 #ifdef CSQC
 
@@ -46,5 +45,3 @@ entity RubbleNew(string cname)
 }
 
 #endif
-
-#endif
index e69998563d281f1f49f344bd361e7b6e146c2c95..2a7b3f80c485ef413e246028834d20ad38d8156b 100644 (file)
        void entcs_detach(entity player)
        {
                if (!player.entcs) return;
-               remove(player.entcs);
+               delete(player.entcs);
                player.entcs = NULL;
        }
 
                int n = this.sv_entnum;
                entity e = entcs_receiver(n);
                entcs_receiver(n, NULL);
-               if (e != this) remove(e);
+               if (e != this) delete(e);
        }
 
        void entcs_think(entity this)
index 1c72b351f7ff7e4e65b48fd9e5bf599f86c11a40..fdaaab2d57c0f37be4345a824a3892a3fdd90e51 100644 (file)
@@ -1,5 +1,4 @@
-#ifndef ENT_CS_H
-#define ENT_CS_H
+#pragma once
 
 REGISTER_NET_LINKED(ENT_CLIENT_ENTCS)
 REGISTER_NET_TEMP(CLIENT_ENTCS)
@@ -141,5 +140,3 @@ REGISTER_NET_TEMP(CLIENT_ENTCS)
        }
 
 #endif
-
-#endif
index 35fe31c2bd6ea49295a0697d68cf0e7d55c85cc0..0f0ecb471943ff4623627aa9cbcd9206676bf9d5 100644 (file)
@@ -70,8 +70,6 @@ float OtherTeam(float t)  //works only if there are two teams on the map!
 }
 
 const float ST_NEXBALL_GOALS = 1;
-const float SP_NEXBALL_GOALS = 4;
-const float SP_NEXBALL_FAULTS = 5;
 void nb_ScoreRules(int teams)
 {
        ScoreRules_basics(teams, 0, 0, true);
@@ -453,7 +451,7 @@ spawnfunc(nexball_team)
 {
        if(!g_nexball)
        {
-               remove(this);
+               delete(this);
                return;
        }
        this.team = this.cnt + 1;
@@ -461,7 +459,7 @@ spawnfunc(nexball_team)
 
 void nb_spawnteam(string teamname, float teamcolor)
 {
-       LOG_TRACE("^2spawned team ", teamname, "\n");
+       LOG_TRACE("^2spawned team ", teamname);
        entity e = new(nexball_team);
        e.netname = teamname;
        e.cnt = teamcolor;
@@ -527,7 +525,7 @@ void nb_delayedinit(entity this)
 
 void SpawnBall(entity this)
 {
-       if(!g_nexball) { remove(this); return; }
+       if(!g_nexball) { delete(this); return; }
 
 //     balls += 4; // using the remaining bits to count balls will leave more than the max edict count, so it's fine
 
@@ -624,7 +622,7 @@ bool nb_Goal_Customize(entity this, entity client)
 
 void SpawnGoal(entity this)
 {
-       if(!g_nexball) { remove(this); return; }
+       if(!g_nexball) { delete(this); return; }
 
        EXACTTRIGGER_INIT;
 
@@ -761,17 +759,17 @@ void W_Nexball_Touch(entity this, entity toucher)
                                GiveBall(attacker, toucher.ballcarried);
                        }
                }
-       remove(this);
+       delete(this);
 }
 
-void W_Nexball_Attack(entity actor, float t)
+void W_Nexball_Attack(entity actor, .entity weaponentity, float t)
 {
        entity ball;
        float mul, mi, ma;
        if(!(ball = actor.ballcarried))
                return;
 
-       W_SetupShot(actor, false, 4, SND_NB_SHOOT1, CH_WEAPON_A, 0);
+       W_SetupShot(actor, weaponentity, false, 4, SND_NB_SHOOT1, CH_WEAPON_A, 0);
        tracebox(w_shotorg, BALL_MINS, BALL_MAXS, w_shotorg, MOVE_WORLDONLY, NULL);
        if(trace_startsolid)
        {
@@ -802,12 +800,12 @@ void W_Nexball_Attack(entity actor, float t)
 
 vector trigger_push_calculatevelocity(vector org, entity tgt, float ht);
 
-void W_Nexball_Attack2(entity actor)
+void W_Nexball_Attack2(entity actor, .entity weaponentity)
 {
        if(actor.ballcarried.enemy)
        {
                entity _ball = actor.ballcarried;
-               W_SetupShot(actor, false, 4, SND_NB_SHOOT1, CH_WEAPON_A, 0);
+               W_SetupShot(actor, weaponentity, false, 4, SND_NB_SHOOT1, CH_WEAPON_A, 0);
                DropBall(_ball, w_shotorg, trigger_push_calculatevelocity(_ball.origin, _ball.enemy, 32));
                setthink(_ball, W_Nexball_Think);
                _ball.nextthink = time;
@@ -817,7 +815,7 @@ void W_Nexball_Attack2(entity actor)
        if(!autocvar_g_nexball_tackling)
                return;
 
-       W_SetupShot(actor, false, 2, SND_NB_SHOOT2, CH_WEAPON_A, 0);
+       W_SetupShot(actor, weaponentity, false, 2, SND_NB_SHOOT2, CH_WEAPON_A, 0);
        entity missile = new(ballstealer);
 
        missile.owner = actor;
@@ -837,6 +835,7 @@ void W_Nexball_Attack2(entity actor)
 
        missile.effects = EF_BRIGHTFIELD | EF_LOWPRECISION;
        missile.flags = FL_PROJECTILE;
+       IL_PUSH(g_projectiles, missile);
 
        CSQCProjectile(missile, true, PROJECTILE_ELECTRO, true);
 }
@@ -882,19 +881,19 @@ METHOD(BallStealer, wr_think, void(BallStealer thiswep, entity actor, .entity we
             }
             else
             {
-                W_Nexball_Attack(actor, -1);
+                W_Nexball_Attack(actor, weaponentity, -1);
                 weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, autocvar_g_balance_nexball_primary_animtime, w_ready);
             }
     if(fire & 2)
         if(weapon_prepareattack(thiswep, actor, weaponentity, true, autocvar_g_balance_nexball_secondary_refire))
         {
-            W_Nexball_Attack2(actor);
+            W_Nexball_Attack2(actor, weaponentity);
             weapon_thinkf(actor, weaponentity, WFRAME_FIRE2, autocvar_g_balance_nexball_secondary_animtime, w_ready);
         }
 
     if(!(fire & 1) && actor.metertime && actor.ballcarried)
     {
-        W_Nexball_Attack(actor, time - actor.metertime);
+        W_Nexball_Attack(actor, weaponentity, time - actor.metertime);
         // DropBall or stealing will set metertime back to 0
         weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, autocvar_g_balance_nexball_primary_animtime, w_ready);
     }
index 013479242bb1b0a5a69857f635ed8b324b09f83f..fb8cb71719a2e4acea5a10718a737eb4f54d50bb 100644 (file)
@@ -117,15 +117,15 @@ void cpicon_construct(entity this)
                setmodel(this.icon_realmodel, MDL_Null);
                setorigin(this.icon_realmodel, this.origin);
                setsize(this.icon_realmodel, CPICON_MIN, CPICON_MAX);
-               this.icon_realmodel.move_movetype = MOVETYPE_NOCLIP;
+               set_movetype(this.icon_realmodel, MOVETYPE_NOCLIP);
                this.icon_realmodel.solid = SOLID_NOT;
        }
 
        if(this.iscaptured) { this.icon_realmodel.solid = SOLID_BBOX; }
 
-       this.move_movetype      = MOVETYPE_NOCLIP;
+       set_movetype(this, MOVETYPE_NOCLIP);
        this.solid                      = SOLID_NOT;
-       this.move_movetype              = MOVETYPE_NOCLIP;
+       set_movetype(this, MOVETYPE_NOCLIP);
        this.move_time          = time;
        this.drawmask           = MASK_NORMAL;
        this.alpha                      = 1;
index 0135f467ed0eb5fb84e9180048ce2df87bb67077..2b9470f7750ab2b9fecac82a5abe51590811e6bb 100644 (file)
@@ -14,7 +14,7 @@ void ons_generator_ray_draw(entity this)
 
        if(this.count > 10)
        {
-               remove(this);
+               delete(this);
                return;
        }
 
@@ -33,7 +33,7 @@ void ons_generator_ray_spawn(vector org)
        setmodel(e, MDL_ONS_RAY);
        setorigin(e, org);
        e.angles = randomvec() * 360;
-       e.move_movetype = MOVETYPE_NONE;
+       set_movetype(e, MOVETYPE_NONE);
        e.alpha = 0;
        e.scale = random() * 5 + 8;
        e.move_time = time + 0.05;
@@ -152,9 +152,9 @@ void generator_construct(entity this)
        setmodel(this, MDL_ONS_GEN);
        setsize(this, GENERATOR_MIN, GENERATOR_MAX);
 
-       this.move_movetype      = MOVETYPE_NOCLIP;
+       set_movetype(this, MOVETYPE_NOCLIP);
        this.solid                      = SOLID_BBOX;
-       this.move_movetype              = MOVETYPE_NOCLIP;
+       set_movetype(this, MOVETYPE_NOCLIP);
        this.move_time          = time;
        this.drawmask           = MASK_NORMAL;
        this.alpha                      = 1;
index 89c5eef51dc2edb0897676f0e7de8e1a3289e7f7..713c5d7de06e3abf40c19b27f211d0759aef5a1e 100644 (file)
@@ -120,8 +120,6 @@ void havocbot_goalrating_enemyplayers(entity this, float ratingscale, vector org
 
 // score rule declarations
 const int ST_ONS_CAPS = 1;
-const int SP_ONS_CAPS = 4;
-const int SP_ONS_TAKES = 6;
 
 #endif
 #endif
@@ -238,14 +236,14 @@ void onslaught_updatelinks()
 {
        entity l;
        // first check if the game has ended
-       LOG_DEBUG("--- updatelinks ---\n");
+       LOG_DEBUG("--- updatelinks ---");
        // mark generators as being shielded and networked
        for(l = ons_worldgeneratorlist; l; l = l.ons_worldgeneratornext)
        {
                if (l.iscaptured)
-                       LOG_DEBUG(strcat(etos(l), " (generator) belongs to team ", ftos(l.team), "\n"));
+                       LOG_DEBUG(etos(l), " (generator) belongs to team ", ftos(l.team));
                else
-                       LOG_DEBUG(strcat(etos(l), " (generator) is destroyed\n"));
+                       LOG_DEBUG(etos(l), " (generator) is destroyed");
                l.islinked = l.iscaptured;
                l.isshielded = l.iscaptured;
                l.sprite.SendFlags |= 16;
@@ -257,7 +255,7 @@ void onslaught_updatelinks()
                l.isshielded = true;
                int i;
                for(i = 0; i < 17; ++i) { l.isgenneighbor[i] = false; l.iscpneighbor[i] = false; }
-               LOG_DEBUG(strcat(etos(l), " (point) belongs to team ", ftos(l.team), "\n"));
+               LOG_DEBUG(etos(l), " (point) belongs to team ", ftos(l.team));
                l.sprite.SendFlags |= 16;
        }
        // flow power outward from the generators through the network
@@ -277,13 +275,13 @@ void onslaught_updatelinks()
                                                {
                                                        stop = false;
                                                        l.goalentity.islinked = true;
-                                                       LOG_DEBUG(strcat(etos(l), " (link) is marking ", etos(l.goalentity), " (point) because its team matches ", etos(l.enemy), " (point)\n"));
+                                                       LOG_DEBUG(etos(l), " (link) is marking ", etos(l.goalentity), " (point) because its team matches ", etos(l.enemy), " (point)");
                                                }
                                                else if (!l.enemy.islinked)
                                                {
                                                        stop = false;
                                                        l.enemy.islinked = true;
-                                                       LOG_DEBUG(strcat(etos(l), " (link) is marking ", etos(l.enemy), " (point) because its team matches ", etos(l.goalentity), " (point)\n"));
+                                                       LOG_DEBUG(etos(l), " (link) is marking ", etos(l.enemy), " (point) because its team matches ", etos(l.goalentity), " (point)");
                                                }
                                        }
                }
@@ -296,7 +294,7 @@ void onslaught_updatelinks()
                {
                        if(DIFF_TEAM(l.goalentity, l.enemy))
                        {
-                               LOG_DEBUG(strcat(etos(l), " (link) is unshielding ", etos(l.enemy), " (point) because its team does not match ", etos(l.goalentity), " (point)\n"));
+                               LOG_DEBUG(etos(l), " (link) is unshielding ", etos(l.enemy), " (point) because its team does not match ", etos(l.goalentity), " (point)");
                                l.enemy.isshielded = false;
                        }
                        if(l.goalentity.classname == "onslaught_generator")
@@ -308,7 +306,7 @@ void onslaught_updatelinks()
                {
                        if(DIFF_TEAM(l.goalentity, l.enemy))
                        {
-                               LOG_DEBUG(strcat(etos(l), " (link) is unshielding ", etos(l.goalentity), " (point) because its team does not match ", etos(l.enemy), " (point)\n"));
+                               LOG_DEBUG(etos(l), " (link) is unshielding ", etos(l.goalentity), " (point) because its team does not match ", etos(l.enemy), " (point)");
                                l.goalentity.isshielded = false;
                        }
                        if(l.enemy.classname == "onslaught_generator")
@@ -322,13 +320,13 @@ void onslaught_updatelinks()
        {
                if (l.isshielded)
                {
-                       LOG_DEBUG(strcat(etos(l), " (generator) is shielded\n"));
+                       LOG_DEBUG(etos(l), " (generator) is shielded");
                        l.takedamage = DAMAGE_NO;
                        l.bot_attack = false;
                }
                else
                {
-                       LOG_DEBUG(strcat(etos(l), " (generator) is not shielded\n"));
+                       LOG_DEBUG(etos(l), " (generator) is not shielded");
                        l.takedamage = DAMAGE_AIM;
                        l.bot_attack = true;
                }
@@ -340,7 +338,7 @@ void onslaught_updatelinks()
        {
                if (l.isshielded)
                {
-                       LOG_DEBUG(strcat(etos(l), " (point) is shielded\n"));
+                       LOG_DEBUG(etos(l), " (point) is shielded");
                        if (l.goalentity)
                        {
                                l.goalentity.takedamage = DAMAGE_NO;
@@ -349,7 +347,7 @@ void onslaught_updatelinks()
                }
                else
                {
-                       LOG_DEBUG(strcat(etos(l), " (point) is not shielded\n"));
+                       LOG_DEBUG(etos(l), " (point) is not shielded");
                        if (l.goalentity)
                        {
                                l.goalentity.takedamage = DAMAGE_AIM;
@@ -419,7 +417,7 @@ void ons_DelayedLinkSetup(entity this)
        if(!this.goalentity) { objerror(this, "can not find target\n"); }
        if(!this.enemy) { objerror(this, "can not find target2\n"); }
 
-       LOG_DEBUG(strcat(etos(this.goalentity), " linked with ", etos(this.enemy), "\n"));
+       LOG_DEBUG(etos(this.goalentity), " linked with ", etos(this.enemy));
        this.SendFlags |= 3;
        setthink(this, ons_Link_CheckUpdate);
        this.nextthink = time;
@@ -551,7 +549,7 @@ void ons_ControlPoint_Icon_Damage(entity this, entity inflictor, entity attacker
                        setmodel_fixsize(this.owner, MDL_ONS_CP_PAD1);
                //setsize(this, '-32 -32 0', '32 32 8');
 
-               remove(this);
+               delete(this);
        }
 
        this.SendFlags |= CPSF_STATUS;
@@ -819,7 +817,7 @@ void ons_ControlPoint_Think(entity this)
 void ons_ControlPoint_Reset(entity this)
 {
        if(this.goalentity)
-               remove(this.goalentity);
+               delete(this.goalentity);
 
        this.goalentity = NULL;
        this.team = 0;
@@ -1307,8 +1305,8 @@ void havocbot_goalrating_ons_offenseitems(entity this, float ratingscale, vector
        if(!needweapons && !needarmor)
                return;
 
-       LOG_DEBUG(strcat(this.netname, " needs weapons ", ftos(needweapons) , "\n"));
-       LOG_DEBUG(strcat(this.netname, " needs armor ", ftos(needarmor) , "\n"));
+       LOG_DEBUG(this.netname, " needs weapons ", ftos(needweapons));
+       LOG_DEBUG(this.netname, " needs armor ", ftos(needarmor));
 
        // See what is around
        FOREACH_ENTITY_FLOAT(bot_pickup, true,
@@ -1327,7 +1325,7 @@ void havocbot_goalrating_ons_offenseitems(entity this, float ratingscale, vector
 
 void havocbot_role_ons_setrole(entity this, int role)
 {
-       LOG_DEBUG(strcat(this.netname," switched to "));
+       LOG_DEBUG(this.netname," switched to ");
        switch(role)
        {
                case HAVOCBOT_ONS_ROLE_DEFENSE:
@@ -1349,7 +1347,7 @@ void havocbot_role_ons_setrole(entity this, int role)
                        this.havocbot_role_timeout = 0;
                        break;
        }
-       LOG_DEBUG("\n");
+       LOG_DEBUG("");
 }
 
 void havocbot_goalrating_ons_controlpoints_attack(entity this, float ratingscale)
@@ -1405,7 +1403,7 @@ void havocbot_goalrating_ons_controlpoints_attack(entity this, float ratingscale
        if (!cp)
                return;
 
-       LOG_DEBUG(strcat(this.netname, " chose cp ranked ", ftos(bestvalue), "\n"));
+       LOG_DEBUG(this.netname, " chose cp ranked ", ftos(bestvalue));
 
        if(cp.goalentity)
        {
@@ -1446,12 +1444,12 @@ void havocbot_goalrating_ons_controlpoints_attack(entity this, float ratingscale
                {
                        navigation_routerating(this, cp, ratingscale, 10000);
                }
-               LOG_DEBUG(strcat(this.netname, " found an attackable controlpoint at ", vtos(cp.origin) ,"\n"));
+               LOG_DEBUG(this.netname, " found an attackable controlpoint at ", vtos(cp.origin));
        }
        else
        {
                // Should be touched
-               LOG_DEBUG(strcat(this.netname, " found a touchable controlpoint at ", vtos(cp.origin) ,"\n"));
+               LOG_DEBUG(this.netname, " found a touchable controlpoint at ", vtos(cp.origin));
                found = false;
 
                // Look for auto generated waypoint
@@ -1504,7 +1502,7 @@ bool havocbot_goalrating_ons_generator_attack(entity this, float ratingscale)
 
                if(bestwp)
                {
-                       LOG_DEBUG("waypoints found around generator\n");
+                       LOG_DEBUG("waypoints found around generator");
                        navigation_routerating(this, bestwp, ratingscale, 10000);
                        bestwp.cnt += 1;
 
@@ -1517,7 +1515,7 @@ bool havocbot_goalrating_ons_generator_attack(entity this, float ratingscale)
                }
                else
                {
-                       LOG_DEBUG("generator found without waypoints around\n");
+                       LOG_DEBUG("generator found without waypoints around");
                        // if there aren't waypoints near the generator go straight to it
                        navigation_routerating(this, g, ratingscale, 10000);
                        this.havocbot_attack_time = 0;
@@ -1923,7 +1921,7 @@ void ons_MonsterSpawn_Delayed(entity this)
 {
        entity own = this.owner;
 
-       if(!own) { remove(this); return; }
+       if(!own) { delete(this); return; }
 
        if(own.targetname)
        {
@@ -1936,7 +1934,7 @@ void ons_MonsterSpawn_Delayed(entity this)
                }
        }
 
-       remove(this);
+       delete(this);
 }
 
 MUTATOR_HOOKFUNCTION(ons, MonsterSpawn)
@@ -1952,7 +1950,7 @@ void ons_TurretSpawn_Delayed(entity this)
 {
        entity own = this.owner;
 
-       if(!own) { remove(this); return; }
+       if(!own) { delete(this); return; }
 
        if(own.targetname)
        {
@@ -1966,7 +1964,7 @@ void ons_TurretSpawn_Delayed(entity this)
                }
        }
 
-       remove(this);
+       delete(this);
 }
 
 MUTATOR_HOOKFUNCTION(ons, TurretSpawn)
@@ -2178,7 +2176,7 @@ keys:
  */
 spawnfunc(onslaught_link)
 {
-       if(!g_onslaught) { remove(this); return; }
+       if(!g_onslaught) { delete(this); return; }
 
        if (this.target == "" || this.target2 == "")
                objerror(this, "target and target2 must be set\n");
@@ -2203,7 +2201,7 @@ keys:
 
 spawnfunc(onslaught_controlpoint)
 {
-       if(!g_onslaught) { remove(this); return; }
+       if(!g_onslaught) { delete(this); return; }
 
        ons_ControlPoint_Setup(this);
 }
@@ -2219,7 +2217,7 @@ keys:
  */
 spawnfunc(onslaught_generator)
 {
-       if(!g_onslaught) { remove(this); return; }
+       if(!g_onslaught) { delete(this); return; }
        if(!this.team) { objerror(this, "team must be set"); }
 
        ons_GeneratorSetup(this);
@@ -2236,7 +2234,7 @@ void ons_ScoreRules()
        if(c4 >= 0) teams |= BIT(3);
        ScoreRules_basics(teams, SFL_SORT_PRIO_PRIMARY, 0, true);
        ScoreInfo_SetLabel_TeamScore  (ST_ONS_CAPS,     "destroyed", SFL_SORT_PRIO_PRIMARY);
-       ScoreInfo_SetLabel_PlayerScore(SP_ONS_CAPS,     "caps",      SFL_SORT_PRIO_SECONDARY);
+       ScoreInfo_SetLabel_PlayerScore(SP_ONS_CAPS,    "caps",      SFL_SORT_PRIO_SECONDARY);
        ScoreInfo_SetLabel_PlayerScore(SP_ONS_TAKES,    "takes",     0);
        ScoreRules_basics_end();
 }
index 6780ac16d0fa1ddd83c766319d05f2d9289b2c01..45a8f1323b9f142bd02b5eae8ad61202a273ae63 100644 (file)
@@ -1,5 +1,4 @@
-#ifndef IMPULSES_ALL_H
-#define IMPULSES_ALL_H
+#pragma once
 
 REGISTRY(IMPULSES, 255)
 REGISTER_REGISTRY(IMPULSES)
@@ -216,5 +215,3 @@ CHIMPULSE(SPEEDRUN, 141)
 CHIMPULSE(CLONE_STANDING, 142)
 CHIMPULSE(TELEPORT, 143)
 CHIMPULSE(R00T, 148)
-
-#endif
index 18cc5ae4f3b707dfd11caea3774cc2473d2587f2..ff54a3a299f8a3e614fc0e7c62992591b0c8777d 100644 (file)
@@ -1,5 +1,4 @@
-#ifndef ITEMS_ALL_H
-#define ITEMS_ALL_H
+#pragma once
 
 #include <common/command/all.qh>
 
@@ -33,5 +32,3 @@ GENERIC_COMMAND(dumpitems, "Dump all items to the console") {
 #ifndef MENUQC
 string Item_Model(string item_mdl);
 #endif
-
-#endif
index 934271059ba55ed6cc464e9c7122cdd970bc65eb..811f716fb84bccad19e7cf9044c6f56ffafaa0d0 100644 (file)
@@ -1,14 +1,13 @@
-#ifndef INVENTORY_H
-#define INVENTORY_H
+#pragma once
 
 #include "all.qh"
 #include "item/pickup.qh"
 
 CLASS(Inventory, Object)
     /** Stores counts of items, the id being the index */
-    ATTRIBARRAY(Inventory, inv_items, int, Items_MAX)
+    ATTRIBARRAY(Inventory, inv_items, int, Items_MAX);
     /** Previous state */
-    ATTRIB(Inventory, inventory, Inventory, NULL)
+    ATTRIB(Inventory, inventory, Inventory);
 ENDCLASS(Inventory)
 
 /** Player inventory */
@@ -25,7 +24,7 @@ NET_HANDLE(ENT_CLIENT_INVENTORY, bool isnew)
         .int fld = inv_items[it.m_id];
         int prev = this.(fld);
         int next = this.(fld) = ReadByte();
-        LOG_TRACEF("%s: %.0f -> %.0f\n", it.m_name, prev, next);
+        LOG_TRACEF("%s: %.0f -> %.0f", it.m_name, prev, next);
     });
     return true;
 }
@@ -71,8 +70,6 @@ void Inventory_new(entity e)
     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_delete(entity e) { delete(e.inventory.inventory); delete(e.inventory); }
 void Inventory_update(entity e) { e.inventory.SendFlags = 0xFFFFFF; }
 #endif
-
-#endif
index 4ab7af4f2317341ebeb4d1f625dfb8659cecb3d8..e46df6b3c31d8374ff0b5fc8084c84e78a5c1d64 100644 (file)
@@ -1,5 +1,4 @@
-#ifndef GAMEITEM_H
-#define GAMEITEM_H
+#pragma once
 
 const int IT_UNLIMITED_WEAPON_AMMO             =  BIT(0); // when this bit is set, using a weapon does not reduce ammo. Checkpoints can give this powerup.
 const int IT_UNLIMITED_SUPERWEAPONS            =  BIT(1); // when this bit is set, superweapons don't expire. Checkpoints can give this powerup.
@@ -40,12 +39,12 @@ const int IT_PICKUPMASK                     = IT_UNLIMITED_AMMO | IT_JETPACK | IT_FU
 
 #define ITEM_HANDLE(signal, ...) __Item_Send_##signal(__VA_ARGS__)
 CLASS(GameItem, Object)
-    ATTRIB(GameItem, m_id, int, 0)
-    ATTRIB(GameItem, m_name, string, string_null)
-    ATTRIB(GameItem, m_icon, string, string_null)
-    ATTRIB(GameItem, m_color, vector, '1 1 1')
-    ATTRIB(GameItem, m_waypoint, string, string_null)
-    ATTRIB(GameItem, m_waypointblink, int, 1)
+    ATTRIB(GameItem, m_id, int, 0);
+    ATTRIB(GameItem, m_name, string);
+    ATTRIB(GameItem, m_icon, string);
+    ATTRIB(GameItem, m_color, vector, '1 1 1');
+    ATTRIB(GameItem, m_waypoint, string);
+    ATTRIB(GameItem, m_waypointblink, int, 1);
     METHOD(GameItem, display, void(GameItem this, void(string name, string icon) returns))
     {
         TC(GameItem, this);
@@ -58,5 +57,3 @@ CLASS(GameItem, Object)
     }
     void ITEM_HANDLE(Show, GameItem this) { this.show(this); }
 ENDCLASS(GameItem)
-
-#endif
index 84f20483e4f2902d65cc325ee8d0f0ca31d0509b..56c9369192899010fdbabda6d5408028410ae4bd 100644 (file)
@@ -1,11 +1,10 @@
-#ifndef AMMO_H
-#define AMMO_H
+#pragma once
+
 #include "pickup.qh"
 CLASS(Ammo, Pickup)
 #ifdef SVQC
-    ATTRIB(Ammo, m_pickupevalfunc, float(entity player, entity item), commodity_pickupevalfunc)
-    ATTRIB(Ammo, m_respawntime, float(), GET(g_pickup_respawntime_ammo))
-    ATTRIB(Ammo, m_respawntimejitter, float(), GET(g_pickup_respawntimejitter_ammo))
+    ATTRIB(Ammo, m_pickupevalfunc, float(entity player, entity item), commodity_pickupevalfunc);
+    ATTRIB(Ammo, m_respawntime, float(), GET(g_pickup_respawntime_ammo));
+    ATTRIB(Ammo, m_respawntimejitter, float(), GET(g_pickup_respawntimejitter_ammo));
 #endif
 ENDCLASS(Ammo)
-#endif
index adb93e7c94eb8010c2ca8de8da34e6da1e7b7f2f..9078b636d4322b0ac369f8b4dbc2f44f4189baa1 100644 (file)
@@ -1,11 +1,10 @@
-#ifndef ARMOR_H
-#define ARMOR_H
+#pragma once
+
 #include "pickup.qh"
 CLASS(Armor, Pickup)
 #ifdef SVQC
-    ATTRIB(Armor, m_mins, vector, '-16 -16 0')
-    ATTRIB(Armor, m_maxs, vector, '16 16 48')
-    ATTRIB(Armor, m_pickupevalfunc, float(entity player, entity item), commodity_pickupevalfunc)
+    ATTRIB(Armor, m_mins, vector, '-16 -16 0');
+    ATTRIB(Armor, m_maxs, vector, '16 16 48');
+    ATTRIB(Armor, m_pickupevalfunc, float(entity player, entity item), commodity_pickupevalfunc);
 #endif
 ENDCLASS(Armor)
-#endif
index f7bfb5c9386d48e3d0d972fd04db2bc714769dd9..8eb463a8f97ddc9ed66c562748c1fe0732fe8ad3 100644 (file)
@@ -1,11 +1,10 @@
-#ifndef HEALTH_H
-#define HEALTH_H
+#pragma once
+
 #include "pickup.qh"
 CLASS(Health, Pickup)
 #ifdef SVQC
-    ATTRIB(Health, m_mins, vector, '-16 -16 0')
-    ATTRIB(Health, m_maxs, vector, '16 16 48')
-    ATTRIB(Health, m_pickupevalfunc, float(entity player, entity item), commodity_pickupevalfunc)
+    ATTRIB(Health, m_mins, vector, '-16 -16 0');
+    ATTRIB(Health, m_maxs, vector, '16 16 48');
+    ATTRIB(Health, m_pickupevalfunc, float(entity player, entity item), commodity_pickupevalfunc);
 #endif
 ENDCLASS(Health)
-#endif
index 6d914948182482ea6267a1a49352231188dd6c3b..136c8dab6dbf73c633ab35b548134611e6c9b7a3 100644 (file)
@@ -1,35 +1,35 @@
-#ifndef PICKUP_H
-#define PICKUP_H
+#pragma once
+
 #include <common/items/inventory.qh>
 #include <common/items/item.qh>
 CLASS(Pickup, GameItem)
 #ifndef MENUQC
-    ATTRIB(Pickup, m_model, Model, NULL)
-    ATTRIB(Pickup, m_sound, Sound, SND_ITEMPICKUP)
+    ATTRIB(Pickup, m_model, Model);
+    ATTRIB(Pickup, m_sound, Sound, SND_ITEMPICKUP);
 #endif
-    ATTRIB(Pickup, m_name, string, string_null)
+    ATTRIB(Pickup, m_name, string);
     METHOD(Pickup, show, void(Pickup this))
     {
         TC(Pickup, this);
         LOG_INFOF("%s: %s\n", etos(this), this.m_name);
     }
 #ifdef SVQC
-    ATTRIB(Pickup, m_mins, vector, '-16 -16 0')
-    ATTRIB(Pickup, m_maxs, vector, '16 16 32')
-    ATTRIB(Pickup, m_botvalue, int, 0)
-    ATTRIB(Pickup, m_itemflags, int, 0)
-    ATTRIB(Pickup, m_itemid, int, 0)
+    ATTRIB(Pickup, m_mins, vector, '-16 -16 0');
+    ATTRIB(Pickup, m_maxs, vector, '16 16 32');
+    ATTRIB(Pickup, m_botvalue, int, 0);
+    ATTRIB(Pickup, m_itemflags, int, 0);
+    ATTRIB(Pickup, m_itemid, int, 0);
     float generic_pickupevalfunc(entity player, entity item);
-    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)
+    ATTRIB(Pickup, m_pickupevalfunc, float(entity player, entity item), generic_pickupevalfunc);
+    ATTRIB(Pickup, m_respawntime, float());
+    ATTRIB(Pickup, m_respawntimejitter, float());
     float Item_GiveTo(entity item, entity player);
     METHOD(Pickup, giveTo, bool(Pickup this, entity item, entity player))
     {
         TC(Pickup, this);
         bool b = Item_GiveTo(item, player);
         if (b) {
-            LOG_DEBUGF("entity %i picked up %s\n", player, this.m_name);
+            LOG_DEBUGF("entity %i picked up %s", player, this.m_name);
             player.inventory.inv_items[this.m_id]++;
             Inventory_update(player);
         }
@@ -38,5 +38,3 @@ CLASS(Pickup, GameItem)
     bool ITEM_HANDLE(Pickup, Pickup this, entity item, entity player);
 #endif
 ENDCLASS(Pickup)
-
-#endif
index 0a3d907288a203cee53c8e61575de30ebd0cfb87..ca17c970bab7aa01066c61e04f0289062314b82e 100644 (file)
@@ -8,11 +8,11 @@
 #include "pickup.qh"
 CLASS(Powerup, Pickup)
 #ifdef SVQC
-    ATTRIB(Powerup, m_mins, vector, '-16 -16 0')
-    ATTRIB(Powerup, m_maxs, vector, '16 16 48')
-    ATTRIB(Powerup, m_botvalue, int, 100000)
-    ATTRIB(Powerup, m_itemflags, int, FL_POWERUP)
-    ATTRIB(Powerup, m_respawntime, float(), GET(g_pickup_respawntime_powerup))
-    ATTRIB(Powerup, m_respawntimejitter, float(), GET(g_pickup_respawntimejitter_powerup))
+    ATTRIB(Powerup, m_mins, vector, '-16 -16 0');
+    ATTRIB(Powerup, m_maxs, vector, '16 16 48');
+    ATTRIB(Powerup, m_botvalue, int, 100000);
+    ATTRIB(Powerup, m_itemflags, int, FL_POWERUP);
+    ATTRIB(Powerup, m_respawntime, float(), GET(g_pickup_respawntime_powerup));
+    ATTRIB(Powerup, m_respawntimejitter, float(), GET(g_pickup_respawntimejitter_powerup));
 #endif
 ENDCLASS(Powerup)
index 2ec902f68556d121bdceb8122adbef84f4edc999..2bc84c4593afec5e62a5ddcbbfc689cd2c92d71f 100644 (file)
@@ -150,7 +150,11 @@ float _MapInfo_FilterList_cmp(float i, float j, entity pass)
        return strcasecmp(a, b);
 }
 
-float MapInfo_FilterGametype(int pGametype, int pFeatures, int pFlagsRequired, int pFlagsForbidden, bool pAbortOnGenerate)
+float MapInfo_FilterGametype(Gametype pGametype, int pFeatures, int pFlagsRequired, int pFlagsForbidden, bool pAbortOnGenerate)
+{
+       return _MapInfo_FilterGametype(pGametype.m_flags, pFeatures, pFlagsRequired, pFlagsForbidden, pAbortOnGenerate);
+}
+float _MapInfo_FilterGametype(int pGametype, int pFeatures, int pFlagsRequired, int pFlagsForbidden, bool pAbortOnGenerate)
 {
        float i, j;
        if (!_MapInfo_filtered_allocated)
@@ -161,10 +165,10 @@ float MapInfo_FilterGametype(int pGametype, int pFeatures, int pFlagsRequired, i
        MapInfo_count = 0;
        for(i = 0, j = -1; i < _MapInfo_globcount; ++i)
        {
-               if(MapInfo_Get_ByName(_MapInfo_GlobItem(i), 1, 0) == 2) // if we generated one... BAIL OUT and let the caller continue in the next frame.
+               if(MapInfo_Get_ByName(_MapInfo_GlobItem(i), 1, NULL) == 2) // if we generated one... BAIL OUT and let the caller continue in the next frame.
                        if(pAbortOnGenerate)
                        {
-                               LOG_TRACE("Autogenerated a .mapinfo, doing the rest later.\n");
+                               LOG_TRACE("Autogenerated a .mapinfo, doing the rest later.");
                                MapInfo_progress = i / _MapInfo_globcount;
                                return 0;
                        }
@@ -249,7 +253,7 @@ string unquote(string s)
 
 float MapInfo_Get_ByID(float i)
 {
-       if(MapInfo_Get_ByName(MapInfo_BSPName_ByID(i), 0, 0))
+       if(MapInfo_Get_ByName(MapInfo_BSPName_ByID(i), 0, NULL))
                return 1;
        return 0;
 }
@@ -265,7 +269,6 @@ float _MapInfo_Generate(string pFilename) // 0: failure, 1: ok ent, 2: ok bsp
        float i;
        float inWorldspawn;
        float r;
-       float twoBaseModes;
        float diameter, spawnpoints;
        float spawnplaces;
 
@@ -345,21 +348,7 @@ float _MapInfo_Generate(string pFilename) // 0: failure, 1: ok ent, 2: ok bsp
                        }
                        else if(k == "classname")
                        {
-                               if(v == "dom_controlpoint")
-                                       MapInfo_Map_supportedGametypes |= MAPINFO_TYPE_DOMINATION;
-                               else if(v == "item_flag_team2")
-                                       MapInfo_Map_supportedGametypes |= MAPINFO_TYPE_CTF;
-                               else if(v == "team_CTF_blueflag")
-                                       MapInfo_Map_supportedGametypes |= MAPINFO_TYPE_CTF;
-                               else if(v == "invasion_spawnpoint")
-                                       MapInfo_Map_supportedGametypes |= MAPINFO_TYPE_INVASION;
-                               else if(v == "target_assault_roundend")
-                                       MapInfo_Map_supportedGametypes |= MAPINFO_TYPE_ASSAULT;
-                               else if(v == "onslaught_generator")
-                                       MapInfo_Map_supportedGametypes |= MAPINFO_TYPE_ONSLAUGHT;
-                               else if(substring(v, 0, 8) == "nexball_" || substring(v, 0, 4) == "ball")
-                                       MapInfo_Map_supportedGametypes |= MAPINFO_TYPE_NEXBALL;
-                               else if(v == "info_player_team1")
+                               if(v == "info_player_team1")
                                        ++spawnpoints;
                                else if(v == "info_player_team2")
                                        ++spawnpoints;
@@ -367,10 +356,6 @@ float _MapInfo_Generate(string pFilename) // 0: failure, 1: ok ent, 2: ok bsp
                                        ++spawnpoints;
                                else if(v == "info_player_deathmatch")
                                        ++spawnpoints;
-                               else if(v == "trigger_race_checkpoint")
-                                       MapInfo_Map_supportedGametypes |= MAPINFO_TYPE_RACE;
-                               else if(v == "target_startTimer")
-                                       MapInfo_Map_supportedGametypes |= MAPINFO_TYPE_CTS;
                                else if(v == "weapon_nex")
                                        { }
                                else if(v == "weapon_railgun")
@@ -385,6 +370,8 @@ float _MapInfo_Generate(string pFilename) // 0: failure, 1: ok ent, 2: ok bsp
                                        MapInfo_Map_supportedFeatures |= MAPINFO_FEATURE_MONSTERS;
                                else if(v == "target_music" || v == "trigger_music")
                                        _MapInfo_Map_worldspawn_music = string_null; // don't use regular BGM
+                               else
+                                       FOREACH(Gametypes, true, it.m_generate_mapinfo(it, v));
                        }
                }
        }
@@ -395,37 +382,27 @@ float _MapInfo_Generate(string pFilename) // 0: failure, 1: ok ent, 2: ok bsp
        }
        diameter = vlen(mapMaxs - mapMins);
 
-       twoBaseModes = MapInfo_Map_supportedGametypes & (MAPINFO_TYPE_CTF | MAPINFO_TYPE_ASSAULT | MAPINFO_TYPE_RACE | MAPINFO_TYPE_NEXBALL);
-       if(twoBaseModes && (MapInfo_Map_supportedGametypes == twoBaseModes))
+       int twoBaseModes = 0;
+       FOREACH(Gametypes, it.m_isTwoBaseMode(), twoBaseModes |= it.m_flags);
+       if(twoBaseModes && (twoBaseModes &= MapInfo_Map_supportedGametypes))
        {
-               // we have a CTF-only or Assault-only map. Don't add other modes then,
-               // as the map is too symmetric for them.
+               // we have a symmetrical map, don't add the modes without bases
        }
        else
        {
-               MapInfo_Map_supportedGametypes |= MAPINFO_TYPE_DEATHMATCH;      // DM always works
-               MapInfo_Map_supportedGametypes |= MAPINFO_TYPE_LMS;             // LMS always works
-               MapInfo_Map_supportedGametypes |= MAPINFO_TYPE_KEEPAWAY;                // Keepaway always works
-
-               if(spawnpoints >= 8  && diameter > 4096) {
-                       MapInfo_Map_supportedGametypes |= MAPINFO_TYPE_TEAM_DEATHMATCH;
-                       MapInfo_Map_supportedGametypes |= MAPINFO_TYPE_FREEZETAG;
-                       MapInfo_Map_supportedGametypes |= MAPINFO_TYPE_CA;
-               }
-               if(spawnpoints >= 12 && diameter > 5120)
-                       MapInfo_Map_supportedGametypes |= MAPINFO_TYPE_KEYHUNT;
+               FOREACH(Gametypes, it.m_isAlwaysSupported(it, spawnpoints, diameter), MapInfo_Map_supportedGametypes |= it.m_flags);
        }
 
-       if(MapInfo_Map_supportedGametypes & MAPINFO_TYPE_RACE)
+       if(MapInfo_Map_supportedGametypes & MAPINFO_TYPE_RACE.m_flags)
        if(!spawnplaces)
        {
-               MapInfo_Map_supportedGametypes &= ~MAPINFO_TYPE_RACE;
-               MapInfo_Map_supportedGametypes |= MAPINFO_TYPE_CTS;
+               MapInfo_Map_supportedGametypes &= ~MAPINFO_TYPE_RACE.m_flags;
+               MapInfo_Map_supportedGametypes |= MAPINFO_TYPE_CTS.m_flags;
        }
 
        LOG_TRACE("-> diameter ",    ftos(diameter));
        LOG_TRACE(";  spawnpoints ", ftos(spawnpoints));
-       LOG_TRACE(";  modes ",       ftos(MapInfo_Map_supportedGametypes), "\n");
+       LOG_TRACE(";  modes ",       ftos(MapInfo_Map_supportedGametypes));
 
        fclose(fh);
 
@@ -447,7 +424,7 @@ void _MapInfo_Map_Reset()
        MapInfo_Map_maxs = '0 0 0';
 }
 
-string _MapInfo_GetDefault(float t)
+string _MapInfo_GetDefault(Gametype t)
 {
        switch(t)
        {
@@ -472,11 +449,11 @@ string _MapInfo_GetDefault(float t)
        }
 }
 
-void _MapInfo_Map_ApplyGametype(string s, int pWantedType, int pThisType, int load_default)
+void _MapInfo_Map_ApplyGametype(string s, Gametype pWantedType, Gametype pThisType, int load_default)
 {
        string sa;
-       MapInfo_Map_supportedGametypes |= pThisType;
-       if(!(pThisType & pWantedType))
+       MapInfo_Map_supportedGametypes |= pThisType.m_flags;
+       if(!(pThisType.m_flags & pWantedType.m_flags))
                return;
 
        if(load_default)
@@ -499,55 +476,13 @@ void _MapInfo_Map_ApplyGametype(string s, int pWantedType, int pThisType, int lo
                cvar_set("timelimit", sa);
        s = cdr(s);
 
-       if(pWantedType == MAPINFO_TYPE_TEAM_DEATHMATCH)
-       {
-               sa = car(s);
-               if(sa != "")
-                       cvar_set("g_tdm_teams", sa);
-               s = cdr(s);
-       }
-
-       if(pWantedType == MAPINFO_TYPE_KEYHUNT)
-       {
-               sa = car(s);
-               if(sa != "")
-                       cvar_set("g_keyhunt_teams", sa);
-               s = cdr(s);
-       }
-
-       if(pWantedType == MAPINFO_TYPE_CA)
-       {
-               sa = car(s);
-               if(sa != "")
-                       cvar_set("g_ca_teams", sa);
-               s = cdr(s);
-       }
-
-       if(pWantedType == MAPINFO_TYPE_FREEZETAG)
-       {
-               sa = car(s);
-               if(sa != "")
-                       cvar_set("g_freezetag_teams", sa);
-               s = cdr(s);
-       }
-
-       if(pWantedType == MAPINFO_TYPE_CTF)
-       {
-               sa = car(s);
-               if(sa != "")
-                       cvar_set("fraglimit", sa);
-               s = cdr(s);
-       }
-
-       /* keepaway wuz here
-       if(pWantedType == MAPINFO_TYPE_KEEPAWAY)
+       if(pWantedType.m_setTeams)
        {
                sa = car(s);
                if(sa != "")
-                       cvar_set("fraglimit", sa);
+                       pWantedType.m_setTeams(sa);
                s = cdr(s);
        }
-       */
 
        // rc = timelimit timelimit_qualification laps laps_teamplay
        if(pWantedType == MAPINFO_TYPE_RACE)
@@ -569,19 +504,6 @@ void _MapInfo_Map_ApplyGametype(string s, int pWantedType, int pThisType, int lo
                s = cdr(s);
        }
 
-       if(pWantedType == MAPINFO_TYPE_CTS)
-       {
-               sa = car(s);
-
-               // this is the skill of the map
-               // not parsed by anything yet
-               // for map databases
-               //if(sa != "")
-               //      cvar_set("fraglimit", sa);
-
-               s = cdr(s);
-       }
-
        if(pWantedType == MAPINFO_TYPE_ASSAULT || pWantedType == MAPINFO_TYPE_ONSLAUGHT || pWantedType == MAPINFO_TYPE_CTS) // these modes don't use fraglimit
        {
                cvar_set("leadlimit", "0");
@@ -595,22 +517,20 @@ void _MapInfo_Map_ApplyGametype(string s, int pWantedType, int pThisType, int lo
        }
 }
 
-string _MapInfo_GetDefaultEx(float t)
+string _MapInfo_GetDefaultEx(Gametype t)
 {
-       FOREACH(Gametypes, it.items == t, return it.model2);
-       return "";
+       return t ? t.model2 : "";
 }
 
-float _MapInfo_GetTeamPlayBool(float t)
+float _MapInfo_GetTeamPlayBool(Gametype t)
 {
-       FOREACH(Gametypes, it.items == t, return it.team);
-       return false;
+       return t ? t.team : false;
 }
 
-void _MapInfo_Map_ApplyGametypeEx(string s, int pWantedType, int pThisType)
+void _MapInfo_Map_ApplyGametypeEx(string s, Gametype pWantedType, Gametype pThisType)
 {
-       MapInfo_Map_supportedGametypes |= pThisType;
-       if (!(pThisType & pWantedType))
+       MapInfo_Map_supportedGametypes |= pThisType.m_flags;
+       if (!(pThisType.m_flags & pWantedType.m_flags))
                return;
 
        // reset all the cvars to their defaults
@@ -683,13 +603,7 @@ void _MapInfo_Map_ApplyGametypeEx(string s, int pWantedType, int pThisType)
        }
 }
 
-Gametype MapInfo_Type(int t)
-{
-       FOREACH(Gametypes, it.items == t, return it);
-       return NULL;
-}
-
-int MapInfo_Type_FromString(string t)
+Gametype MapInfo_Type_FromString(string t)
 {
 #define deprecate(from, to) MACRO_BEGIN { \
        if (t == #from) { \
@@ -704,31 +618,25 @@ int MapInfo_Type_FromString(string t)
        deprecate(invasion, inv);
        deprecate(assault, as);
        deprecate(race, rc);
-       if (t == "all") return MAPINFO_TYPE_ALL;
-       FOREACH(Gametypes, it.mdl == t, return it.items);
-       return 0;
+       FOREACH(Gametypes, it.mdl == t, return it);
+       return NULL;
 #undef deprecate
 }
 
-string MapInfo_Type_Description(float t)
+string MapInfo_Type_Description(Gametype t)
 {
-       FOREACH(Gametypes, it.items == t, return it.gametype_description);
-       return "";
+       return t ? t.gametype_description : "";
 }
 
-string MapInfo_Type_ToString(float t)
+string MapInfo_Type_ToString(Gametype t)
 {
-       if(t == MAPINFO_TYPE_ALL)
-               return "all";
-       FOREACH(Gametypes, it.items == t, return it.mdl);
-       return "";
+       return t ? t.mdl : "";
 }
 
-string MapInfo_Type_ToText(float t)
+string MapInfo_Type_ToText(Gametype t)
 {
-       FOREACH(Gametypes, it.items == t, return it.message);
        /* xgettext:no-c-format */
-       return _("@!#%'n Tuba Throwing");
+       return t ? t.message : _("@!#%'n Tuba Throwing");
 }
 
 void _MapInfo_Parse_Settemp(string pFilename, string acl, float type, string s, float recurse)
@@ -815,7 +723,7 @@ void _MapInfo_Parse_Settemp(string pFilename, string acl, float type, string s,
        {
                if(type == 0) // server set
                {
-                       LOG_TRACE("Applying temporary setting ", t, " := ", s, "\n");
+                       LOG_TRACE("Applying temporary setting ", t, " := ", s);
                        if(cvar("g_campaign"))
                                cvar_set(t, s); // this is a wrapper and is always temporary anyway; no need to backup old values then
                        else
@@ -823,7 +731,7 @@ void _MapInfo_Parse_Settemp(string pFilename, string acl, float type, string s,
                }
                else
                {
-                       LOG_TRACE("Applying temporary client setting ", t, " := ", s, "\n");
+                       LOG_TRACE("Applying temporary client setting ", t, " := ", s);
                        MapInfo_Map_clientstuff = strcat(
                                        MapInfo_Map_clientstuff, "cl_cmd settemp \"", t, "\" \"", s, "\"\n"
                                        );
@@ -857,7 +765,7 @@ float MapInfo_isRedundant(string fn, string t)
 }
 
 // load info about a map by name into the MapInfo_Map_* globals
-float MapInfo_Get_ByName_NoFallbacks(string pFilename, int pAllowGenerate, int pGametypeToSet)
+float MapInfo_Get_ByName_NoFallbacks(string pFilename, int pAllowGenerate, Gametype pGametypeToSet)
 {
        string fn;
        string s, t;
@@ -874,7 +782,7 @@ float MapInfo_Get_ByName_NoFallbacks(string pFilename, int pAllowGenerate, int p
                return 0;
        }
 
-       if(pGametypeToSet == 0)
+       if(pGametypeToSet == NULL)
                if(MapInfo_Cache_Retrieve(pFilename))
                        return 1;
 
@@ -939,9 +847,9 @@ float MapInfo_Get_ByName_NoFallbacks(string pFilename, int pAllowGenerate, int p
                        if(MapInfo_Map_flags & MAPINFO_FLAG_FRUSTRATING)
                                fputs(fh, "frustrating\n");
 
-                       for(i = 1; i <= MapInfo_Map_supportedGametypes; i *= 2)
-                               if(MapInfo_Map_supportedGametypes & i)
-                                       fputs(fh, sprintf("gametype %s // defaults: %s\n", MapInfo_Type_ToString(i), _MapInfo_GetDefaultEx(i)));
+                       FOREACH(Gametypes, MapInfo_Map_supportedGametypes & it.m_flags, {
+                               fputs(fh, sprintf("gametype %s // defaults: %s\n", MapInfo_Type_ToString(it), _MapInfo_GetDefaultEx(it)));
+                       });
 
                        if(fexists(strcat("scripts/", pFilename, ".arena")))
                                fputs(fh, "settemp_for_type all sv_q3acompat_machineshotgunswap 1\n");
@@ -1025,7 +933,7 @@ float MapInfo_Get_ByName_NoFallbacks(string pFilename, int pAllowGenerate, int p
                else if(t == "type")
                {
                        t = car(s); s = cdr(s);
-                       f = MapInfo_Type_FromString(t);
+                       Gametype f = MapInfo_Type_FromString(t);
                        LOG_MAPWARN("Map ", pFilename, " contains the legacy 'type' keyword which is deprecated and will be removed in the future. Please migrate the mapinfo file to 'gametype'.\n");
                        if(f)
                                _MapInfo_Map_ApplyGametype (s, pGametypeToSet, f, true);
@@ -1035,7 +943,7 @@ float MapInfo_Get_ByName_NoFallbacks(string pFilename, int pAllowGenerate, int p
                else if(t == "gametype")
                {
                        t = car(s); s = cdr(s);
-                       f = MapInfo_Type_FromString(t);
+                       Gametype f = MapInfo_Type_FromString(t);
                        if(f)
                                _MapInfo_Map_ApplyGametypeEx (s, pGametypeToSet, f);
                        else
@@ -1075,9 +983,10 @@ float MapInfo_Get_ByName_NoFallbacks(string pFilename, int pAllowGenerate, int p
                else if(t == "settemp_for_type")
                {
                        t = car(s); s = cdr(s);
+                       Gametype f;
                        if((f = MapInfo_Type_FromString(t)))
                        {
-                               if(f & pGametypeToSet)
+                               if(f.m_flags & pGametypeToSet.m_flags)
                                {
                                        _MapInfo_Parse_Settemp(pFilename, acl, 0, s, 1);
                                }
@@ -1090,9 +999,10 @@ float MapInfo_Get_ByName_NoFallbacks(string pFilename, int pAllowGenerate, int p
                else if(t == "clientsettemp_for_type")
                {
                        t = car(s); s = cdr(s);
+                       Gametype f;
                        if((f = MapInfo_Type_FromString(t)))
                        {
-                               if(f & pGametypeToSet)
+                               if(f.m_flags & pGametypeToSet.m_flags)
                                {
                                        _MapInfo_Parse_Settemp(pFilename, acl, 1, s, 1);
                                }
@@ -1146,21 +1056,21 @@ float MapInfo_Get_ByName_NoFallbacks(string pFilename, int pAllowGenerate, int p
        LOG_MAPWARN("Map ", pFilename, " supports no game types, ignored\n");
        return 0;
 }
-float MapInfo_Get_ByName(string pFilename, float pAllowGenerate, int pGametypeToSet)
+int MapInfo_Get_ByName(string pFilename, float pAllowGenerate, Gametype pGametypeToSet)
 {
-       float r = MapInfo_Get_ByName_NoFallbacks(pFilename, pAllowGenerate, pGametypeToSet);
+       int r = MapInfo_Get_ByName_NoFallbacks(pFilename, pAllowGenerate, pGametypeToSet);
 
        if(cvar("g_tdm_on_dm_maps"))
        {
                // if this is set, all DM maps support TDM too
-               if (!(MapInfo_Map_supportedGametypes & MAPINFO_TYPE_TEAM_DEATHMATCH))
-                       if(MapInfo_Map_supportedGametypes & MAPINFO_TYPE_DEATHMATCH)
+               if (!(MapInfo_Map_supportedGametypes & MAPINFO_TYPE_TEAM_DEATHMATCH.m_flags))
+                       if(MapInfo_Map_supportedGametypes & MAPINFO_TYPE_DEATHMATCH.m_flags)
                                _MapInfo_Map_ApplyGametypeEx ("", pGametypeToSet, MAPINFO_TYPE_TEAM_DEATHMATCH);
        }
 
        if(pGametypeToSet)
        {
-               if(!(MapInfo_Map_supportedGametypes & pGametypeToSet))
+               if(!(MapInfo_Map_supportedGametypes & pGametypeToSet.m_flags))
                {
                        error("Can't select the requested game type. This should never happen as the caller should prevent it!\n");
                        //_MapInfo_Map_ApplyGametypeEx("", pGametypeToSet, MAPINFO_TYPE_DEATHMATCH);
@@ -1233,19 +1143,18 @@ int MapInfo_CurrentFeatures()
        return req;
 }
 
-int MapInfo_CurrentGametype()
+Gametype MapInfo_CurrentGametype()
 {
-       int prev = cvar("gamecfg");
-       FOREACH(Gametypes, cvar(it.netname) && it.items != prev, return it.items);
-       if (prev) return prev;
-       return MAPINFO_TYPE_DEATHMATCH;
+       Gametype prev = Gametypes_from(cvar("gamecfg"));
+       FOREACH(Gametypes, cvar(it.netname) && it != prev, return it);
+       return prev ? prev : MAPINFO_TYPE_DEATHMATCH;
 }
 
 float _MapInfo_CheckMap(string s) // returns 0 if the map can't be played with the current settings, 1 otherwise
 {
-       if(!MapInfo_Get_ByName(s, 1, 0))
+       if(!MapInfo_Get_ByName(s, 1, NULL))
                return 0;
-       if((MapInfo_Map_supportedGametypes & MapInfo_CurrentGametype()) == 0)
+       if((MapInfo_Map_supportedGametypes & MapInfo_CurrentGametype().m_flags) == 0)
                return 0;
        if((MapInfo_Map_supportedFeatures & MapInfo_CurrentFeatures()) != MapInfo_CurrentFeatures())
                return 0;
@@ -1260,9 +1169,9 @@ float MapInfo_CheckMap(string s) // returns 0 if the map can't be played with th
        return r;
 }
 
-void MapInfo_SwitchGameType(int t)
+void MapInfo_SwitchGameType(Gametype t)
 {
-       FOREACH(Gametypes, true, cvar_set(it.netname, (it.items == t) ? "1" : "0"));
+       FOREACH(Gametypes, true, cvar_set(it.netname, (it == t) ? "1" : "0"));
 }
 
 void MapInfo_LoadMap(string s, float reinit)
@@ -1272,7 +1181,7 @@ void MapInfo_LoadMap(string s, float reinit)
        //if(!MapInfo_CheckMap(s))
        //{
        //      print("EMERGENCY: can't play the selected map in the given game mode. Falling back to DM.\n");
-       //      MapInfo_SwitchGameType(MAPINFO_TYPE_DEATHMATCH);
+       //      MapInfo_SwitchGameType(MAPINFO_TYPE_DEATHMATCH.m_flags);
        //}
 
        cvar_settemp_restore();
@@ -1282,7 +1191,7 @@ void MapInfo_LoadMap(string s, float reinit)
                localcmd(strcat("\nchangelevel ", s, "\n"));
 }
 
-string MapInfo_ListAllowedMaps(float type, float pRequiredFlags, float pForbiddenFlags)
+string MapInfo_ListAllowedMaps(Gametype type, float pRequiredFlags, float pForbiddenFlags)
 {
        string out;
        float i;
@@ -1304,7 +1213,7 @@ string MapInfo_ListAllAllowedMaps(float pRequiredFlags, float pForbiddenFlags)
 
        // to make absolutely sure:
        MapInfo_Enumerate();
-       MapInfo_FilterGametype(MAPINFO_TYPE_ALL, 0, pRequiredFlags, pForbiddenFlags, 0);
+       _MapInfo_FilterGametype(MAPINFO_TYPE_ALL, 0, pRequiredFlags, pForbiddenFlags, 0);
 
        out = "";
        for(i = 0; i < MapInfo_count; ++i)
@@ -1315,47 +1224,46 @@ string MapInfo_ListAllAllowedMaps(float pRequiredFlags, float pForbiddenFlags)
        return substring(out, 1, strlen(out) - 1);
 }
 
-void MapInfo_LoadMapSettings_SaveGameType(float t)
+void MapInfo_LoadMapSettings_SaveGameType(Gametype t)
 {
        MapInfo_SwitchGameType(t);
-       cvar_set("gamecfg", ftos(t));
+       cvar_set("gamecfg", ftos(t.m_id));
        MapInfo_LoadedGametype = t;
 }
 
 void MapInfo_LoadMapSettings(string s) // to be called from worldspawn
 {
-       float t;
-
-       t = MapInfo_CurrentGametype();
+       Gametype t = MapInfo_CurrentGametype();
        MapInfo_LoadMapSettings_SaveGameType(t);
 
        if(!_MapInfo_CheckMap(s)) // with underscore, it keeps temps
        {
                if(cvar("g_mapinfo_allow_unsupported_modes_and_let_stuff_break"))
                {
-                       LOG_SEVERE("can't play the selected map in the given game mode. Working with only the override settings.\n");
+                       LOG_SEVERE("can't play the selected map in the given game mode. Working with only the override settings.");
                        _MapInfo_Map_ApplyGametypeEx("", t, t);
                        return; // do not call Get_ByName!
                }
 
                if(MapInfo_Map_supportedGametypes == 0)
                {
-                       LOG_SEVERE("Mapinfo system is not functional at all. Assuming deathmatch.\n");
-                       MapInfo_Map_supportedGametypes = MAPINFO_TYPE_DEATHMATCH;
+                       LOG_SEVERE("Mapinfo system is not functional at all. Assuming deathmatch.");
+                       MapInfo_Map_supportedGametypes = MAPINFO_TYPE_DEATHMATCH.m_flags;
                        MapInfo_LoadMapSettings_SaveGameType(MAPINFO_TYPE_DEATHMATCH);
                        _MapInfo_Map_ApplyGametypeEx("", MAPINFO_TYPE_DEATHMATCH, MAPINFO_TYPE_DEATHMATCH);
                        return; // do not call Get_ByName!
                }
 
-               t = 1;
+               int _t = 1;
                while(!(MapInfo_Map_supportedGametypes & 1))
                {
-                       t *= 2;
-                       MapInfo_Map_supportedGametypes = floor(MapInfo_Map_supportedGametypes / 2);
+                       _t <<= 1;
+                       MapInfo_Map_supportedGametypes = floor(MapInfo_Map_supportedGametypes >> 1);
                }
+               FOREACH(Gametypes, it.m_flags == _t, { t = it; break; });
 
                // t is now a supported mode!
-               LOG_WARNING("can't play the selected map in the given game mode. Falling back to a supported mode.\n");
+               LOG_WARN("can't play the selected map in the given game mode. Falling back to a supported mode.");
                MapInfo_LoadMapSettings_SaveGameType(t);
        }
        MapInfo_Get_ByName(s, 1, t);
index b7115ef552522fd2786a3749166430e9a7ae8ea8..f37e2db060881e23088652e012926e668b731216 100644 (file)
@@ -1,32 +1,67 @@
-#ifndef MAPINFO_H
-#define MAPINFO_H
+#pragma once
 
 bool autocvar_developer_mapper;
 
-#define LOG_MAPWARN(...) MACRO_BEGIN { if (autocvar_developer_mapper) LOG_WARNING(__VA_ARGS__); } MACRO_END
-#define LOG_MAPWARNF(...) MACRO_BEGIN { if (autocvar_developer_mapper) LOG_WARNINGF(__VA_ARGS__); } MACRO_END
+#define LOG_MAPWARN(...) MACRO_BEGIN { if (autocvar_developer_mapper) LOG_WARN(__VA_ARGS__); } MACRO_END
+#define LOG_MAPWARNF(...) MACRO_BEGIN { if (autocvar_developer_mapper) LOG_WARNF(__VA_ARGS__); } MACRO_END
 
 #include "util.qh"
 
+// info about a map that MapInfo loads
+string MapInfo_Map_bspname;
+string MapInfo_Map_title;
+string MapInfo_Map_titlestring; // either bspname: title or just title, depending on whether bspname is redundant
+string MapInfo_Map_description;
+string MapInfo_Map_author;
+string MapInfo_Map_clientstuff; // not in cache, only for map load
+string MapInfo_Map_fog; // not in cache, only for map load
+int MapInfo_Map_supportedGametypes;
+int MapInfo_Map_supportedFeatures;
+int MapInfo_Map_flags;
+vector MapInfo_Map_mins; // these are '0 0 0' if not supported!
+vector MapInfo_Map_maxs; // these are '0 0 0' if not specified!
+
+int MAPINFO_TYPE_ALL;
+.int m_flags;
+
 CLASS(Gametype, Object)
-    ATTRIB(Gametype, m_id, int, 0)
+    ATTRIB(Gametype, m_id, int, 0);
     /** game type ID */
-    ATTRIB(Gametype, items, int, 0)
+    ATTRIB(Gametype, items, int, 0);
     /** game type name as in cvar (with g_ prefix) */
-    ATTRIB(Gametype, netname, string, string_null)
+    ATTRIB(Gametype, netname, string);
     /** game type short name */
-    ATTRIB(Gametype, mdl, string, string_null)
+    ATTRIB(Gametype, mdl, string);
     /** human readable name */
-    ATTRIB(Gametype, message, string, string_null)
+    ATTRIB(Gametype, message, string);
     /** does this gametype support teamplay? */
-    ATTRIB(Gametype, team, bool, false)
+    ATTRIB(Gametype, team, bool, false);
     /** game type defaults */
-    ATTRIB(Gametype, model2, string, string_null)
+    ATTRIB(Gametype, model2, string);
     /** game type description */
-    ATTRIB(Gametype, gametype_description, string, string_null)
+    ATTRIB(Gametype, gametype_description, string);
+#ifdef CSQC
+    ATTRIB(Gametype, m_modicons, void(vector pos, vector mySize));
+    ATTRIB(Gametype, m_modicons_reset, void());
+#endif
 
-    ATTRIB(Gametype, m_mutators, string, string_null)
-    ATTRIB(Gametype, m_parse_mapinfo, bool(string k, string v), func_null)
+    ATTRIB(Gametype, m_mutators, string);
+    METHOD(Gametype, m_parse_mapinfo, bool(string k, string v))
+    {
+        return false;
+    }
+    METHOD(Gametype, m_generate_mapinfo, void(Gametype this, string v))
+    {
+        TC(Gametype, this);
+    }
+    METHOD(Gametype, m_isTwoBaseMode, bool())
+    {
+        return false;
+    }
+    METHOD(Gametype, m_isAlwaysSupported, bool(Gametype this, int spawnpoints, float diameter))
+    {
+        return false;
+    }
 
     METHOD(Gametype, describe, string(Gametype this))
     {
@@ -40,150 +75,412 @@ CLASS(Gametype, Object)
         returns(this.message, strcat("gametype_", this.mdl));
     }
 
-    CONSTRUCTOR(Gametype, string hname, string sname, string g_name, bool gteamplay, string mutators, string defaults, string gdescription)
+    METHOD(Gametype, gametype_init, void(Gametype this, string hname, string sname, string g_name, bool gteamplay, string mutators, string defaults, string gdescription))
     {
-        CONSTRUCT(Gametype);
         this.netname = g_name;
         this.mdl = sname;
         this.message = hname;
         this.team = gteamplay;
-        this.m_mutators = mutators;
+        this.m_mutators = cons(sname, mutators);
         this.model2 = defaults;
         this.gametype_description = gdescription;
+
+        // same as `1 << m_id`
+        MAPINFO_TYPE_ALL |= this.items = this.m_flags = (MAPINFO_TYPE_ALL + 1);
     }
 ENDCLASS(Gametype)
 
-REGISTRY(Gametypes, BITS(4))
+REGISTRY(Gametypes, 24)
 #define Gametypes_from(i) _Gametypes_from(i, NULL)
 REGISTER_REGISTRY(Gametypes)
 REGISTRY_CHECK(Gametypes)
-int MAPINFO_TYPE_ALL;
-#define REGISTER_GAMETYPE(hname, sname, g_name, NAME, gteamplay, mutators, defaults, gdescription)          \
-    int MAPINFO_TYPE_##NAME;                                                                                \
-    bool NAME##_mapinfo(string k, string v) { return = false; }                                             \
-    REGISTER(Gametypes, MAPINFO_TYPE, g_name, m_id,                                      \
-        NEW(Gametype, hname, #sname, #g_name, gteamplay, #sname " " mutators, defaults, gdescription)       \
-    ) {                                                                                                     \
-        /* same as `1 << m_id` */                                                                           \
-        MAPINFO_TYPE_##NAME = MAPINFO_TYPE_ALL + 1; MAPINFO_TYPE_ALL |= MAPINFO_TYPE_##NAME;                \
-        this.items = MAPINFO_TYPE_##NAME;                                                                   \
-        this.m_parse_mapinfo = NAME##_mapinfo;                                                              \
-    }                                                                                                       \
-    [[accumulate]] bool NAME##_mapinfo(string k, string v)
-
-#define IS_GAMETYPE(NAME) \
-    (MapInfo_LoadedGametype == MAPINFO_TYPE_##NAME)
-
-REGISTER_GAMETYPE(_("Deathmatch"),dm,g_dm,DEATHMATCH,false,"","timelimit=20 pointlimit=30 leadlimit=0",_("Score as many frags as you can"));
-
-REGISTER_GAMETYPE(_("Last Man Standing"),lms,g_lms,LMS,false,"","timelimit=20 lives=9 leadlimit=0",_("Survive and kill until the enemies have no lives left"));
-
-REGISTER_GAMETYPE(_("Race"),rc,g_race,RACE,false,"","timelimit=20 qualifying_timelimit=5 laplimit=7 teamlaplimit=15 leadlimit=0",_("Race against other players to the finish line"))
-{
-    if (!k) {
-       cvar_set("g_race_qualifying_timelimit", cvar_defstring("g_race_qualifying_timelimit"));
+#define REGISTER_GAMETYPE(NAME, inst) REGISTER(Gametypes, MAPINFO_TYPE, NAME, m_id, inst)
+
+#define IS_GAMETYPE(NAME) (MapInfo_LoadedGametype == MAPINFO_TYPE_##NAME)
+
+CLASS(Deathmatch, Gametype)
+    INIT(Deathmatch)
+    {
+        this.gametype_init(this, _("Deathmatch"),"dm","g_dm",false,"","timelimit=20 pointlimit=30 leadlimit=0",_("Score as many frags as you can"));
+    }
+    METHOD(Deathmatch, m_isAlwaysSupported, bool(Gametype this, int spawnpoints, float diameter))
+    {
+        return true;
+    }
+ENDCLASS(Deathmatch)
+REGISTER_GAMETYPE(DEATHMATCH, NEW(Deathmatch));
+
+CLASS(LastManStanding, Gametype)
+    INIT(LastManStanding)
+    {
+        this.gametype_init(this, _("Last Man Standing"),"lms","g_lms",false,"","timelimit=20 lives=9 leadlimit=0",_("Survive and kill until the enemies have no lives left"));
+    }
+    METHOD(LastManStanding, m_isAlwaysSupported, bool(Gametype this, int spawnpoints, float diameter))
+    {
         return true;
     }
-    switch (k) {
-        case "qualifying_timelimit":
-            cvar_set("g_race_qualifying_timelimit", v);
+ENDCLASS(LastManStanding)
+REGISTER_GAMETYPE(LMS, NEW(LastManStanding));
+
+#ifdef CSQC
+void HUD_Mod_Race(vector pos, vector mySize);
+#endif
+CLASS(Race, Gametype)
+    INIT(Race)
+    {
+        this.gametype_init(this, _("Race"),"rc","g_race",false,"","timelimit=20 qualifying_timelimit=5 laplimit=7 teamlaplimit=15 leadlimit=0",_("Race against other players to the finish line"));
+    }
+    METHOD(Race, m_parse_mapinfo, bool(string k, string v))
+    {
+        if (!k) {
+            cvar_set("g_race_qualifying_timelimit", cvar_defstring("g_race_qualifying_timelimit"));
             return true;
+        }
+        switch (k) {
+            case "qualifying_timelimit":
+                cvar_set("g_race_qualifying_timelimit", v);
+                return true;
+        }
+        return false;
+    }
+    METHOD(Race, m_generate_mapinfo, void(Gametype this, string v))
+    {
+        if(v == "trigger_race_checkpoint")
+            MapInfo_Map_supportedGametypes |= this.m_flags;
     }
-}
+    METHOD(Race, m_isTwoBaseMode, bool())
+    {
+        return true;
+    }
+#ifdef CSQC
+    ATTRIB(Race, m_modicons, void(vector pos, vector mySize), HUD_Mod_Race);
+#endif
+ENDCLASS(Race)
+REGISTER_GAMETYPE(RACE, NEW(Race));
 #define g_race IS_GAMETYPE(RACE)
 
-REGISTER_GAMETYPE(_("Race CTS"),cts,g_cts,CTS,false,"cloaked","timelimit=20",_("Race for fastest time."));
+CLASS(RaceCTS, Gametype)
+    INIT(RaceCTS)
+    {
+        this.gametype_init(this, _("Race CTS"),"cts","g_cts",false,"cloaked","timelimit=20",_("Race for fastest time."));
+    }
+    METHOD(RaceCTS, m_generate_mapinfo, void(Gametype this, string v))
+    {
+        if(v == "target_startTimer")
+            MapInfo_Map_supportedGametypes |= this.m_flags;
+    }
+    METHOD(RaceCTS, m_setTeams, void(string sa))
+    {
+        // this is the skill of the map
+        // not parsed by anything yet
+        // for map databases
+        //  cvar_set("fraglimit", sa);
+    }
+#ifdef CSQC
+    ATTRIB(RaceCTS, m_modicons, void(vector pos, vector mySize), HUD_Mod_Race);
+#endif
+ENDCLASS(RaceCTS)
+REGISTER_GAMETYPE(CTS, NEW(RaceCTS));
 #define g_cts IS_GAMETYPE(CTS)
 
-REGISTER_GAMETYPE(_("Team Deathmatch"),tdm,g_tdm,TEAM_DEATHMATCH,true,"","timelimit=20 pointlimit=50 teams=2 leadlimit=0",_("Help your team score the most frags against the enemy team"))
-{
-    if (!k) {
-        cvar_set("g_tdm_teams", cvar_defstring("g_tdm_teams"));
-        return true;
+CLASS(TeamDeathmatch, Gametype)
+    INIT(TeamDeathmatch)
+    {
+        this.gametype_init(this, _("Team Deathmatch"),"tdm","g_tdm",true,"","timelimit=20 pointlimit=50 teams=2 leadlimit=0",_("Help your team score the most frags against the enemy team"));
+    }
+    METHOD(TeamDeathmatch, m_parse_mapinfo, bool(string k, string v))
+    {
+        if (!k) {
+            cvar_set("g_tdm_teams", cvar_defstring("g_tdm_teams"));
+            return true;
+        }
+        switch (k) {
+            case "teams":
+                cvar_set("g_tdm_teams", v);
+                return true;
+        }
+        return false;
     }
-    switch (k) {
-        case "teams":
-            cvar_set("g_tdm_teams", v);
+    METHOD(TeamDeathmatch, m_isAlwaysSupported, bool(Gametype this, int spawnpoints, float diameter))
+    {
+        if(spawnpoints >= 8 && diameter > 4096)
             return true;
+        return false;
+    }
+    METHOD(TeamDeathmatch, m_setTeams, void(string sa))
+    {
+        cvar_set("g_tdm_teams", sa);
     }
-}
+ENDCLASS(TeamDeathmatch)
+REGISTER_GAMETYPE(TEAM_DEATHMATCH, NEW(TeamDeathmatch));
 #define g_tdm IS_GAMETYPE(TEAM_DEATHMATCH)
 
-REGISTER_GAMETYPE(_("Capture the Flag"),ctf,g_ctf,CTF,true,"","timelimit=20 caplimit=10 leadlimit=6",_("Find and bring the enemy flag to your base to capture it, defend your base from the other team"));
+#ifdef CSQC
+void HUD_Mod_CTF(vector pos, vector mySize);
+void HUD_Mod_CTF_Reset();
+#endif
+CLASS(CaptureTheFlag, Gametype)
+    INIT(CaptureTheFlag)
+    {
+        this.gametype_init(this, _("Capture the Flag"),"ctf","g_ctf",true,"","timelimit=20 caplimit=10 leadlimit=6",_("Find and bring the enemy flag to your base to capture it, defend your base from the other team"));
+    }
+    METHOD(CaptureTheFlag, m_generate_mapinfo, void(Gametype this, string v))
+    {
+        if(v == "item_flag_team2" || v == "team_CTF_blueflag")
+            MapInfo_Map_supportedGametypes |= this.m_flags;
+    }
+    METHOD(CaptureTheFlag, m_isTwoBaseMode, bool())
+    {
+        return true;
+    }
+    METHOD(CaptureTheFlag, m_setTeams, void(string sa))
+    {
+        cvar_set("fraglimit", sa);
+    }
+#ifdef CSQC
+    ATTRIB(CaptureTheFlag, m_modicons, void(vector pos, vector mySize), HUD_Mod_CTF);
+    ATTRIB(CaptureTheFlag, m_modicons_reset, void(), HUD_Mod_CTF_Reset);
+#endif
+ENDCLASS(CaptureTheFlag)
+REGISTER_GAMETYPE(CTF, NEW(CaptureTheFlag));
 #define g_ctf IS_GAMETYPE(CTF)
 
-REGISTER_GAMETYPE(_("Clan Arena"),ca,g_ca,CA,true,"","timelimit=20 pointlimit=10 teams=2 leadlimit=0",_("Kill all enemy teammates to win the round"))
-{
-    if (!k) {
-        cvar_set("g_ca_teams", cvar_defstring("g_ca_teams"));
-        return true;
+#ifdef CSQC
+void HUD_Mod_CA(vector pos, vector mySize);
+#endif
+CLASS(ClanArena, Gametype)
+    INIT(ClanArena)
+    {
+        this.gametype_init(this, _("Clan Arena"),"ca","g_ca",true,"","timelimit=20 pointlimit=10 teams=2 leadlimit=0",_("Kill all enemy teammates to win the round"));
     }
-    switch (k) {
-        case "teams":
-            cvar_set("g_ca_teams", v);
+    METHOD(ClanArena, m_parse_mapinfo, bool(string k, string v))
+    {
+        if (!k) {
+            cvar_set("g_ca_teams", cvar_defstring("g_ca_teams"));
             return true;
+        }
+        switch (k) {
+            case "teams":
+                cvar_set("g_ca_teams", v);
+                return true;
+        }
+        return false;
     }
-}
+    METHOD(ClanArena, m_isAlwaysSupported, bool(Gametype this, int spawnpoints, float diameter))
+    {
+        if(spawnpoints >= 8 && diameter > 4096)
+            return true;
+        return false;
+    }
+    METHOD(ClanArena, m_setTeams, void(string sa))
+    {
+        cvar_set("g_ca_teams", sa);
+    }
+#ifdef CSQC
+    ATTRIB(ClanArena, m_modicons, void(vector pos, vector mySize), HUD_Mod_CA);
+#endif
+ENDCLASS(ClanArena)
+REGISTER_GAMETYPE(CA, NEW(ClanArena));
 #define g_ca IS_GAMETYPE(CA)
 
-REGISTER_GAMETYPE(_("Domination"),dom,g_domination,DOMINATION,true,"","timelimit=20 pointlimit=200 teams=2 leadlimit=0",_("Capture and defend all the control points to win"))
-{
-    if (!k) {
-        cvar_set("g_domination_default_teams", cvar_defstring("g_domination_default_teams"));
-        return true;
+#ifdef CSQC
+void HUD_Mod_Dom(vector pos, vector mySize);
+#endif
+CLASS(Domination, Gametype)
+    INIT(Domination)
+    {
+        this.gametype_init(this, _("Domination"),"dom","g_domination",true,"","timelimit=20 pointlimit=200 teams=2 leadlimit=0",_("Capture and defend all the control points to win"));
     }
-    switch (k) {
-        case "teams":
-            cvar_set("g_domination_default_teams", v);
+    METHOD(Domination, m_parse_mapinfo, bool(string k, string v))
+    {
+        if (!k) {
+            cvar_set("g_domination_default_teams", cvar_defstring("g_domination_default_teams"));
             return true;
+        }
+        switch (k) {
+            case "teams":
+                cvar_set("g_domination_default_teams", v);
+                return true;
+        }
+        return false;
     }
-}
+    METHOD(Domination, m_generate_mapinfo, void(Gametype this, string v))
+    {
+        if(v == "dom_controlpoint")
+            MapInfo_Map_supportedGametypes |= this.m_flags;
+    }
+#ifdef CSQC
+    ATTRIB(Domination, m_modicons, void(vector pos, vector mySize), HUD_Mod_Dom);
+#endif
+ENDCLASS(Domination)
+REGISTER_GAMETYPE(DOMINATION, NEW(Domination));
 
-REGISTER_GAMETYPE(_("Key Hunt"),kh,g_keyhunt,KEYHUNT,true,"","timelimit=20 pointlimit=1000 teams=3 leadlimit=0",_("Gather all the keys to win the round"))
-{
-    if (!k) {
-       cvar_set("g_keyhunt_teams", cvar_defstring("g_keyhunt_teams"));
-       return true;
+#ifdef CSQC
+void HUD_Mod_KH(vector pos, vector mySize);
+#endif
+CLASS(KeyHunt, Gametype)
+    INIT(KeyHunt)
+    {
+        this.gametype_init(this, _("Key Hunt"),"kh","g_keyhunt",true,"","timelimit=20 pointlimit=1000 teams=3 leadlimit=0",_("Gather all the keys to win the round"));
     }
-    switch (k) {
-        case "teams":
-            cvar_set("g_keyhunt_teams", v);
+    METHOD(KeyHunt, m_parse_mapinfo, bool(string k, string v))
+    {
+        if (!k) {
+            cvar_set("g_keyhunt_teams", cvar_defstring("g_keyhunt_teams"));
             return true;
+        }
+        switch (k) {
+            case "teams":
+                cvar_set("g_keyhunt_teams", v);
+                return true;
+        }
+        return false;
+    }
+    METHOD(KeyHunt, m_isAlwaysSupported, bool(Gametype this, int spawnpoints, float diameter))
+    {
+        if(spawnpoints >= 12 && diameter > 5120)
+            return true;
+        return false;
+    }
+    METHOD(KeyHunt, m_setTeams, void(string sa))
+    {
+        cvar_set("g_keyhunt_teams", sa);
     }
-}
+#ifdef CSQC
+    ATTRIB(KeyHunt, m_modicons, void(vector pos, vector mySize), HUD_Mod_KH);
+#endif
+ENDCLASS(KeyHunt)
+REGISTER_GAMETYPE(KEYHUNT, NEW(KeyHunt));
 
-REGISTER_GAMETYPE(_("Assault"),as,g_assault,ASSAULT,true,"","timelimit=20",_("Destroy obstacles to find and destroy the enemy power core before time runs out"));
+CLASS(Assault, Gametype)
+    INIT(Assault)
+    {
+        this.gametype_init(this, _("Assault"),"as","g_assault",true,"","timelimit=20",_("Destroy obstacles to find and destroy the enemy power core before time runs out"));
+    }
+    METHOD(Assault, m_generate_mapinfo, void(Gametype this, string v))
+    {
+        if(v == "target_assault_roundend")
+            MapInfo_Map_supportedGametypes |= this.m_flags;
+    }
+    METHOD(Assault, m_isTwoBaseMode, bool())
+    {
+        return true;
+    }
+ENDCLASS(Assault)
+REGISTER_GAMETYPE(ASSAULT, NEW(Assault));
 #define g_assault IS_GAMETYPE(ASSAULT)
 
-REGISTER_GAMETYPE(_("Onslaught"),ons,g_onslaught,ONSLAUGHT,true,"","pointlimit=1 timelimit=20",_("Capture control points to reach and destroy the enemy generator"));
+CLASS(Onslaught, Gametype)
+    INIT(Onslaught)
+    {
+        this.gametype_init(this, _("Onslaught"),"ons","g_onslaught",true,"","pointlimit=1 timelimit=20",_("Capture control points to reach and destroy the enemy generator"));
+    }
+    METHOD(Onslaught, m_generate_mapinfo, void(Gametype this, string v))
+    {
+        if(v == "onslaught_generator")
+            MapInfo_Map_supportedGametypes |= this.m_flags;
+    }
+ENDCLASS(Onslaught)
+REGISTER_GAMETYPE(ONSLAUGHT, NEW(Onslaught));
 
-REGISTER_GAMETYPE(_("Nexball"),nb,g_nexball,NEXBALL,true,"","timelimit=20 pointlimit=5 leadlimit=0",_("Shoot and kick the ball into the enemies goal, keep your goal clean"));
+#ifdef CSQC
+void HUD_Mod_NexBall(vector pos, vector mySize);
+#endif
+CLASS(NexBall, Gametype)
+    INIT(NexBall)
+    {
+        this.gametype_init(this, _("Nexball"),"nb","g_nexball",true,"","timelimit=20 pointlimit=5 leadlimit=0",_("Shoot and kick the ball into the enemies goal, keep your goal clean"));
+    }
+    METHOD(NexBall, m_generate_mapinfo, void(Gametype this, string v))
+    {
+        if(substring(v, 0, 8) == "nexball_" || substring(v, 0, 4) == "ball")
+            MapInfo_Map_supportedGametypes |= this.m_flags;
+    }
+    METHOD(NexBall, m_isTwoBaseMode, bool())
+    {
+        return true;
+    }
+#ifdef CSQC
+    ATTRIB(NexBall, m_modicons, void(vector pos, vector mySize), HUD_Mod_NexBall);
+#endif
+ENDCLASS(NexBall)
+REGISTER_GAMETYPE(NEXBALL, NEW(NexBall));
 #define g_nexball IS_GAMETYPE(NEXBALL)
 
-REGISTER_GAMETYPE(_("Freeze Tag"),ft,g_freezetag,FREEZETAG,true,"","timelimit=20 pointlimit=10 teams=2 leadlimit=0",_("Kill enemies to freeze them, stand next to teammates to revive them, freeze the most enemies to win"))
-{
-    if (!k) {
-        cvar_set("g_freezetag_teams", cvar_defstring("g_freezetag_teams"));
-        return true;
+CLASS(FreezeTag, Gametype)
+    INIT(FreezeTag)
+    {
+        this.gametype_init(this, _("Freeze Tag"),"ft","g_freezetag",true,"","timelimit=20 pointlimit=10 teams=2 leadlimit=0",_("Kill enemies to freeze them, stand next to teammates to revive them, freeze the most enemies to win"));
+    }
+    METHOD(FreezeTag, m_parse_mapinfo, bool(string k, string v))
+    {
+        if (!k) {
+            cvar_set("g_freezetag_teams", cvar_defstring("g_freezetag_teams"));
+            return true;
+        }
+        switch (k) {
+            case "teams":
+                cvar_set("g_freezetag_teams", v);
+                return true;
+        }
+        return false;
     }
-    switch (k) {
-        case "teams":
-            cvar_set("g_freezetag_teams", v);
+    METHOD(FreezeTag, m_isAlwaysSupported, bool(Gametype this, int spawnpoints, float diameter))
+    {
+        if(spawnpoints >= 8 && diameter > 4096)
             return true;
+        return false;
+    }
+    METHOD(FreezeTag, m_setTeams, void(string sa))
+    {
+        cvar_set("g_freezetag_teams", sa);
     }
-}
+#ifdef CSQC
+    ATTRIB(FreezeTag, m_modicons, void(vector pos, vector mySize), HUD_Mod_CA);
+#endif
+ENDCLASS(FreezeTag)
+REGISTER_GAMETYPE(FREEZETAG, NEW(FreezeTag));
 #define g_freezetag IS_GAMETYPE(FREEZETAG)
 
-REGISTER_GAMETYPE(_("Keepaway"),ka,g_keepaway,KEEPAWAY,true,"","timelimit=20 pointlimit=30",_("Hold the ball to get points for kills"));
+#ifdef CSQC
+void HUD_Mod_Keepaway(vector pos, vector mySize);
+#endif
+CLASS(Keepaway, Gametype)
+    INIT(Keepaway)
+    {
+        this.gametype_init(this, _("Keepaway"),"ka","g_keepaway",true,"","timelimit=20 pointlimit=30",_("Hold the ball to get points for kills"));
+    }
+    METHOD(Keepaway, m_isAlwaysSupported, bool(Gametype this, int spawnpoints, float diameter))
+    {
+        return true;
+    }
+#ifdef CSQC
+    ATTRIB(Keepaway, m_modicons, void(vector pos, vector mySize), HUD_Mod_Keepaway);
+#endif
+ENDCLASS(Keepaway)
+REGISTER_GAMETYPE(KEEPAWAY, NEW(Keepaway));
 
-REGISTER_GAMETYPE(_("Invasion"),inv,g_invasion,INVASION,false,"","pointlimit=50 teams=0",_("Survive against waves of monsters"))
-{
-    switch (k) {
-        case "teams":
-            cvar_set("g_invasion_teams", v);
-            return true;
+CLASS(Invasion, Gametype)
+    INIT(Invasion)
+    {
+        this.gametype_init(this, _("Invasion"),"inv","g_invasion",false,"","pointlimit=50 teams=0",_("Survive against waves of monsters"));
     }
-}
+    METHOD(Invasion, m_parse_mapinfo, bool(string k, string v))
+    {
+        switch (k) {
+            case "teams":
+                cvar_set("g_invasion_teams", v);
+                return true;
+        }
+        return false;
+    }
+    METHOD(Invasion, m_generate_mapinfo, void(Gametype this, string v))
+    {
+        if(v == "invasion_spawnpoint")
+            MapInfo_Map_supportedGametypes |= this.m_flags;
+    }
+ENDCLASS(Invasion)
+REGISTER_GAMETYPE(INVASION, NEW(Invasion));
 
 const int MAPINFO_FEATURE_WEAPONS       = 1; // not defined for instagib-only maps
 const int MAPINFO_FEATURE_VEHICLES      = 2;
@@ -197,30 +494,17 @@ const int MAPINFO_FLAG_NOAUTOMAPLIST    = 8; // do not include when automaticall
 
 float MapInfo_count;
 
-// info about a map that MapInfo loads
-string MapInfo_Map_bspname;
-string MapInfo_Map_title;
-string MapInfo_Map_titlestring; // either bspname: title or just title, depending on whether bspname is redundant
-string MapInfo_Map_description;
-string MapInfo_Map_author;
-string MapInfo_Map_clientstuff; // not in cache, only for map load
-string MapInfo_Map_fog; // not in cache, only for map load
-int MapInfo_Map_supportedGametypes;
-int MapInfo_Map_supportedFeatures;
-int MapInfo_Map_flags;
-vector MapInfo_Map_mins; // these are '0 0 0' if not supported!
-vector MapInfo_Map_maxs; // these are '0 0 0' if not specified!
-
 // load MapInfo_count; generate mapinfo for maps that miss them, and clear the
 // cache; you need to call MapInfo_FilterGametype afterwards!
 void MapInfo_Enumerate();
 
 // filter the info by game type mask (updates MapInfo_count)
 float MapInfo_progress;
-float MapInfo_FilterGametype(float gametype, float features, float pFlagsRequired, float pFlagsForbidden, float pAbortOnGenerate); // 1 on success, 0 on temporary failure (call it again next frame then; use MapInfo_progress as progress indicator)
+float MapInfo_FilterGametype(Gametype gametypeFlags, float features, float pFlagsRequired, float pFlagsForbidden, float pAbortOnGenerate); // 1 on success, 0 on temporary failure (call it again next frame then; use MapInfo_progress as progress indicator)
+float _MapInfo_FilterGametype(int gametypeFlags, float features, float pFlagsRequired, float pFlagsForbidden, float pAbortOnGenerate); // 1 on success, 0 on temporary failure (call it again next frame then; use MapInfo_progress as progress indicator)
 void MapInfo_FilterString(string sf); // filter _MapInfo_filtered (created by MapInfo_FilterGametype) with keyword
 int MapInfo_CurrentFeatures(); // retrieves currently required features from cvars
-int MapInfo_CurrentGametype(); // retrieves current gametype from cvars
+Gametype MapInfo_CurrentGametype(); // retrieves current gametype from cvars
 int MapInfo_ForbiddenFlags(); // retrieves current flags from cvars
 int MapInfo_RequiredFlags(); // retrieves current flags from cvars
 
@@ -229,7 +513,7 @@ float MapInfo_Get_ByID(float i); // 1 on success, 0 on failure
 string MapInfo_BSPName_ByID(float i);
 
 // load info about a map by name into the MapInfo_Map_* globals
-float MapInfo_Get_ByName(string s, float allowGenerate, float gametypeToSet); // 1 on success, 0 on failure, 2 if it autogenerated a mapinfo file
+int MapInfo_Get_ByName(string s, float allowGenerate, Gametype gametypeToSet); // 1 on success, 0 on failure, 2 if it autogenerated a mapinfo file
 
 // look for a map by a prefix, returns the actual map name on success, string_null on failure or ambigous match
 string MapInfo_FindName_match; // the name of the map that was found
@@ -242,23 +526,22 @@ float MapInfo_CheckMap(string s); // returns 0 if the map can't be played with t
 void MapInfo_LoadMap(string s, float reinit);
 
 // list all maps for the current game type
-string MapInfo_ListAllowedMaps(float type, float pFlagsRequired, float pFlagsForbidden);
+string MapInfo_ListAllowedMaps(Gametype type, float pFlagsRequired, float pFlagsForbidden);
 // list all allowed maps (for any game type)
 string MapInfo_ListAllAllowedMaps(float pFlagsRequired, float pFlagsForbidden);
 
 // gets a gametype from a string
-string _MapInfo_GetDefaultEx(float t);
-float _MapInfo_GetTeamPlayBool(float t);
-Gametype MapInfo_Type(int t);
-float MapInfo_Type_FromString(string t);
-string MapInfo_Type_Description(float t);
-string MapInfo_Type_ToString(float t);
-string MapInfo_Type_ToText(float t);
-void MapInfo_SwitchGameType(int t);
+string _MapInfo_GetDefaultEx(Gametype t);
+float _MapInfo_GetTeamPlayBool(Gametype t);
+Gametype MapInfo_Type_FromString(string t);
+string MapInfo_Type_Description(Gametype t);
+string MapInfo_Type_ToString(Gametype t);
+string MapInfo_Type_ToText(Gametype t);
+void MapInfo_SwitchGameType(Gametype t);
 
 // to be called from worldspawn to set up cvars
 void MapInfo_LoadMapSettings(string s);
-float MapInfo_LoadedGametype; // game type that was active during map load
+Gametype MapInfo_LoadedGametype; // game type that was active during map load
 
 void MapInfo_Cache_Destroy(); // disable caching
 void MapInfo_Cache_Create(); // enable caching
@@ -270,4 +553,3 @@ void MapInfo_Shutdown(); // call this in the shutdown handler
 
 #define MAPINFO_SETTEMP_ACL_USER cvar_string("g_mapinfo_settemp_acl")
 #define MAPINFO_SETTEMP_ACL_SYSTEM "-g_mapinfo_* -rcon_* -_* -g_ban* +*"
-#endif
index 1aa748faab08c38ebc7955b3a12c88f4475c3ab2..42f8c514e9bf0166a53bbfdc7c0cad5ccec2f5d9 100644 (file)
@@ -74,8 +74,8 @@ MINIGAME_SIMPLELINKED_ENTITIES
 
 void minigame_autoclean_entity(entity e)
 {
-       LOG_DEBUG("CL Auto-cleaned: ",ftos(etof(e)), " (",e.classname,")\n");
-       remove(e);
+       LOG_DEBUG("CL Auto-cleaned: ",ftos(etof(e)), " (",e.classname,")");
+       delete(e);
 }
 
 void HUD_MinigameMenu_CurrentButton();
@@ -121,7 +121,7 @@ void activate_minigame(entity minigame)
 
        if ( !minigame.descriptor || minigame.classname != "minigame" )
        {
-               LOG_TRACE("Trying to activate unregistered minigame ",minigame.netname," in client\n");
+               LOG_TRACE("Trying to activate unregistered minigame ",minigame.netname," in client");
                return;
        }
 
@@ -174,7 +174,7 @@ void minigame_read_owner(entity this)
                this.owner = find(this.owner,netname,owner_name);
        while ( this.owner && this.owner.classname != "minigame" );
        if ( !this.owner )
-               LOG_TRACE("Got a minigame entity without a minigame!\n");
+               LOG_TRACE("Got a minigame entity without a minigame!");
 }
 NET_HANDLE(ENT_CLIENT_MINIGAME, bool isnew)
 {
@@ -196,7 +196,7 @@ NET_HANDLE(ENT_CLIENT_MINIGAME, bool isnew)
                        this.entremove = minigame_entremove;
                        this.descriptor = minigame_get_descriptor(ReadString_Raw());
                        if ( !this.descriptor )
-                               LOG_TRACE("Got a minigame without a client-side descriptor!\n");
+                               LOG_TRACE("Got a minigame without a client-side descriptor!");
                        else
                                this.minigame_event = this.descriptor.minigame_event;
                }
@@ -212,7 +212,7 @@ NET_HANDLE(ENT_CLIENT_MINIGAME, bool isnew)
                        minigame_read_owner(this);
                        float ent = ReadLong();
                        this.minigame_playerslot = ent;
-                       LOG_DEBUG("Player: ",entcs_GetName(ent-1),"\n");
+                       LOG_DEBUG("Player: ",entcs_GetName(ent-1));
 
                        activate = (ent == player_localnum+1 && this.owner && this.owner != active_minigame);
 
@@ -238,7 +238,7 @@ NET_HANDLE(ENT_CLIENT_MINIGAME, bool isnew)
        {
                LOG_DEBUG("CL Reading entity: ",ftos(etof(this)),
                        " classname:",this.classname," enttype:",ftos(this.enttype) );
-               LOG_DEBUG(" sf:",ftos(sf)," netname:",this.netname,"\n\n");
+               LOG_DEBUG(" sf:",ftos(sf)," netname:",this.netname);
        }
        return true;
 }
index cc24d4bf0c69256717525a81ced1e28360ac5941..602c7973585c1510e3903b4d6fe1d5d6d696ebaa 100644 (file)
@@ -1,5 +1,4 @@
-#ifndef CL_MINIGAMES_H
-#define CL_MINIGAMES_H
+#pragma once
 
 // Get a square in the center of the avaliable area
 // \note macro to pass by reference pos and mySize
@@ -128,5 +127,3 @@ REGISTRY_CHECK(Minigames)
                this.minigame_event = name##_client_event; \
     } \
     REGISTER_INIT(MINIGAME_##name)
-
-#endif
index c26109bfd39e488179eddba303a3d5f5b974aac2..90f1b2252ec2c816bea0c566a63725be73424891 100644 (file)
@@ -143,7 +143,7 @@ void HUD_MinigameMenu_EraseEntry ( entity e )
        if ( HUD_MinigameMenu_activeitem == e )
                HUD_MinigameMenu_activeitem = NULL;
 
-       remove(e);
+       delete(e);
 }
 
 // Minigame menu options: create entry
@@ -193,7 +193,7 @@ bool HUD_MinigameMenu_Click_ExpandCollapse(entity this)
                        if ( e.flags & 2 )
                                HUD_MinigameMenu_Click(e);
                        this.list_next = e.list_next;
-                       remove(e);
+                       delete(e);
                }
                if ( this.list_next )
                        this.list_next.list_prev = this;
@@ -351,7 +351,7 @@ void HUD_MinigameMenu_Close(entity this, entity actor, entity trigger)
                for ( e = HUD_MinigameMenu_entries; e != NULL; e = p )
                {
                        p = e.list_next;
-                       remove(e);
+                       delete(e);
                }
                HUD_MinigameMenu_entries = NULL;
                HUD_MinigameMenu_last_entry = NULL;
index f170c590dea2037745df88de968f9c5ca75ad092..ef44ea025f5633635496415635e9ce6665293075 100644 (file)
@@ -1,7 +1,4 @@
-#ifndef CL_MINIGAMES_HUD_H
-#define CL_MINIGAMES_HUD_H
+#pragma once
 
 float HUD_Minigame_InputEvent(float bInputType, float nPrimary, float nSecondary);
 void HUD_Minigame_Mouse();
-
-#endif
index db25c2959e02470d85a6b5d3b23b022f24488d6a..041e56339c3039be7f7207c642510a7638202951 100644 (file)
@@ -259,7 +259,7 @@ void bd_editor_place(entity minigame, entity player, string pos, int thetile, st
                                        return; // how?!
 
                                if(piece.netname) { strunzone(piece.netname); }
-                               remove(piece);
+                               delete(piece);
                                minigame_server_sendflags(minigame,MINIG_SF_UPDATE);
                                return;
                        }
@@ -313,12 +313,12 @@ void bd_unfill_recurse(entity minigame, entity player, int thetype, int letter,
        if(targ && thetype == targ.bd_tiletype)
        {
                if(targ.netname) { strunzone(targ.netname); }
-               remove(targ);
+               delete(targ);
        }
        else if(piece && thetype == piece.bd_tiletype)
        {
                if(piece.netname) { strunzone(piece.netname); }
-               remove(piece);
+               delete(piece);
        }
        else return;
 
@@ -393,7 +393,7 @@ void bd_setup_pieces(entity minigame)
                if(e.classname == "minigame_board_piece")
                {
                        if(e.netname) { strunzone(e.netname); }
-                       remove(e);
+                       delete(e);
                }
 
        bd_load_level(minigame);
@@ -631,7 +631,7 @@ int bd_server_event(entity minigame, string event, ...)
                        if(e.classname == "minigame_board_piece")
                        {
                                if(e.netname) { strunzone(e.netname); }
-                               remove(e);
+                               delete(e);
                        }
 
                        if(minigame.bd_nextlevel) { strunzone(minigame.bd_nextlevel); }
index 3c2beacb6fc20c3f1e0c87ecfbb93cab7ff41e39..497ef2afc394d24bbe2a46ee0292a94ff0941e11 100644 (file)
@@ -201,7 +201,7 @@ int c4_server_event(entity minigame, string event, ...)
                        if(e.classname == "minigame_board_piece")
                        {
                                if(e.netname) { strunzone(e.netname); }
-                               remove(e);
+                               delete(e);
                        }
                        return false;
                }
index 8f8e3da2eab0719526230920994af4c81407a1e3..78fb30f1df65b4bfc40cf6921d33a25316b97d89 100644 (file)
@@ -123,7 +123,7 @@ void nmm_kill_tiles(entity minig)
                        strunzone(e.netname);
                        strunzone(e.nmm_tile_hmill);
                        strunzone(e.nmm_tile_vmill);
-                       remove(e);
+                       delete(e);
                }
 }
 
@@ -369,7 +369,7 @@ int nmm_server_event(entity minigame, string event, ...)
                                minigame.SendFlags |= MINIG_SF_UPDATE;
                        }
                        else
-                               LOG_TRACE("Invalid move: ",...(2,string),"\n");
+                               LOG_TRACE("Invalid move: ", ...(2, string));
                        return 1;
                }
        }
index 602cad22d3d103b277ec0d3d00369e6943d15678..d535b8c85dca031a59c460d118aee7838f001c66 100644 (file)
@@ -442,8 +442,8 @@ int pong_server_event(entity minigame, string event, ...)
                                                                paddle.realowner.classname == "pong_ai" )
                                                        {
                                                                minigame.pong_paddles[i] = NULL;
-                                                               remove(paddle.realowner);
-                                                               remove(paddle);
+                                                               delete(paddle.realowner);
+                                                               delete(paddle);
                                                                return true;
                                                        }
                                                }
index 7d4048d61b58bcd2de5c21520286fb6ec3105a31..f9e0f79b9a92c29459333113448238a826764404 100644 (file)
@@ -121,7 +121,7 @@ void pp_move(entity minigame, entity player, string pos )
                        if(existing)
                        {
                                if(existing.netname) { strunzone(existing.netname); }
-                               remove(existing);
+                               delete(existing);
                        }
 
                        entity piece = msle_spawn(minigame,"minigame_board_piece");
@@ -186,7 +186,7 @@ void pp_next_match(entity minigame, entity player)
                entity e = NULL;
                while ( ( e = findentity(e,owner,minigame) ) )
                        if ( e.classname == "minigame_board_piece" )
-                               remove(e);
+                               delete(e);
                minigame.pp_team1_score = 0;
                minigame.pp_team2_score = 0;
 
@@ -215,7 +215,7 @@ int pp_server_event(entity minigame, string event, ...)
                        if(e.classname == "minigame_board_piece")
                        {
                                if(e.netname) { strunzone(e.netname); }
-                               remove(e);
+                               delete(e);
                        }
                        return false;
                }
index 2a612c599a8317acdbd846d5505c1dded4a9ed81..c9ef8bd67a4ae9fad1bed23776646f2485b1bad1 100644 (file)
@@ -139,7 +139,7 @@ bool ps_move_piece(entity minigame, entity piece, string pos, int leti, int numb
                return false;
 
        if(middle.netname) { strunzone(middle.netname); }
-       remove(middle);
+       delete(middle);
 
        if(piece.netname) { strunzone(piece.netname); }
        piece.netname = strzone(pos);
@@ -232,7 +232,7 @@ int ps_server_event(entity minigame, string event, ...)
                        if(e.classname == "minigame_board_piece")
                        {
                                if(e.netname) { strunzone(e.netname); }
-                               remove(e);
+                               delete(e);
                        }
                        return false;
                }
index 617ed957ca635f84081282dbeee62f664fb67ea9..4248d589a13391c0f6218d518a155f0cf5727556 100644 (file)
@@ -287,7 +287,7 @@ void snake_eat_team(entity minigame, int pteam)
                if ( e.classname == "minigame_board_piece" && e.cnt && e.team == pteam )
                {
                        if(e.netname) { strunzone(e.netname); }
-                       remove(e);
+                       delete(e);
                }
 
        if(minigame.snake_lives[pteam] <= 0)
@@ -354,7 +354,7 @@ void snake_move_head(entity minigame, entity head)
        if(ate_mouse)
        {
                if(hit.netname) { strunzone(hit.netname); }
-               remove(hit);
+               delete(hit);
 
                snake_new_mouse(minigame);
        }
@@ -425,7 +425,7 @@ int snake_server_event(entity minigame, string event, ...)
                        if(e.classname == "minigame_board_piece")
                        {
                                if(e.netname) { strunzone(e.netname); }
-                               remove(e);
+                               delete(e);
                        }
                        return false;
                }
index b5248467f5908d8aca373cca211c87cc6f204726..9c0ece163343e840075cb463f79086113ba90e49 100644 (file)
@@ -123,7 +123,7 @@ void ttt_next_match(entity minigame, entity player)
                entity e = NULL;
                while ( ( e = findentity(e,owner,minigame) ) )
                        if ( e.classname == "minigame_board_piece" )
-                               remove(e);
+                               delete(e);
        }
 }
 
@@ -147,7 +147,7 @@ int ttt_server_event(entity minigame, string event, ...)
                        if(e.classname == "minigame_board_piece")
                        {
                                if(e.netname) { strunzone(e.netname); }
-                               remove(e);
+                               delete(e);
                        }
                        return false;
                }
@@ -421,7 +421,7 @@ int ttt_ai_random(int piecemask)
                f <<= 1;
        }
 
-       LOG_TRACE(sprintf("TTT AI: selected %x from %x\n",
+       LOG_TRACE(sprintf("TTT AI: selected %x from %x",
                        RandomSelection_chosen_float, piecemask) );
        return RandomSelection_chosen_float;
 }
@@ -439,7 +439,7 @@ int ttt_ai_block3 ( int piecemask, int piecemask_free )
        r |= ttt_ai_1of3(piecemask,TTT_AI_POSFLAG_A3,TTT_AI_POSFLAG_B3,TTT_AI_POSFLAG_C3);
        r |= ttt_ai_1of3(piecemask,TTT_AI_POSFLAG_A1,TTT_AI_POSFLAG_B2,TTT_AI_POSFLAG_C3);
        r |= ttt_ai_1of3(piecemask,TTT_AI_POSFLAG_A3,TTT_AI_POSFLAG_B2,TTT_AI_POSFLAG_C1);
-       LOG_TRACE(sprintf("TTT AI: possible 3 in a rows in %x: %x (%x)\n",piecemask,r, r&piecemask_free));
+       LOG_TRACE(sprintf("TTT AI: possible 3 in a rows in %x: %x (%x)",piecemask,r, r&piecemask_free));
        r &= piecemask_free;
        return ttt_ai_random(r);
 }
@@ -452,15 +452,15 @@ string ttt_ai_choose_simple(int piecemask_self, int piecemask_opponent, int piec
 {
        int move = 0;
 
-       LOG_TRACE("TTT AI: checking winning move\n");
+       LOG_TRACE("TTT AI: checking winning move");
        if (( move = ttt_ai_block3(piecemask_self,piecemask_free) ))
                return ttt_ai_piece_flag2pos(move); // place winning move
 
-       LOG_TRACE("TTT AI: checking opponent's winning move\n");
+       LOG_TRACE("TTT AI: checking opponent's winning move");
        if (( move = ttt_ai_block3(piecemask_opponent,piecemask_free) ))
                return ttt_ai_piece_flag2pos(move); // block opponent
 
-       LOG_TRACE("TTT AI: random move\n");
+       LOG_TRACE("TTT AI: random move");
        return ttt_ai_piece_flag2pos(ttt_ai_random(piecemask_free));
 }
 
@@ -510,12 +510,12 @@ void ttt_aimove(entity minigame)
                }
 
                // TODO multiple AI difficulties
-               LOG_TRACE(sprintf("TTT AI: self: %x opponent: %x free: %x\n",
+               LOG_TRACE(sprintf("TTT AI: self: %x opponent: %x free: %x",
                                piecemask_self, piecemask_opponent, piecemask_free));
                pos = ttt_ai_choose_simple(piecemask_self, piecemask_opponent, piecemask_free);
-               LOG_TRACE("TTT AI: chosen move: ",pos,"\n\n");
+               LOG_TRACE("TTT AI: chosen move: ", pos);
                if ( !pos )
-                       LOG_TRACE("Tic Tac Toe AI has derped!\n");
+                       LOG_TRACE("Tic Tac Toe AI has derped!");
                else
                        ttt_move(minigame,aiplayer,pos);
        }
index 7425149f389d9b484c38d089ebef97c2b750f6df..284001a0a22e97997b107a386601d9f75207345f 100644 (file)
@@ -1,5 +1,4 @@
-#ifndef MINIGAMES_H
-#define MINIGAMES_H
+#pragma once
 
 // previous node in a doubly linked list
 .entity list_prev;
@@ -121,5 +120,3 @@ entity msle_spawn(entity minigame_session, string class_name);
 
 int msle_id(string class_name);
 string msle_classname(int id);
-
-#endif
index 0d0efb05dcdf0b201b00191371b8cbb79d7bc9ac..da04340a63c3bcbc21c8ed6d7f7a9f60aa6565eb 100644 (file)
@@ -27,7 +27,7 @@ void minigame_rmplayer(entity minigame_session, entity player)
                GameLogEcho(strcat(":minigame:part:",minigame_session.netname,":",
                        ftos(etof(player)),":",player.netname));
                minigame_session.minigame_players = p.list_next;
-               remove ( p );
+               delete ( p );
                player_clear_minigame(player);
        }
        else
@@ -40,7 +40,7 @@ void minigame_rmplayer(entity minigame_session, entity player)
                                GameLogEcho(strcat(":minigame:part:",minigame_session.netname,":",
                                        ftos(etof(player)),":",player.netname));
                                p.list_next = e.list_next;
-                               remove(e);
+                               delete(e);
                                player_clear_minigame(player);
                                return;
                        }
@@ -153,7 +153,7 @@ int minigame_addplayer(entity minigame_session, entity player)
 
                minigame_resend(minigame_session);
        }
-       else { remove(player_pointer); }
+       else { delete(player_pointer); }
        GameLogEcho(strcat(":minigame:join",(mgteam?"":"fail"),":",minigame_session.netname,":",
                ftos(etof(player)),":",player.netname));
 
@@ -176,7 +176,7 @@ entity start_minigame(entity player, string minigame )
                GameLogEcho(strcat(":minigame:start:",minig.netname));
                if ( ! minigame_addplayer(minig,player) )
                {
-                       LOG_TRACE("Minigame ",minig.netname," rejected the first player join!\n");
+                       LOG_TRACE("Minigame ",minig.netname," rejected the first player join!");
                        end_minigame(minig);
                        return NULL;
                }
@@ -235,8 +235,8 @@ void end_minigame(entity minigame_session)
        while( (e = findentity(e, owner, minigame_session)) )
                if ( e.minigame_autoclean )
                {
-                       LOG_TRACE("SV Auto-cleaned: ",ftos(etof(e)), " (",e.classname,")\n");
-                       remove(e);
+                       LOG_TRACE("SV Auto-cleaned: ",ftos(etof(e)), " (",e.classname,")");
+                       delete(e);
                }
 
        entity p;
@@ -244,11 +244,11 @@ void end_minigame(entity minigame_session)
        {
                p = e.list_next;
                player_clear_minigame(e.minigame_players);
-               remove(e);
+               delete(e);
        }
 
        strunzone(minigame_session.netname);
-       remove(minigame_session);
+       delete(minigame_session);
 }
 
 void end_minigames()
index de9e3f69610d41b3a42b3eeb5ac1fffc01c99914..b5015a1f40fd3e452d83ce2d23ed5a510ce63c4c 100644 (file)
@@ -1,5 +1,4 @@
-#ifndef SV_MINIGAMES_H
-#define SV_MINIGAMES_H
+#pragma once
 
 /// Create a new minigame session
 /// \return minigame session entity
@@ -59,5 +58,3 @@ REGISTRY_CHECK(Minigames)
                this.minigame_event = name##_server_event; \
     } \
     REGISTER_INIT(MINIGAME_##name)
-
-#endif
index f3bfd64c7532a833757eed9545782933b72272aa..ce98629411fd0cd6c3ce798a813acf5dd0fd602f 100644 (file)
@@ -1,5 +1,4 @@
-#ifndef MODELS_ALL_H
-#define MODELS_ALL_H
+#pragma once
 
 #include "model.qh"
 
@@ -22,5 +21,3 @@ PRECACHE(Models) {
 
 MODEL(Null, "null");
 #include "all.inc"
-
-#endif
index 91fb278ae0a5ec975c1580d4f7e023f8b96793e2..7a1e7d73c2a471c802a1cf496d9a68e15c0d49e9 100644 (file)
@@ -1,11 +1,10 @@
-#ifndef MODEL_H
-#define MODEL_H
+#pragma once
 
 #define setmodel(e, m) _setmodel((e), (m).model_str())
 
 CLASS(Model, Object)
-    ATTRIB(Model, m_id, int, 0)
-    ATTRIB(Model, model_str, string(), func_null)
+    ATTRIB(Model, m_id, int, 0);
+    ATTRIB(Model, model_str, string());
     CONSTRUCTOR(Model, string() path)
     {
         CONSTRUCT(Model);
@@ -16,12 +15,10 @@ CLASS(Model, Object)
         TC(Model, this);
         string s = this.model_str();
         if (s != "" && s != "null" && !fexists(s)) {
-            LOG_WARNINGF("Missing model: \"%s\"\n", s);
+            LOG_WARNF("Missing model: \"%s\"", s);
             return;
         }
-        profile(sprintf("precache_model(\"%s\")\n", s));
+        profile(sprintf("precache_model(\"%s\")", s));
         precache_model(s);
     }
 ENDCLASS(Model)
-
-#endif
index 1e23f3287940218b3c8a882033d3f12b42c88fd2..84f7a0d78f6d19d4121334681655c170e19f2569 100644 (file)
@@ -1,5 +1,4 @@
-#ifndef MONSTERS_ALL_H
-#define MONSTERS_ALL_H
+#pragma once
 
 #include "monster.qh"
 
@@ -18,5 +17,3 @@ REGISTER_MONSTER(Null, NEW(Monster));
 
 
 #include "monster/_mod.inc"
-
-#endif
index de24caa01a2ded2092bfd8689b2a4924f849fe4d..5187c7f56b17f576771778ff3f2a7b0652b0bde2 100644 (file)
@@ -1,10 +1,9 @@
-#ifndef MONSTER_H
-#define MONSTER_H
+#pragma once
 
 #ifdef SVQC
 #include "sv_monsters.qh"
 #include <server/g_damage.qh>
-#include <server/bot/bot.qh>
+#include <server/bot/api.qh>
 #include <server/weapons/common.qh>
 #include <server/weapons/tracing.qh>
 #include <server/weapons/weaponsystem.qh>
@@ -46,19 +45,19 @@ const int MONSTER_SIZE_QUAKE = 8192;
 .vector anim_spawn;
 
 CLASS(Monster, Object)
-    ATTRIB(Monster, monsterid, int, 0)
+    ATTRIB(Monster, monsterid, int, 0);
     /** attributes */
-    ATTRIB(Monster, spawnflags, int, 0)
+    ATTRIB(Monster, spawnflags, int, 0);
     /** human readable name */
-    ATTRIB(Monster, monster_name, string, "Monster")
+    ATTRIB(Monster, monster_name, string, "Monster");
     /** short name */
-    ATTRIB(Monster, netname, string, "")
+    ATTRIB(Monster, netname, string, "");
     /** model */
-    ATTRIB(Monster, m_model, entity, NULL)
+    ATTRIB(Monster, m_model, entity);
     /** hitbox size */
-    ATTRIB(Monster, mins, vector, '-0 -0 -0')
+    ATTRIB(Monster, mins, vector, '-0 -0 -0');
     /** hitbox size */
-    ATTRIB(Monster, maxs, vector, '0 0 0')
+    ATTRIB(Monster, maxs, vector, '0 0 0');
 
     /** (SERVER) setup monster data */
     METHOD(Monster, mr_setup, bool(Monster this, entity actor)) { TC(Monster, this); return false; }
@@ -74,5 +73,3 @@ CLASS(Monster, Object)
     METHOD(Monster, mr_anim, bool(Monster this, entity actor)) { TC(Monster, this); return false; }
 
 ENDCLASS(Monster)
-
-#endif
index 65c82ab37dbaaeb7216c1118e259ccecead06470..509fa0aca11bc6cfdc277af9c14f545d081e13ce 100644 (file)
@@ -49,7 +49,7 @@ METHOD(MageSpike, wr_think, void(MageSpike thiswep, entity actor, .entity weapon
     if (!IS_PLAYER(actor) || weapon_prepareattack(thiswep, actor, weaponentity, false, 0.2)) {
         if (!actor.target_range) actor.target_range = autocvar_g_monsters_target_range;
         actor.enemy = Monster_FindTarget(actor);
-        W_SetupShot_Dir(actor, v_forward, false, 0, SND_MageSpike_FIRE, CH_WEAPON_B, 0);
+        W_SetupShot_Dir(actor, weaponentity, v_forward, false, 0, SND_MageSpike_FIRE, CH_WEAPON_B, 0);
        if (!IS_PLAYER(actor)) w_shotdir = normalize((actor.enemy.origin + '0 0 10') - actor.origin);
         M_Mage_Attack_Spike(actor, w_shotdir);
         weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, 0, w_ready);
@@ -157,7 +157,7 @@ void M_Mage_Attack_Spike_Explode(entity this, entity directhitentity)
        Send_Effect(EFFECT_EXPLOSION_SMALL, this.origin, '0 0 0', 1);
        RadiusDamage (this, this.realowner, (autocvar_g_monster_mage_attack_spike_damage), (autocvar_g_monster_mage_attack_spike_damage) * 0.5, (autocvar_g_monster_mage_attack_spike_radius), NULL, NULL, 0, DEATH_MONSTER_MAGE.m_id, directhitentity);
 
-       remove (this);
+       delete (this);
 }
 
 void M_Mage_Attack_Spike_Touch(entity this, entity toucher)
@@ -235,6 +235,7 @@ void M_Mage_Attack_Spike(entity this, vector dir)
        missile.solid = SOLID_BBOX;
        set_movetype(missile, MOVETYPE_FLYMISSILE);
        missile.flags = FL_PROJECTILE;
+       IL_PUSH(g_projectiles, missile);
        setorigin(missile, this.origin + v_forward * 14 + '0 0 30' + v_right * -14);
        setsize(missile, '0 0 0', '0 0 0');
        missile.velocity = dir * 400;
index afbb954c0b3590f7f42925b7525570ddb8e7256e..eb615fb55483d7e5665fe7f698d8472acbb206dd 100644 (file)
@@ -91,7 +91,7 @@ void M_Shambler_Attack_Lightning_Explode(entity this, entity directhitentity)
        if(this.move_movetype == MOVETYPE_NONE)
                this.velocity = this.oldvelocity;
 
-       RadiusDamage (this, this.realowner, (autocvar_g_monster_shambler_attack_lightning_damage), (autocvar_g_monster_shambler_attack_lightning_damage), (autocvar_g_monster_shambler_attack_lightning_radius), 
+       RadiusDamage (this, this.realowner, (autocvar_g_monster_shambler_attack_lightning_damage), (autocvar_g_monster_shambler_attack_lightning_damage), (autocvar_g_monster_shambler_attack_lightning_radius),
                                        NULL, NULL, (autocvar_g_monster_shambler_attack_lightning_force), this.projectiledeathtype, directhitentity);
 
        FOREACH_ENTITY_RADIUS(this.origin, autocvar_g_monster_shambler_attack_lightning_radius_zap, it != this.realowner && it.takedamage,
@@ -173,6 +173,7 @@ void M_Shambler_Attack_Lightning(entity this)
 
        gren.angles = vectoangles (gren.velocity);
        gren.flags = FL_PROJECTILE;
+       IL_PUSH(g_projectiles, gren);
 
        CSQCProjectile(gren, true, PROJECTILE_SHAMBLER_LIGHTNING, true);
 }
index c7ffece15158c36af25677639988bdb42d2bf7be..9fa73508c1bcb4327d2ad7067a7e066cc5b365b9 100644 (file)
@@ -106,7 +106,7 @@ METHOD(SpiderAttack, wr_think, void(SpiderAttack thiswep, entity actor, .entity
                        actor.anim_finished = time + 1;
                }
         if (isPlayer) actor.enemy = Monster_FindTarget(actor);
-        W_SetupShot_Dir(actor, v_forward, false, 0, SND_SpiderAttack_FIRE, CH_WEAPON_B, 0);
+        W_SetupShot_Dir(actor, weaponentity, v_forward, false, 0, SND_SpiderAttack_FIRE, CH_WEAPON_B, 0);
        if (!isPlayer) w_shotdir = normalize((actor.enemy.origin + '0 0 10') - actor.origin);
                M_Spider_Attack_Web(actor);
         weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, 0, w_ready);
@@ -148,7 +148,7 @@ void M_Spider_Attack_Web_Explode(entity this)
                        it.spider_slowness = time + (autocvar_g_monster_spider_attack_web_damagetime);
                });
 
-               remove(this);
+               delete(this);
        }
 }
 
@@ -194,6 +194,7 @@ void M_Spider_Attack_Web(entity this)
        proj.health = 500;
        proj.event_damage = func_null;
        proj.flags = FL_PROJECTILE;
+       IL_PUSH(g_projectiles, proj);
        proj.damagedbycontents = true;
 
        proj.bouncefactor = 0.3;
index 53d08effa84a0e387dd3ebec1dac8911aacf3c48..33a3c445991c274ed87a520d4d326afb4850eabe 100644 (file)
@@ -54,7 +54,7 @@ METHOD(WyvernAttack, wr_think, void(WyvernAttack thiswep, entity actor, .entity
     TC(WyvernAttack, thiswep);
     if (fire & 1)
     if (time > actor.attack_finished_single[0] || weapon_prepareattack(thiswep, actor, weaponentity, false, 1.2)) {
-        if (IS_PLAYER(actor)) W_SetupShot_Dir(actor, v_forward, false, 0, SND_WyvernAttack_FIRE, CH_WEAPON_B, 0);
+        if (IS_PLAYER(actor)) W_SetupShot_Dir(actor, weaponentity, v_forward, false, 0, SND_WyvernAttack_FIRE, CH_WEAPON_B, 0);
                if (IS_MONSTER(actor)) {
                        actor.attack_finished_single[0] = time + 1.2;
                        actor.anim_finished = time + 1.2;
@@ -69,6 +69,7 @@ METHOD(WyvernAttack, wr_think, void(WyvernAttack thiswep, entity actor, .entity
                setsize(missile, '-6 -6 -6', '6 6 6');
                setorigin(missile, actor.origin + actor.view_ofs + v_forward * 14);
                missile.flags = FL_PROJECTILE;
+        IL_PUSH(g_projectiles, missile);
                missile.velocity = w_shotdir * (autocvar_g_monster_wyvern_attack_fireball_speed);
                missile.avelocity = '300 300 300';
                missile.nextthink = time + 5;
@@ -113,7 +114,7 @@ void M_Wyvern_Attack_Fireball_Explode(entity this)
                        Fire_AddDamage(it, own, 5 * MONSTER_SKILLMOD(own), autocvar_g_monster_wyvern_attack_fireball_damagetime, this.projectiledeathtype);
        });
 
-       remove(this);
+       delete(this);
 }
 
 void M_Wyvern_Attack_Fireball_Touch(entity this, entity toucher)
index 2ebdcc54e80dadee46142c9435e10007147f9b05..0aba5c19d4326f2220c89c576468d022263be4f3 100644 (file)
@@ -1,5 +1,3 @@
-#ifndef SPAWN_H
-#define SPAWN_H
+#pragma once
 
 entity spawnmonster (string monster, float monster_id, entity spawnedby, entity own, vector orig, float respwn, float invincible, float moveflag);
-#endif
index 60c2777ca7bd12b5774f953999a0dad99b729687..ea46be5f12e7343152b8920cc2f7089d9f6253bf 100644 (file)
@@ -247,7 +247,7 @@ void Monster_Sound_Precache(string f)
        {
                if(tokenize_console(s) != 3)
                {
-                       LOG_TRACE("Invalid sound info line: ", s, "\n");
+                       LOG_TRACE("Invalid sound info line: ", s);
                        continue;
                }
                PrecacheGlobalSound(strcat(argv(1), " ", argv(2)));
@@ -302,7 +302,7 @@ bool Monster_Sounds_Load(entity this, string f, int first)
        fh = fopen(f, FILE_READ);
        if(fh < 0)
        {
-               LOG_TRACE("Monster sound file not found: ", f, "\n");
+               LOG_TRACE("Monster sound file not found: ", f);
                return false;
        }
        while((s = fgets(fh)))
@@ -685,6 +685,8 @@ void Monster_CalculateVelocity(entity this, vector to, vector from, float turnra
        //this.angles = vectoangles(this.velocity);
 }
 
+.entity draggedby;
+
 void Monster_Move(entity this, float runspeed, float walkspeed, float stpspeed)
 {
        if(this.target2) { this.goalentity = find(NULL, targetname, this.target2); }
@@ -897,16 +899,20 @@ void Monster_Remove(entity this)
        if(IS_CLIENT(this))
                return; // don't remove it?
 
-       .entity weaponentity = weaponentities[0];
        if(!this) { return; }
 
        if(!MUTATOR_CALLHOOK(MonsterRemove, this))
                Send_Effect(EFFECT_ITEM_PICKUP, this.origin, '0 0 0', 1);
 
-       if(this.(weaponentity)) { remove(this.(weaponentity)); }
-       if(this.iceblock) { remove(this.iceblock); }
+       for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+       {
+               .entity weaponentity = weaponentities[slot];
+               if(this.(weaponentity))
+                       delete(this.(weaponentity));
+       }
+       if(this.iceblock) { delete(this.iceblock); }
        WaypointSprite_Kill(this.sprite);
-       remove(this);
+       delete(this);
 }
 
 void Monster_Dead_Think(entity this)
index ffade7b6a2accc4ccbfeb0fac9c82a1ebb5e7a0e..56509cf66130287530503eed396bd3a32fc2d35b 100644 (file)
@@ -1,5 +1,4 @@
-#ifndef SV_MONSTERS_H
-#define SV_MONSTERS_H
+#pragma once
 
 // stats networking
 .int stat_monsters_killed;
@@ -113,5 +112,3 @@ ALLMONSTERSOUNDS
 #undef _MSOUND
 
 float GetMonsterSoundSampleField_notFound;
-
-#endif
index e99092c660896d524f4c97e268dd8be7bead69b1..6225872332b488458e63db9d02293d886212b978 100644 (file)
@@ -16,6 +16,7 @@
 #include "mutator/damagetext/module.inc"
 #include "mutator/dodging/module.inc"
 #include "mutator/doublejump/module.inc"
+#include "mutator/globalforces/module.inc"
 #include "mutator/hook/module.inc"
 #include "mutator/instagib/module.inc"
 #include "mutator/invincibleproj/module.inc"
index c1f7501c9bc5528536590c5e3b9cd4082e2afd9c..5187f7fe1ffeb12b8f397e170597ec398295b6ca 100644 (file)
@@ -20,7 +20,7 @@ CLASS(Callback, Object)
      *     return false;
      * }
      */
-    ATTRIB(Callback, cbc_func, bool(), func_null)
+    ATTRIB(Callback, cbc_func, bool());
     CONSTRUCTOR(Callback, bool() func) {
         CONSTRUCT(Callback);
         this.cbc_func = func;
@@ -32,9 +32,9 @@ ENDCLASS(Callback)
  */
 CLASS(CallbackChain, Object)
     CLASS(CallbackNode, Object)
-        ATTRIB(CallbackNode, cbc, Callback, NULL)
-        ATTRIB(CallbackNode, cbc_next, CallbackNode, NULL)
-        ATTRIB(CallbackNode, cbc_order, int, 0)
+        ATTRIB(CallbackNode, cbc, Callback);
+        ATTRIB(CallbackNode, cbc_next, CallbackNode);
+        ATTRIB(CallbackNode, cbc_order, int, 0);
         CONSTRUCTOR(CallbackNode, Callback it, int order) {
             CONSTRUCT(CallbackNode);
             this.cbc = it;
@@ -42,8 +42,8 @@ CLASS(CallbackChain, Object)
         }
     ENDCLASS(CallbackNode)
 
-    ATTRIB(CallbackChain, cbc_next, CallbackNode, NULL)
-    ATTRIB(CallbackChain, cbc_order, int, 0)
+    ATTRIB(CallbackChain, cbc_next, CallbackNode);
+    ATTRIB(CallbackChain, cbc_order, int, 0);
     CONSTRUCTOR(CallbackChain, string _name) {
         CONSTRUCT(CallbackChain);
         this.netname = _name;
@@ -150,10 +150,10 @@ enum {
 USING(mutatorfunc_t, bool(int));
 
 CLASS(Mutator, Object)
-    ATTRIB(Mutator, m_id, int, 0)
-    ATTRIB(Mutator, m_name, string, string_null)
-    ATTRIB(Mutator, mutatorfunc, mutatorfunc_t, func_null)
-    ATTRIB(Mutator, mutatorcheck, bool(), func_null)
+    ATTRIB(Mutator, m_id, int, 0);
+    ATTRIB(Mutator, m_name, string);
+    ATTRIB(Mutator, mutatorfunc, mutatorfunc_t);
+    ATTRIB(Mutator, mutatorcheck, bool());
     CONSTRUCTOR(Mutator, string _name, mutatorfunc_t func) {
         CONSTRUCT(Mutator);
         this.m_name = _name;
@@ -203,7 +203,7 @@ NET_HANDLE(Mutator, bool isNew)
         WITH(bool, mutator_log, true, LAMBDA(
             FOREACH(Mutators, it.registered_id == s, { Mutator_Add(it); ++added; });
         ));
-        if (added > 1) LOG_WARNINGF("Added more than one mutator for %s\n", s);
+        if (added > 1) LOG_WARNF("Added more than one mutator for %s", s);
     }
 }
 #endif
@@ -227,7 +227,7 @@ bool Mutator_Add(Mutator mut)
     mutatorfunc_t func = mut.mutatorfunc;
     if (!func(MUTATOR_ADDING)) {
         // good
-        if (mutator_log) LOG_TRACEF("Mutator: added %s\n", mut.m_name);
+        if (mutator_log) LOG_TRACEF("Mutator: added %s", mut.m_name);
 #ifdef SVQC
         Net_LinkEntity(mut, false, 0, Mutator_SendEntity);
 #endif
@@ -257,7 +257,7 @@ void Mutator_Remove(Mutator mut)
         // baaaaad
         error("Mutator_Remove: removing mutator failed");
     }
-    if (mutator_log) LOG_TRACEF("Mutator: removed %s\n", mut.m_name);
+    if (mutator_log) LOG_TRACEF("Mutator: removed %s", mut.m_name);
 #ifdef SVQC
     Net_UnlinkEntity(mut);
 #endif
index 75fc8d31e1508a7037037c1db71e1b7db1c77e8a..0dbc9ea21857cffe72d144a258fbddc25e5dc837 100644 (file)
@@ -75,6 +75,7 @@ MUTATOR_HOOKABLE(WP_Format, EV_WP_Format);
  */
 #define EV_PlayerPhysics(i, o) \
     /** player */ i(entity, MUTATOR_ARGV_0_entity) \
+    /** ticrate*/ i(float, MUTATOR_ARGV_1_float) \
     /**/
 MUTATOR_HOOKABLE(PlayerPhysics, EV_PlayerPhysics);
 
@@ -92,6 +93,7 @@ MUTATOR_HOOKABLE(PlayerJump, EV_PlayerJump);
 #define EV_PM_Physics(i, o) \
     /** player */       i(entity, MUTATOR_ARGV_0_entity) \
     /** maxspeed_mod */ i(float, MUTATOR_ARGV_1_float) \
+    /** tick rate */    i(float, MUTATOR_ARGV_2_float) \
     /**/
 MUTATOR_HOOKABLE(PM_Physics, EV_PM_Physics);
 
index 66f83d1c517c03705af2508787f4f0eeef4f46f9..79117c95a811f852ac7e6a6eb3ef8b29b3464486 100644 (file)
@@ -18,12 +18,12 @@ REGISTRY_CHECK(Buffs)
 #include <common/items/item/pickup.qh>
 CLASS(Buff, Pickup)
        /** bit index */
-       ATTRIB(Buff, m_itemid, int, 0)
-       ATTRIB(Buff, m_name, string, "buff")
-       ATTRIB(Buff, m_color, vector, '1 1 1')
-       ATTRIB(Buff, m_prettyName, string, "Buff")
-       ATTRIB(Buff, m_skin, int, 0)
-       ATTRIB(Buff, m_sprite, string, "")
+       ATTRIB(Buff, m_itemid, int, 0);
+       ATTRIB(Buff, m_name, string, "buff");
+       ATTRIB(Buff, m_color, vector, '1 1 1');
+       ATTRIB(Buff, m_prettyName, string, "Buff");
+       ATTRIB(Buff, m_skin, int, 0);
+       ATTRIB(Buff, m_sprite, string, "");
        METHOD(Buff, display, void(entity this, void(string name, string icon) returns)) {
                returns(this.m_prettyName, sprintf("/gfx/hud/%s/buff_%s", cvar_string("menu_skin"), this.m_name));
        }
index 5c2987e0e74922eac1b0e5c516cbaf6d2995e10b..29a0a39256ed85d45404a8f097603f0744efda2f 100644 (file)
@@ -411,7 +411,7 @@ bool buff_Customize(entity this, entity client)
 
 void buff_Init(entity this)
 {
-       if(!cvar("g_buffs")) { remove(this); return; }
+       if(!cvar("g_buffs")) { delete(this); return; }
 
        if(!teamplay && this.team) { this.team = 0; }
 
@@ -480,7 +480,7 @@ void buff_Vengeance_DelayedDamage(entity this)
        if(this.enemy)
                Damage(this.enemy, this.owner, this.owner, this.dmg, DEATH_BUFF.m_id, this.enemy.origin, '0 0 0');
 
-       remove(this);
+       delete(this);
        return;
 }
 
@@ -681,7 +681,7 @@ MUTATOR_HOOKFUNCTION(buffs, MonsterMove)
 MUTATOR_HOOKFUNCTION(buffs, PlayerDies)
 {
        entity frag_target = M_ARGV(2, entity);
-       
+
        if(frag_target.buffs)
        {
                int buffid = buff_FirstFromFlags(frag_target.buffs).m_id;
@@ -690,7 +690,7 @@ MUTATOR_HOOKFUNCTION(buffs, PlayerDies)
 
                if(frag_target.buff_model)
                {
-                       remove(frag_target.buff_model);
+                       delete(frag_target.buff_model);
                        frag_target.buff_model = NULL;
                }
        }
@@ -788,7 +788,7 @@ bool buffs_RemovePlayer(entity player)
 {
        if(player.buff_model)
        {
-               remove(player.buff_model);
+               delete(player.buff_model);
                player.buff_model = NULL;
        }
 
@@ -986,7 +986,7 @@ MUTATOR_HOOKFUNCTION(buffs, PlayerPreThink)
                }
                else
                {
-                       remove(player.buff_model);
+                       delete(player.buff_model);
                        player.buff_model = NULL;
 
                        player.effects &= ~(EF_NOSHADOW);
index fbbe6035043af2fbfe6bc1a087d38f8e56f85961..f636696e64fc2506cedd588e63afc99a5a31d80d 100644 (file)
@@ -60,7 +60,7 @@ void bugrigs_SetVars()
 
 #endif
 
-void RaceCarPhysics(entity this)
+void RaceCarPhysics(entity this, float dt)
 {
        // using this move type for "big rigs"
        // the engine does not push the entity!
@@ -114,35 +114,35 @@ void RaceCarPhysics(entity this)
                {
                        if (myspeed > 0)
                        {
-                               myspeed = max(0, myspeed - PHYS_INPUT_TIMELENGTH * (PHYS_BUGRIGS_FRICTION_FLOOR(this) - PHYS_BUGRIGS_FRICTION_BRAKE(this) * accel));
+                               myspeed = max(0, myspeed - dt * (PHYS_BUGRIGS_FRICTION_FLOOR(this) - PHYS_BUGRIGS_FRICTION_BRAKE(this) * accel));
                        }
                        else
                        {
                                if (!PHYS_BUGRIGS_REVERSE_SPEEDING(this))
-                                       myspeed = min(0, myspeed + PHYS_INPUT_TIMELENGTH * PHYS_BUGRIGS_FRICTION_FLOOR(this));
+                                       myspeed = min(0, myspeed + dt * PHYS_BUGRIGS_FRICTION_FLOOR(this));
                        }
                }
                else
                {
                        if (myspeed >= 0)
                        {
-                               myspeed = max(0, myspeed - PHYS_INPUT_TIMELENGTH * PHYS_BUGRIGS_FRICTION_FLOOR(this));
+                               myspeed = max(0, myspeed - dt * PHYS_BUGRIGS_FRICTION_FLOOR(this));
                        }
                        else
                        {
                                if (PHYS_BUGRIGS_REVERSE_STOPPING(this))
                                        myspeed = 0;
                                else
-                                       myspeed = min(0, myspeed + PHYS_INPUT_TIMELENGTH * (PHYS_BUGRIGS_FRICTION_FLOOR(this) + PHYS_BUGRIGS_FRICTION_BRAKE(this) * accel));
+                                       myspeed = min(0, myspeed + dt * (PHYS_BUGRIGS_FRICTION_FLOOR(this) + PHYS_BUGRIGS_FRICTION_BRAKE(this) * accel));
                        }
                }
                // terminal velocity = velocity at which 50 == accelfactor, that is, 1549 units/sec
                //MAXIMA: friction(v) := PHYS_BUGRIGS_FRICTION_FLOOR(this);
 
-               this.angles_y += steer * PHYS_INPUT_TIMELENGTH * steerfactor; // apply steering
+               this.angles_y += steer * dt * steerfactor; // apply steering
                makevectors(this.angles); // new forward direction!
 
-               myspeed += accel * accelfactor * PHYS_INPUT_TIMELENGTH;
+               myspeed += accel * accelfactor * dt;
 
                rigvel = myspeed * v_forward + '0 0 1' * upspeed;
        }
@@ -153,13 +153,13 @@ void RaceCarPhysics(entity this)
                // responsiveness factor for steering and acceleration
                float f = 1 / (1 + pow(max(0, myspeed / PHYS_BUGRIGS_SPEED_REF(this)), PHYS_BUGRIGS_SPEED_POW(this)));
                float steerfactor = -myspeed * f;
-               this.angles_y += steer * PHYS_INPUT_TIMELENGTH * steerfactor; // apply steering
+               this.angles_y += steer * dt * steerfactor; // apply steering
 
                rigvel = this.velocity;
                makevectors(this.angles); // new forward direction!
        }
 
-       rigvel *= max(0, 1 - vlen(rigvel) * PHYS_BUGRIGS_FRICTION_AIR(this) * PHYS_INPUT_TIMELENGTH);
+       rigvel *= max(0, 1 - vlen(rigvel) * PHYS_BUGRIGS_FRICTION_AIR(this) * dt);
        //MAXIMA: airfriction(v) := v * v * PHYS_BUGRIGS_FRICTION_AIR(this);
        //MAXIMA: total_acceleration(v) := accel(v) - friction(v) - airfriction(v);
        //MAXIMA: solve(total_acceleration(v) = 0, v);
@@ -169,7 +169,7 @@ void RaceCarPhysics(entity this)
                vector rigvel_xy, neworigin, up;
                float mt;
 
-               rigvel_z -= PHYS_INPUT_TIMELENGTH * PHYS_GRAVITY(this); // 4x gravity plays better
+               rigvel_z -= dt * PHYS_GRAVITY(this); // 4x gravity plays better
                rigvel_xy = vec2(rigvel);
 
                if (PHYS_BUGRIGS_CAR_JUMPING(this))
@@ -182,10 +182,10 @@ void RaceCarPhysics(entity this)
 
                // BUG RIGS: align the move to the surface instead of doing collision testing
                // can we move?
-               tracebox(trace_endpos, this.mins, this.maxs, trace_endpos + rigvel_xy * PHYS_INPUT_TIMELENGTH, mt, this);
+               tracebox(trace_endpos, this.mins, this.maxs, trace_endpos + rigvel_xy * dt, mt, this);
 
                // align to surface
-               tracebox(trace_endpos, this.mins, this.maxs, trace_endpos - up + '0 0 1' * rigvel_z * PHYS_INPUT_TIMELENGTH, mt, this);
+               tracebox(trace_endpos, this.mins, this.maxs, trace_endpos - up + '0 0 1' * rigvel_z * dt, mt, this);
 
                if (trace_fraction < 0.5)
                {
@@ -213,12 +213,12 @@ void RaceCarPhysics(entity this)
                        UNSET_ONGROUND(this);
                }
 
-               this.velocity = (neworigin - this.origin) * (1.0 / PHYS_INPUT_TIMELENGTH);
+               this.velocity = (neworigin - this.origin) * (1.0 / dt);
                set_movetype(this, MOVETYPE_NOCLIP);
        }
        else
        {
-               rigvel_z -= PHYS_INPUT_TIMELENGTH * PHYS_GRAVITY(this); // 4x gravity plays better
+               rigvel_z -= dt * PHYS_GRAVITY(this); // 4x gravity plays better
                this.velocity = rigvel;
                set_movetype(this, MOVETYPE_FLY);
        }
@@ -251,7 +251,7 @@ void RaceCarPhysics(entity this)
        // smooth the angles
        vector vf1, vu1, smoothangles;
        makevectors(this.angles);
-       float f = bound(0, PHYS_INPUT_TIMELENGTH * PHYS_BUGRIGS_ANGLE_SMOOTHING(this), 1);
+       float f = bound(0, dt * PHYS_BUGRIGS_ANGLE_SMOOTHING(this), 1);
        if (f == 0)
                f = 1;
        vf1 = v_forward * f;
@@ -270,6 +270,7 @@ void RaceCarPhysics(entity this)
 MUTATOR_HOOKFUNCTION(bugrigs, PM_Physics)
 {
     entity player = M_ARGV(0, entity);
+    float dt = M_ARGV(2, float);
 
        if(!PHYS_BUGRIGS(player) || !IS_PLAYER(player)) { return; }
 
@@ -277,7 +278,7 @@ MUTATOR_HOOKFUNCTION(bugrigs, PM_Physics)
        player.angles = player.bugrigs_prevangles;
 #endif
 
-       RaceCarPhysics(player);
+       RaceCarPhysics(player, dt);
        return true;
 }
 
index 191f61681583ab70092cde44e2eb49ff2fb9a18e..1ab6fb4624eb246b027319a8685f12dc54081bac 100644 (file)
@@ -11,7 +11,7 @@ REGISTER_MUTATOR(campcheck, cvar("g_campcheck"));
 MUTATOR_HOOKFUNCTION(campcheck, PlayerDies)
 {
        entity frag_target = M_ARGV(2, entity);
-       
+
        Kill_Notification(NOTIF_ONE, frag_target, MSG_CENTER, CPID_CAMPCHECK);
 }
 
@@ -86,6 +86,6 @@ MUTATOR_HOOKFUNCTION(campcheck, PlayerSpawn)
 
 MUTATOR_HOOKFUNCTION(campcheck, BuildMutatorsString)
 {
-       M_ARGV(0, string) = strcat(M_ARGV(0, string), ":CampCheck");;
+       M_ARGV(0, string) = strcat(M_ARGV(0, string), ":CampCheck");
 }
 #endif
index 8de4f2b8549d09d9a99f12903a3870b9629fee04..878a854fb79ccc27bcbe6ffdd7c1fe7a7900a76e 100644 (file)
@@ -31,25 +31,25 @@ AUTOCVAR_SAVE(cl_damagetext_friendlyfire_color, vector, '1 0 0',    "Damage text
 
 #ifdef CSQC
 CLASS(DamageText, Object)
-    ATTRIB(DamageText, m_color, vector, autocvar_cl_damagetext_color)
-    ATTRIB(DamageText, m_color_friendlyfire, vector, autocvar_cl_damagetext_friendlyfire_color)
-    ATTRIB(DamageText, m_size, float, autocvar_cl_damagetext_size)
-    ATTRIB(DamageText, alpha, float, autocvar_cl_damagetext_alpha_start)
-    ATTRIB(DamageText, fade_rate, float, 1 / autocvar_cl_damagetext_alpha_lifetime)
-    ATTRIB(DamageText, velocity, vector, autocvar_cl_damagetext_velocity)
-    ATTRIB(DamageText, m_group, int, 0)
-    ATTRIB(DamageText, m_friendlyfire, bool, false)
-    ATTRIB(DamageText, m_damage, int, 0)
-    ATTRIB(DamageText, m_armordamage, int, 0)
-    ATTRIB(DamageText, m_deathtype, int, 0)
-    ATTRIB(DamageText, time_prev, float, time)
+    ATTRIB(DamageText, m_color, vector, autocvar_cl_damagetext_color);
+    ATTRIB(DamageText, m_color_friendlyfire, vector, autocvar_cl_damagetext_friendlyfire_color);
+    ATTRIB(DamageText, m_size, float, autocvar_cl_damagetext_size);
+    ATTRIB(DamageText, alpha, float, autocvar_cl_damagetext_alpha_start);
+    ATTRIB(DamageText, fade_rate, float, 1 / autocvar_cl_damagetext_alpha_lifetime);
+    ATTRIB(DamageText, velocity, vector, autocvar_cl_damagetext_velocity);
+    ATTRIB(DamageText, m_group, int, 0);
+    ATTRIB(DamageText, m_friendlyfire, bool, false);
+    ATTRIB(DamageText, m_damage, int, 0);
+    ATTRIB(DamageText, m_armordamage, int, 0);
+    ATTRIB(DamageText, m_deathtype, int, 0);
+    ATTRIB(DamageText, time_prev, float, time);
 
     void DamageText_draw2d(DamageText this) {
         float dt = time - this.time_prev;
         this.time_prev = time;
         setorigin(this, this.origin + dt * this.velocity);
         this.alpha -= dt * this.fade_rate;
-        if (this.alpha < 0) remove(this);
+        if (this.alpha < 0) delete(this);
         vector pos = project_3d_to_2d(this.origin) + autocvar_cl_damagetext_offset;
         if (pos.z >= 0 && this.m_size > 0) {
             pos.z = 0;
@@ -71,7 +71,7 @@ CLASS(DamageText, Object)
             drawcolorcodedstring2_builtin(pos, s, this.m_size * '1 1 0', rgb, this.alpha, DRAWFLAG_NORMAL);
         }
     }
-    ATTRIB(DamageText, draw2d, void(DamageText), DamageText_draw2d)
+    ATTRIB(DamageText, draw2d, void(DamageText), DamageText_draw2d);
 
     void DamageText_update(DamageText this, vector _origin, int _health, int _armor, int _deathtype) {
         this.m_damage = _health;
@@ -160,10 +160,10 @@ NET_HANDLE(damagetext, bool isNew)
 CLASS(XonoticDamageTextSettings, XonoticTab)
     #include <menu/gamesettings.qh>
     REGISTER_SETTINGS(damagetext, NEW(XonoticDamageTextSettings));
-    ATTRIB(XonoticDamageTextSettings, title, string, _("Damage text"))
-    ATTRIB(XonoticDamageTextSettings, intendedWidth, float, 0.9)
-    ATTRIB(XonoticDamageTextSettings, rows, float, 15.5)
-    ATTRIB(XonoticDamageTextSettings, columns, float, 5)
+    ATTRIB(XonoticDamageTextSettings, title, string, _("Damage text"));
+    ATTRIB(XonoticDamageTextSettings, intendedWidth, float, 0.9);
+    ATTRIB(XonoticDamageTextSettings, rows, float, 15.5);
+    ATTRIB(XonoticDamageTextSettings, columns, float, 5);
     INIT(XonoticDamageTextSettings) { this.configureDialog(this); }
     METHOD(XonoticDamageTextSettings, showNotify, void(entity this)) { loadAllCvars(this); }
     METHOD(XonoticDamageTextSettings, fill, void(entity this))
diff --git a/qcsrc/common/mutators/mutator/globalforces/_mod.inc b/qcsrc/common/mutators/mutator/globalforces/_mod.inc
new file mode 100644 (file)
index 0000000..006a5d5
--- /dev/null
@@ -0,0 +1,2 @@
+// generated file; do not modify
+#include <common/mutators/mutator/globalforces/globalforces.qc>
diff --git a/qcsrc/common/mutators/mutator/globalforces/_mod.qh b/qcsrc/common/mutators/mutator/globalforces/_mod.qh
new file mode 100644 (file)
index 0000000..ac5cfd2
--- /dev/null
@@ -0,0 +1,2 @@
+// generated file; do not modify
+#include <common/mutators/mutator/globalforces/globalforces.qh>
diff --git a/qcsrc/common/mutators/mutator/globalforces/globalforces.qc b/qcsrc/common/mutators/mutator/globalforces/globalforces.qc
new file mode 100644 (file)
index 0000000..49ac468
--- /dev/null
@@ -0,0 +1,33 @@
+#ifdef IMPLEMENTATION
+
+AUTOCVAR(g_globalforces, float, false, "Global forces: knockback affects everyone");
+AUTOCVAR(g_globalforces_noself, bool, true, "Global forces: ignore self damage");
+AUTOCVAR(g_globalforces_self, float, 1, "Global forces: knockback self scale");
+AUTOCVAR(g_globalforces_range, float, 1000, "Global forces: max range of effect");
+REGISTER_MUTATOR(mutator_globalforces, autocvar_g_globalforces);
+
+MUTATOR_HOOKFUNCTION(mutator_globalforces, BuildMutatorsString) {
+    M_ARGV(0, string) = strcat(M_ARGV(0, string), ":GlobalForces");
+}
+
+MUTATOR_HOOKFUNCTION(mutator_globalforces, BuildMutatorsPrettyString) {
+    M_ARGV(0, string) = strcat(M_ARGV(0, string), ", Global forces");
+}
+
+MUTATOR_HOOKFUNCTION(mutator_globalforces, PlayerDamage_SplitHealthArmor) {
+    entity frag_attacker = M_ARGV(1, entity);
+    entity frag_target = M_ARGV(2, entity);
+    if (autocvar_g_globalforces_noself && frag_target == frag_attacker) return;
+    vector damage_force = M_ARGV(3, vector) * autocvar_g_globalforces;
+    FOREACH_CLIENT(IS_PLAYER(it) && it != frag_target, {
+        if (autocvar_g_globalforces_range) {
+            if (vdist(it.origin - frag_target.origin, >, autocvar_g_globalforces_range)) {
+                continue;
+            }
+        }
+        float f = (it == frag_attacker) ? autocvar_g_globalforces_self : 1;
+        it.velocity += damage_explosion_calcpush(f * it.damageforcescale * damage_force, it.velocity, autocvar_g_balance_damagepush_speedfactor);
+    });
+}
+
+#endif
diff --git a/qcsrc/common/mutators/mutator/globalforces/module.inc b/qcsrc/common/mutators/mutator/globalforces/module.inc
new file mode 100644 (file)
index 0000000..2a0eec8
--- /dev/null
@@ -0,0 +1,3 @@
+#ifdef SVQC
+       #include "globalforces.qc"
+#endif
index 34f3825680445139c5de7e07396304589e55fed2..25edbb225c89b7f6fa045b9c7e3fb6e1630abffa 100644 (file)
@@ -24,7 +24,7 @@ REGISTER_MUTATOR(mutator_instagib, cvar("g_instagib") && !g_nexball);
 
 spawnfunc(item_minst_cells)
 {
-       if (!g_instagib) { remove(this); return; }
+       if (!g_instagib) { delete(this); return; }
        if (!this.ammo_cells) this.ammo_cells = autocvar_g_instagib_ammo_drop;
        StartItem(this, ITEM_VaporizerCells);
 }
index cdd163f57a6ae879b7a69d39f37d5b1da41705f5..f47923d4efcc5c3b1e16f2e439655b9e9f1bd30a 100644 (file)
@@ -180,14 +180,14 @@ MUTATOR_HOOKFUNCTION(itemstime, ClientConnect, CBC_ORDER_LAST)
        {
                // client became player on connection skipping putObserverInServer step
                if (IS_REAL_CLIENT(player))
-               if (warmup_stage)
+               if (warmup_stage || autocvar_sv_itemstime == 2)
                        Item_ItemsTime_SetTimesForPlayer(player);
        }
 }
 
 MUTATOR_HOOKFUNCTION(itemstime, PlayerSpawn)
 {
-    if (warmup_stage) return;
+    if (warmup_stage || autocvar_sv_itemstime == 2) return;
     entity player = M_ARGV(0, entity);
 
     Item_ItemsTime_ResetTimesForPlayer(player);
@@ -270,7 +270,7 @@ void HUD_ItemsTime()
     {
         if (!(
             (autocvar_hud_panel_itemstime == 1 && spectatee_status != 0)
-        ||     (autocvar_hud_panel_itemstime == 2 && (spectatee_status != 0 || warmup_stage))
+        ||     (autocvar_hud_panel_itemstime == 2 && (spectatee_status != 0 || warmup_stage || STAT(ITEMSTIME) == 2))
             )) { return; }
     }
     else
@@ -330,7 +330,7 @@ void HUD_ItemsTime()
     if (autocvar_hud_panel_itemstime_dynamicsize)
     {
         if (autocvar__hud_configure)
-        if (menu_enabled != 2)
+        if (hud_configure_menu_open != 2)
             HUD_Panel_DrawBg(1); // also draw the bg of the entire panel
 
         // reduce panel to avoid spacing items
index cda6b4c8282d290ff00083d1e76fb4c2ec3531d1..1fa69a60e147929437e2b1e02aa8a4816f649738 100644 (file)
@@ -10,7 +10,7 @@ MUTATOR_HOOKFUNCTION(midair, PlayerDamage_Calculate)
 {
        entity frag_attacker = M_ARGV(1, entity);
        entity frag_target = M_ARGV(2, entity);
-       
+
        if(IS_PLAYER(frag_attacker))
        if(IS_PLAYER(frag_target))
        if(time < frag_target.midair_shieldtime)
index 780836d4986166d4c6f6cce4457dbc2a0e90d1a0..d6dc30cee4ec16d0ce8d4a3e899376ab6b429575 100644 (file)
@@ -60,7 +60,7 @@ MUTATOR_HOOKFUNCTION(multijump, PlayerJump)
 
        int phys_multijump = PHYS_MULTIJUMP(player);
 
-       if(!M_ARGV(2, bool) && player.multijump_ready && (PHYS_MULTIJUMP_COUNT(player) < phys_multijump || phys_multijump == -1) && player.velocity_z > PHYS_MULTIJUMP_SPEED(player) && 
+       if(!M_ARGV(2, bool) && player.multijump_ready && (PHYS_MULTIJUMP_COUNT(player) < phys_multijump || phys_multijump == -1) && player.velocity_z > PHYS_MULTIJUMP_SPEED(player) &&
                (!PHYS_MULTIJUMP_MAXSPEED(player) || vdist(player.velocity, <=, PHYS_MULTIJUMP_MAXSPEED(player))))
        {
                if (PHYS_MULTIJUMP(player))
index 5570a1b084aa6befa6a67ca796e1dae109504c7a..d785124a76e6698bc139ffe2d38134a975cba50c 100644 (file)
@@ -163,7 +163,7 @@ void nade_timer_think(entity this)
        this.skin = 8 - (this.owner.wait - time) / (autocvar_g_nades_nade_lifetime / 10);
        this.nextthink = time;
        if(!this.owner || wasfreed(this.owner))
-               remove(this);
+               delete(this);
 }
 
 void nade_burn_spawn(entity _nade)
@@ -232,13 +232,13 @@ void napalm_ball_think(entity this)
        if(round_handler_IsActive())
        if(!round_handler_IsRoundStarted())
        {
-               remove(this);
+               delete(this);
                return;
        }
 
        if(time > this.pushltime)
        {
-               remove(this);
+               delete(this);
                return;
        }
 
@@ -294,6 +294,7 @@ void nade_napalm_ball(entity this)
 
        proj.angles = vectoangles(proj.velocity);
        proj.flags = FL_PROJECTILE;
+       IL_PUSH(g_projectiles, proj);
        proj.missile_flags = MIF_SPLASH | MIF_PROXY | MIF_ARC;
 
        //CSQCProjectile(proj, true, PROJECTILE_NAPALM_FIRE, true);
@@ -306,13 +307,13 @@ void napalm_fountain_think(entity this)
        if(round_handler_IsActive())
        if(!round_handler_IsRoundStarted())
        {
-               remove(this);
+               delete(this);
                return;
        }
 
        if(time >= this.ltime)
        {
-               remove(this);
+               delete(this);
                return;
        }
 
@@ -379,7 +380,7 @@ void nade_ice_think(entity this)
        if(round_handler_IsActive())
        if(!round_handler_IsRoundStarted())
        {
-               remove(this);
+               delete(this);
                return;
        }
 
@@ -396,7 +397,7 @@ void nade_ice_think(entity this)
                        Damage_DamageInfo(this.origin, autocvar_g_nades_nade_damage, autocvar_g_nades_nade_edgedamage,
                                autocvar_g_nades_nade_radius, '1 1 1' * autocvar_g_nades_nade_force, this.projectiledeathtype, 0, this);
                }
-               remove(this);
+               delete(this);
                return;
        }
 
@@ -502,7 +503,7 @@ void nade_spawn_boom(entity this)
 
        if(this.realowner.nade_spawnloc)
        {
-               remove(this.realowner.nade_spawnloc);
+               delete(this.realowner.nade_spawnloc);
                this.realowner.nade_spawnloc = NULL;
        }
 
@@ -513,7 +514,7 @@ void nades_orb_think(entity this)
 {
        if(time >= this.ltime)
        {
-               remove(this);
+               delete(this);
                return;
        }
 
@@ -737,7 +738,7 @@ void nade_boom(entity this)
                        RemoveGrapplingHook(it.realowner);
        });
 
-       remove(this);
+       delete(this);
 }
 
 void spawn_held_nade(entity player, entity nowner, float ntime, int ntype, string pntype);
@@ -771,7 +772,7 @@ void nade_touch(entity this, entity toucher)
        {
                nade_pickup(toucher, this);
                sound(this, CH_SHOTS_SINGLE, SND_Null, VOL_BASE, 0.5 *(ATTEN_LARGE + ATTEN_MAX));
-               remove(this);
+               delete(this);
                return;
        }
        /*float is_weapclip = 0;
@@ -786,7 +787,7 @@ void nade_touch(entity this, entity toucher)
                        if(it.classname == "grapplinghook")
                                RemoveGrapplingHook(it.realowner);
                });
-               remove(this);
+               delete(this);
                return;
        }
 
@@ -884,12 +885,13 @@ void toss_nade(entity e, bool set_owner, vector _velocity, float _time)
        entity _nade = e.nade;
        e.nade = NULL;
 
-       remove(e.fake_nade);
+       delete(e.fake_nade);
        e.fake_nade = NULL;
 
        makevectors(e.v_angle);
 
-       W_SetupShot(e, false, false, SND_Null, CH_WEAPON_A, 0);
+       // NOTE: always throw from first weapon entity?
+       W_SetupShot(e, weaponentities[0], false, false, SND_Null, CH_WEAPON_A, 0);
 
        Kill_Notification(NOTIF_ONE_ONLY, e, MSG_CENTER, CPID_NADES);
 
@@ -941,6 +943,7 @@ void toss_nade(entity e, bool set_owner, vector _velocity, float _time)
        _nade.damagedbycontents = true;
        _nade.angles = vectoangles(_nade.velocity);
        _nade.flags = FL_PROJECTILE;
+       IL_PUSH(g_projectiles, _nade);
        _nade.projectiledeathtype = DEATH_NADE.m_id;
        _nade.toss_time = time;
        _nade.solid = SOLID_CORPSE; //((_nade.nade_type == NADE_TYPE_TRANSLOCATE) ? SOLID_CORPSE : SOLID_BBOX);
@@ -1065,10 +1068,10 @@ void nade_prime(entity this)
                return; // only allow bonus nades
 
        if(this.nade)
-               remove(this.nade);
+               delete(this.nade);
 
        if(this.fake_nade)
-               remove(this.fake_nade);
+               delete(this.fake_nade);
 
        int ntype;
        string pntype = this.pokenade_type;
@@ -1149,9 +1152,9 @@ void nades_CheckThrow(entity this)
 void nades_Clear(entity player)
 {
        if(player.nade)
-               remove(player.nade);
+               delete(player.nade);
        if(player.fake_nade)
-               remove(player.fake_nade);
+               delete(player.fake_nade);
 
        player.nade = player.fake_nade = NULL;
        player.nade_timer = 0;
@@ -1172,7 +1175,7 @@ CLASS(NadeOffhand, OffhandWeapon)
                if (held_nade)
                {
                        player.nade_timer = bound(0, (time - held_nade.nade_time_primed) / autocvar_g_nades_nade_lifetime, 1);
-                       // LOG_TRACEF("%d %d\n", player.nade_timer, time - held_nade.nade_time_primed);
+                       // LOG_TRACEF("%d %d", player.nade_timer, time - held_nade.nade_time_primed);
                        makevectors(player.angles);
                        held_nade.velocity = player.velocity;
                        setorigin(held_nade, player.origin + player.view_ofs + v_forward * 8 + v_right * -8 + v_up * 0);
@@ -1349,7 +1352,7 @@ MUTATOR_HOOKFUNCTION(nades, PlayerSpawn)
 
                if(player.nade_spawnloc.cnt <= 0)
                {
-                       remove(player.nade_spawnloc);
+                       delete(player.nade_spawnloc);
                        player.nade_spawnloc = NULL;
                }
        }
@@ -1427,7 +1430,7 @@ MUTATOR_HOOKFUNCTION(nades, MonsterDies)
 MUTATOR_HOOKFUNCTION(nades, DropSpecialItems)
 {
        entity frag_target = M_ARGV(0, entity);
-       
+
        if(frag_target.nade)
                toss_nade(frag_target, true, '0 0 0', time + 0.05);
 }
index 2f48d9579cba95cfb8272464fc3a8df0f54433f2..a7eed65d33aceb29f20ee28d94228ad3eb2a4331 100644 (file)
@@ -28,12 +28,12 @@ REGISTRY_CHECK(Nades)
 #define REGISTER_NADE(id) REGISTER(Nades, NADE_TYPE, id, m_id, NEW(Nade))
 
 CLASS(Nade, Object)
-    ATTRIB(Nade, m_id, int, 0)
-    ATTRIB(Nade, m_color, vector, '0 0 0')
-    ATTRIB(Nade, m_name, string, _("Grenade"))
-    ATTRIB(Nade, m_icon, string, "nade_normal")
-    ATTRIBARRAY(Nade, m_projectile, int, 2)
-    ATTRIBARRAY(Nade, m_trail, entity, 2)
+    ATTRIB(Nade, m_id, int, 0);
+    ATTRIB(Nade, m_color, vector, '0 0 0');
+    ATTRIB(Nade, m_name, string, _("Grenade"));
+    ATTRIB(Nade, m_icon, string, "nade_normal");
+    ATTRIBARRAY(Nade, m_projectile, int, 2);
+    ATTRIBARRAY(Nade, m_trail, entity, 2);
     METHOD(Nade, display, void(entity this, void(string name, string icon) returns)) {
         returns(this.m_name, sprintf("/gfx/hud/%s/%s", cvar_string("menu_skin"), this.m_icon));
     }
index 9488e02a527a098620f9848cd971e412a205f92e..e2659c7af85307fb2e30529e1318b83e35a12746 100644 (file)
@@ -31,7 +31,7 @@ void orb_setup(entity e)
        e.draw = orb_draw;
        IL_PUSH(g_drawables, e);
        e.health = 255;
-       e.move_movetype = MOVETYPE_NONE;
+       set_movetype(e, MOVETYPE_NONE);
        e.solid = SOLID_NOT;
        e.drawmask = MASK_NORMAL;
        e.scale = 0.01;
index 2000ffd5dd758ccdeb05beb2ce6ee099662e57bf..1512992c250f1e75b508fc0e3eb62ea07afdef59 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef IMPLEMENTATION
 CLASS(HeavyMachineGun, Weapon)
-/* ammotype  */ ATTRIB(HeavyMachineGun, ammo_field, .int, ammo_nails)
-/* impulse   */ ATTRIB(HeavyMachineGun, impulse, int, 3)
+/* ammotype  */ ATTRIB(HeavyMachineGun, ammo_field, .int, ammo_nails);
+/* impulse   */ ATTRIB(HeavyMachineGun, impulse, int, 3);
 /* flags     */ ATTRIB(HeavyMachineGun, spawnflags, int, WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_HIDDEN | WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_TYPE_HITSCAN | WEP_FLAG_SUPERWEAPON);
 /* rating    */ ATTRIB(HeavyMachineGun, bot_pickupbasevalue, float, BOT_PICKUP_RATING_HIGH);
 /* color     */ ATTRIB(HeavyMachineGun, wpcolor, vector, '0.5 0.5 0');
@@ -71,7 +71,7 @@ void W_HeavyMachineGun_Attack_Auto(Weapon thiswep, entity actor, .entity weapone
 
        W_DecreaseAmmo(WEP_HMG, actor, WEP_CVAR(hmg, ammo));
 
-       W_SetupShot (actor, true, 0, SND_UZI_FIRE, CH_WEAPON_A, WEP_CVAR(hmg, damage));
+       W_SetupShot (actor, weaponentity, true, 0, SND_UZI_FIRE, CH_WEAPON_A, WEP_CVAR(hmg, damage));
 
        if(!autocvar_g_norecoil)
        {
@@ -86,13 +86,13 @@ void W_HeavyMachineGun_Attack_Auto(Weapon thiswep, entity actor, .entity weapone
 
        Send_Effect(EFFECT_MACHINEGUN_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
 
-       W_MachineGun_MuzzleFlash(actor);
-       W_AttachToShotorg(actor, actor.muzzle_flash, '5 0 0');
+       W_MachineGun_MuzzleFlash(actor, weaponentity);
+       W_AttachToShotorg(actor, weaponentity, actor.(weaponentity).muzzle_flash, '5 0 0');
 
        if (autocvar_g_casings >= 2) // casing code
        {
                makevectors(actor.v_angle); // for some reason, this is lost
-               SpawnCasing (((random () * 50 + 50) * v_right) - (v_forward * (random () * 25 + 25)) - ((random () * 5 - 70) * v_up), 2, vectoangles(v_forward),'0 250 0', 100, 3, actor);
+               SpawnCasing (((random () * 50 + 50) * v_right) - (v_forward * (random () * 25 + 25)) - ((random () * 5 - 70) * v_up), 2, vectoangles(v_forward),'0 250 0', 100, 3, actor, weaponentity);
        }
 
        int slot = weaponslot(weaponentity);
@@ -145,7 +145,7 @@ METHOD(HeavyMachineGun, wr_checkammo2, bool(entity thiswep, entity actor))
 
 METHOD(HeavyMachineGun, wr_reload, void(entity thiswep, entity actor, .entity weaponentity))
 {
-    W_Reload(actor, WEP_CVAR(hmg, ammo), SND_RELOAD);
+    W_Reload(actor, weaponentity, WEP_CVAR(hmg, ammo), SND_RELOAD);
 }
 
 METHOD(HeavyMachineGun, wr_suicidemessage, Notification(entity thiswep))
index ef76ab51519ceb1f61ee16caefb622a4126e5816..f49fdc11b4a2901a3038257ecd8b9cf2f7990060 100644 (file)
@@ -53,7 +53,7 @@ MUTATOR_HOOKFUNCTION(ok, W_Reload)
        return actor.ok_use_ammocharge;
 }
 
-void W_Blaster_Attack(entity, float, float, float, float, float, float, float, float, float, float);
+void W_Blaster_Attack(entity, .entity, float, float, float, float, float, float, float, float, float, float);
 spawnfunc(weapon_hmg);
 spawnfunc(weapon_rpc);
 
@@ -157,7 +157,7 @@ MUTATOR_HOOKFUNCTION(ok, MonsterDropItem)
        entity olditem = M_ARGV(1, entity);
        entity frag_attacker = M_ARGV(2, entity);
 
-       remove(olditem);
+       delete(olditem);
 
        M_ARGV(1, entity) = NULL;
 
@@ -227,6 +227,7 @@ MUTATOR_HOOKFUNCTION(ok, PlayerPreThink)
                PS(player).m_weapon = WEP_BLASTER;
                W_Blaster_Attack(
                        player,
+                       weaponentities[0], // TODO: unhardcode
                        WEP_BLASTER.m_id | HITTYPE_SECONDARY,
                        WEP_CVAR_SEC(vaporizer, shotangle),
                        WEP_CVAR_SEC(vaporizer, damage),
index 4c59f183a39e53c41104d2c75edb64c107adbc40..f9be2ad9f58c4dd41e660e8e775954cfad0c8777 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef IMPLEMENTATION
 CLASS(RocketPropelledChainsaw, Weapon)
-/* ammotype  */ ATTRIB(RocketPropelledChainsaw, ammo_field, .int, ammo_rockets)
-/* impulse   */ ATTRIB(RocketPropelledChainsaw, impulse, int, 7)
+/* ammotype  */ ATTRIB(RocketPropelledChainsaw, ammo_field, .int, ammo_rockets);
+/* impulse   */ ATTRIB(RocketPropelledChainsaw, impulse, int, 7);
 /* flags     */ ATTRIB(RocketPropelledChainsaw, spawnflags, int, WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_HIDDEN | WEP_FLAG_NORMAL | WEP_FLAG_CANCLIMB | WEP_FLAG_RELOADABLE | WEP_TYPE_SPLASH | WEP_FLAG_SUPERWEAPON);
 /* rating    */ ATTRIB(RocketPropelledChainsaw, bot_pickupbasevalue, float, BOT_PICKUP_RATING_HIGH);
 /* color     */ ATTRIB(RocketPropelledChainsaw, wpcolor, vector, '0.5 0.5 0');
@@ -57,7 +57,7 @@ void W_RocketPropelledChainsaw_Explode(entity this, entity directhitentity)
 
        RadiusDamage (this, this.realowner, WEP_CVAR(rpc, damage), WEP_CVAR(rpc, edgedamage), WEP_CVAR(rpc, radius), NULL, NULL, WEP_CVAR(rpc, force), this.projectiledeathtype, directhitentity);
 
-       remove (this);
+       delete (this);
 }
 
 void W_RocketPropelledChainsaw_Explode_think(entity this)
@@ -92,7 +92,7 @@ void W_RocketPropelledChainsaw_Think(entity this)
 {
        if(this.cnt <= time)
        {
-               remove(this);
+               delete(this);
                return;
        }
 
@@ -110,13 +110,13 @@ void W_RocketPropelledChainsaw_Think(entity this)
        this.nextthink = time;
 }
 
-void W_RocketPropelledChainsaw_Attack (Weapon thiswep, entity actor)
+void W_RocketPropelledChainsaw_Attack (Weapon thiswep, entity actor, .entity weaponentity)
 {
        entity missile = spawn(); //WarpZone_RefSys_SpawnSameRefSys(actor);
        entity flash = spawn ();
 
        W_DecreaseAmmo(thiswep, actor, WEP_CVAR(rpc, ammo));
-       W_SetupShot_ProjectileSize (actor, '-3 -3 -3', '3 3 3', false, 5, SND_ROCKET_FIRE, CH_WEAPON_A, WEP_CVAR(rpc, damage));
+       W_SetupShot_ProjectileSize (actor, weaponentity, '-3 -3 -3', '3 3 3', false, 5, SND_ROCKET_FIRE, CH_WEAPON_A, WEP_CVAR(rpc, damage));
        Send_Effect(EFFECT_ROCKET_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
        PROJECTILE_MAKETRIGGER(missile);
 
@@ -143,13 +143,14 @@ void W_RocketPropelledChainsaw_Attack (Weapon thiswep, entity actor)
        missile.cnt = time + WEP_CVAR(rpc, lifetime);
        missile.nextthink = time;
        missile.flags = FL_PROJECTILE;
+       IL_PUSH(g_projectiles, missile);
 
        CSQCProjectile(missile, true, PROJECTILE_RPC, false);
 
        setmodel(flash, MDL_RPC_MUZZLEFLASH); // precision set below
        SUB_SetFade (flash, time, 0.1);
        flash.effects = EF_ADDITIVE | EF_FULLBRIGHT | EF_LOWPRECISION;
-       W_AttachToShotorg(actor, flash, '5 0 0');
+       W_AttachToShotorg(actor, weaponentity, flash, '5 0 0');
        missile.pos1 = missile.velocity;
 
        MUTATOR_CALLHOOK(EditProjectile, actor, missile);
@@ -170,7 +171,7 @@ METHOD(RocketPropelledChainsaw, wr_think, void(entity thiswep, entity actor, .en
         {
             if(weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR(rpc, refire)))
             {
-                W_RocketPropelledChainsaw_Attack(thiswep, actor);
+                W_RocketPropelledChainsaw_Attack(thiswep, actor, weaponentity);
                 weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR(rpc, animtime), w_ready);
             }
         }
@@ -196,7 +197,7 @@ METHOD(RocketPropelledChainsaw, wr_checkammo2, bool(entity thiswep, entity actor
 
 METHOD(RocketPropelledChainsaw, wr_reload, void(entity thiswep, entity actor, .entity weaponentity))
 {
-    W_Reload(actor, WEP_CVAR(rpc, ammo), SND_RELOAD);
+    W_Reload(actor, weaponentity, WEP_CVAR(rpc, ammo), SND_RELOAD);
 }
 
 METHOD(RocketPropelledChainsaw, wr_suicidemessage, Notification(entity thiswep))
index 8e9d4699e895c8ac33257ce54026472d8ac9e714..f015baeaa9fbc7c3d75f125c47e1d8487280f987 100644 (file)
@@ -10,7 +10,7 @@ REGISTER_MUTATOR(physical_items, cvar("g_physical_items"))
        {
                if (!(autocvar_physics_ode && checkextension("DP_PHYSICS_ODE")))
                {
-                       LOG_TRACE("Warning: Physical items are enabled but no physics engine can be used. Reverting to old items.\n");
+                       LOG_TRACE("Warning: Physical items are enabled but no physics engine can be used. Reverting to old items.");
                        return -1;
                }
        }
@@ -65,7 +65,7 @@ void physical_item_think(entity this)
        }
 
        if(!this.owner.modelindex)
-               remove(this); // the real item is gone, remove this
+               delete(this); // the real item is gone, remove this
 }
 
 void physical_item_touch(entity this, entity toucher)
index 10866a2f169bf19a7a5843922b67f2d6eb2761ab..acdf1718b04cab3dca0702a3d6b5d68bdf2b2d7c 100644 (file)
@@ -4,7 +4,7 @@ REGISTER_MUTATOR(pinata, cvar("g_pinata") && !cvar("g_instagib") && !cvar("g_ove
 MUTATOR_HOOKFUNCTION(pinata, PlayerDies)
 {
        entity frag_target = M_ARGV(2, entity);
-       
+
        FOREACH(Weapons, it != WEP_Null, LAMBDA(
                if(frag_target.weapons & WepSet_FromWeapon(it))
                if(PS(frag_target).m_switchweapon != it)
index a384a2b9c2284923d987181ca4bea8fe4c6f83e9..9706aeca78dc1f564e5486f9fe077a7745b88677 100644 (file)
@@ -35,7 +35,7 @@ MUTATOR_HOOKFUNCTION(random_gravity, SV_StartFrame)
 
        gravity_delay = time + autocvar_g_random_gravity_delay;
 
-       LOG_TRACE("Gravity is now: ", ftos(autocvar_sv_gravity), "\n");
+       LOG_TRACE("Gravity is now: ", ftos(autocvar_sv_gravity));
 }
 
 MUTATOR_HOOKFUNCTION(random_gravity, BuildMutatorsString)
index 6adc964be48374e6d109f0e902a09406b2122b01..577e29c6b07c21b497a1b93391cdade5525e280e 100644 (file)
@@ -217,7 +217,7 @@ void sandbox_ObjectRemove(entity e)
        if(e.netname)   {       strunzone(e.netname);   e.netname = string_null;        }
        if(e.message)   {       strunzone(e.message);   e.message = string_null;        }
        if(e.message2)  {       strunzone(e.message2);  e.message2 = string_null;       }
-       remove(e);
+       delete(e);
        e = NULL;
 
        object_count -= 1;
index 786796866cdc0e0335b4f091223418393682d6d8..947ff01bb717a9557615c175f6470a638ed455a1 100644 (file)
@@ -47,7 +47,7 @@ void superspec_save_client_conf(entity this)
        fh = fopen(fn, FILE_WRITE);
        if(fh < 0)
        {
-               LOG_TRACE("^1ERROR: ^7 superspec can not open ", fn, " for writing.\n");
+               LOG_TRACE("^1ERROR: ^7 superspec can not open ", fn, " for writing.");
        }
        else
        {
@@ -383,7 +383,7 @@ void superspec_hello(entity this)
        if(this.enemy.crypto_idfp == "")
                Send_Notification(NOTIF_ONE_ONLY, this.enemy, MSG_INFO, INFO_SUPERSPEC_MISSING_UID);
 
-       remove(this);
+       delete(this);
 }
 
 MUTATOR_HOOKFUNCTION(superspec, ClientConnect)
@@ -415,14 +415,14 @@ MUTATOR_HOOKFUNCTION(superspec, ClientConnect)
        fh = fopen(fn, FILE_READ);
        if(fh < 0)
        {
-               LOG_TRACE("^1ERROR: ^7 superspec can not open ", fn, " for reading.\n");
+               LOG_TRACE("^1ERROR: ^7 superspec can not open ", fn, " for reading.");
        }
        else
        {
                string _magic = fgets(fh);
                if(_magic != _SSMAGIX)
                {
-                       LOG_TRACE("^1ERROR^7 While reading superspec options file: unknown magic\n");
+                       LOG_TRACE("^1ERROR^7 While reading superspec options file: unknown magic");
                }
                else
                {
index 67e14403c5cfea8d47eda8c705cbf975d6c83e56..c585e7e9061872460920bc0ea3f6fc660c8ff374 100644 (file)
@@ -19,7 +19,7 @@ void PlayerTouchExplode(entity p1, entity p2)
        entity e = spawn();
        setorigin(e, org);
        RadiusDamage(e, NULL, autocvar_g_touchexplode_damage, autocvar_g_touchexplode_edgedamage, autocvar_g_touchexplode_radius, NULL, NULL, autocvar_g_touchexplode_force, DEATH_TOUCHEXPLODE.m_id, NULL);
-       remove(e);
+       delete(e);
 }
 
 MUTATOR_HOOKFUNCTION(touchexplode, PlayerPreThink)
index 2b28784b7cdb284e24ed71fa300f3ebf0b24c701..4645130551a3c1f4b6be52fb83771a790ee0de8f 100644 (file)
@@ -12,11 +12,11 @@ REGISTRY_CHECK(Waypoints)
 #define REGISTER_WAYPOINT_(id, init) REGISTER(Waypoints, WP, id, m_id, init)
 
 CLASS(Waypoint, Object)
-    ATTRIB(Waypoint, m_id, int, 0)
-    ATTRIB(Waypoint, netname, string, string_null)
-    ATTRIB(Waypoint, m_name, string, string_null)
-    ATTRIB(Waypoint, m_color, vector, '1 1 1')
-    ATTRIB(Waypoint, m_blink, int, 1)
+    ATTRIB(Waypoint, m_id, int, 0);
+    ATTRIB(Waypoint, netname, string);
+    ATTRIB(Waypoint, m_name, string);
+    ATTRIB(Waypoint, m_color, vector, '1 1 1');
+    ATTRIB(Waypoint, m_blink, int, 1);
     CONSTRUCTOR(Waypoint, string _netname, string _name, vector _color, int _blink) {
         CONSTRUCT(Waypoint);
         this.netname = _netname;
index 1422f7c0d7498b80b64267e4978d83addd375714..e99303823b9eb44e4efab3daf17fbb72692fba32 100644 (file)
@@ -459,7 +459,7 @@ vector fixrgbexcess(vector rgb)
 
 void Draw_WaypointSprite(entity this)
 {
-    if (this.lifetime)
+    if (this.lifetime > 0)
         this.alpha = pow(bound(0, (this.fadetime - time) / this.lifetime, 1), waypointsprite_timealphaexponent);
     else
         this.alpha = 1;
@@ -470,14 +470,12 @@ void Draw_WaypointSprite(entity this)
     if (autocvar_cl_hidewaypoints >= 2)
         return;
 
-    if (this.hideflags & 1)
-        if (autocvar_cl_hidewaypoints)
-            return; // fixed waypoint
+    if (this.hideflags & 1 && autocvar_cl_hidewaypoints)
+        return; // fixed waypoint
 
     InterpolateOrigin_Do(this);
 
     float t = entcs_GetTeam(player_localnum) + 1;
-
     string spriteimage = "";
 
     // choose the sprite
@@ -486,7 +484,7 @@ void Draw_WaypointSprite(entity this)
         case SPRITERULE_SPECTATOR:
             if (!(
                 (autocvar_g_waypointsprite_itemstime == 1 && t == NUM_SPECTATOR + 1)
-            || (autocvar_g_waypointsprite_itemstime == 2 && (t == NUM_SPECTATOR + 1 || warmup_stage))
+            || (autocvar_g_waypointsprite_itemstime == 2 && (t == NUM_SPECTATOR + 1 || warmup_stage || STAT(ITEMSTIME) == 2))
                 ))
                 return;
             spriteimage = this.netname;
@@ -520,11 +518,8 @@ void Draw_WaypointSprite(entity this)
 
     ++waypointsprite_newcount;
 
-    float dist;
-    dist = vlen(this.origin - view_origin);
-
-    float a;
-    a = this.alpha * autocvar_hud_panel_fg_alpha;
+    float dist = vlen(this.origin - view_origin);
+    float a = this.alpha * autocvar_hud_panel_fg_alpha;
 
     if (this.maxdistance > waypointsprite_normdistance)
         a *= pow(bound(0, (this.maxdistance - dist) / (this.maxdistance - waypointsprite_normdistance), 1), waypointsprite_distancealphaexponent);
@@ -542,7 +537,7 @@ void Draw_WaypointSprite(entity this)
     {
         if (this.helpme && time < this.helpme)
             a *= SPRITE_HELPME_BLINK;
-        else if (!this.lifetime) // fading out waypoints don't blink
+        else if (this.lifetime > 0) // fading out waypoints don't blink
             a *= spritelookupblinkvalue(this, spriteimage);
     }
 
@@ -868,9 +863,10 @@ void WaypointSprite_FadeOutIn(entity e, float t)
         // ensure:
         //   (e.teleport_time - time) / wp.fade_time stays
         //   e.teleport_time = time + fadetime
-        float current_fadetime;
-        current_fadetime = e.teleport_time - time;
+        float current_fadetime = e.teleport_time - time;
         e.teleport_time = time + t;
+        if (e.fade_time < 0)
+               e.fade_time = -e.fade_time;
         e.fade_time = e.fade_time * t / current_fadetime;
     }
 
@@ -888,7 +884,7 @@ void WaypointSprite_Kill(entity wp)
 {
     if (!wp) return;
     if (wp.owner) wp.owner.(wp.owned_by_field) = NULL;
-    remove(wp);
+    delete(wp);
 }
 
 void WaypointSprite_Disown(entity wp, float fadetime)
@@ -1004,8 +1000,10 @@ entity WaypointSprite_Spawn(
 )
 {
     entity wp = new(sprite_waypoint);
+    wp.fade_time = _lifetime; // if negative tells client not to fade it out
+    if(_lifetime < 0)
+       _lifetime = -_lifetime;
     wp.teleport_time = time + _lifetime;
-    wp.fade_time = _lifetime;
     wp.exteriormodeltoclient = ref;
     if (ref)
     {
@@ -1021,7 +1019,7 @@ entity WaypointSprite_Spawn(
     if (own)
     {
         if (own.(ownfield))
-            remove(own.(ownfield));
+            delete(own.(ownfield));
         own.(ownfield) = wp;
         wp.owned_by_field = ownfield;
     }
index b36f631fe2a17676c452e272f8176290d09d29eb..1134205185474bda2be0142568448d3e711ac494 100644 (file)
@@ -1,5 +1,4 @@
-#ifndef NET_NOTICE_H
-#define NET_NOTICE_H
+#pragma once
 
 #ifdef SVQC
 string autocvar_sv_join_notices;
@@ -13,5 +12,3 @@ void sv_notice_join(entity _to);
 #ifdef CSQC
 void cl_notice_read();
 #endif
-
-#endif
index 25c7c63befde9fbdf268584be2110c3f5ee553e4..b9f7b36a91302663bb27857caae3fb061d9c0452 100644 (file)
     MSG_CENTER_NOTIF(CTF_PASS_OTHER_NEUTRAL,            1,      2, 0, "s1 s2",          CPID_CTF_PASS,          "0 0",  _("^BG%s^BG passed the flag to %s"), "")
     MULTITEAM_CENTER(CTF_PASS_RECEIVED, 4,              1,      1, 0, "s1",             CPID_CTF_PASS,          "0 0",  _("^BGYou received the ^TC^TT^BG flag from %s"), "", FLAG)
     MSG_CENTER_NOTIF(CTF_PASS_RECEIVED_NEUTRAL,         1,      1, 0, "s1",             CPID_CTF_PASS,          "0 0",  _("^BGYou received the flag from %s"), "")
-    MSG_CENTER_NOTIF(CTF_PASS_REQUESTED,                1,      1, 0, "s1 pass_key",    CPID_CTF_PASS,          "0 0",  _("^BG%s^BG requests you to pass the flag%s"), "")
+    MSG_CENTER_NOTIF(CTF_PASS_REQUESTED,                1,      1, 0, "pass_key s1",    CPID_CTF_PASS,          "0 0",  _("^BGPress ^F2%s^BG to receive the flag from %s^BG"), "")
     MSG_CENTER_NOTIF(CTF_PASS_REQUESTING,               1,      1, 0, "s1",             CPID_CTF_PASS,          "0 0",  _("^BGRequesting %s^BG to pass you the flag"), "")
     MULTITEAM_CENTER(CTF_PASS_SENT, 4,                  1,      1, 0, "s1",             CPID_CTF_PASS,          "0 0",  _("^BGYou passed the ^TC^TT^BG flag to %s"), "", FLAG)
     MSG_CENTER_NOTIF(CTF_PASS_SENT_NEUTRAL,             1,      1, 0, "s1",             CPID_CTF_PASS,          "0 0",  _("^BGYou passed the flag to %s"), "")
     MSG_CENTER_NOTIF(ONS_GENERATOR_SHIELDED,            1,      0, 0, "",               CPID_ONS_CAPSHIELD,     "0 0",  _("^BGThe enemy generator cannot be destroyed yet\n^F2Capture some control points to unshield it"), "")
     MULTITEAM_CENTER(ONS_NOTSHIELDED, 4,                1,      0, 0, "",               CPID_ONSLAUGHT,         "0 0",  _("^BGThe ^TCenemy^BG generator is no longer shielded!"), "", NAME)
     MSG_CENTER_NOTIF(ONS_NOTSHIELDED_TEAM,              1,      0, 0, "",               CPID_ONSLAUGHT,         "0 0",  _("^K1Your generator is NOT shielded!\n^BGRe-capture control points to shield it!"), "")
-    MSG_CENTER_NOTIF(ONS_TELEPORT,                      1,      0, 0, "pass_key",       CPID_ONSLAUGHT,         "0 0",  _("^BGPress ^F2DROPFLAG%s^BG to teleport"), "")
+    MSG_CENTER_NOTIF(ONS_TELEPORT,                      1,      0, 0, "pass_key",       CPID_ONSLAUGHT,         "0 0",  _("^BGPress ^F2%s^BG to teleport"), "")
     MSG_CENTER_NOTIF(ONS_TELEPORT_ANTISPAM,             1,      0, 1, "f1secs",         CPID_ONSLAUGHT,         "0 0",  _("^BGTeleporting disabled for %s"), "")
 
     MSG_CENTER_NOTIF(OVERTIME_FRAG,                     1,      0, 0, "",               CPID_OVERTIME,          "0 0",  _("^F2Now playing ^F4OVERTIME^F2!\nKeep fragging until we have a winner!"), _("^F2Now playing ^F4OVERTIME^F2!\nKeep scoring until we have a winner!"))
 
     MSG_CENTER_NOTIF(JOIN_PREVENT_MINIGAME,             1,      0, 0, "",               CPID_Null,              "0 0",  _("^K1Cannot join given minigame session!"), "" )
 
-    MSG_CENTER_NOTIF(VEHICLE_ENTER,                     1,      0, 0, "pass_key",       CPID_VEHICLES,          "0 0",  _("^BGPress ^F2DROPFLAG%s^BG to enter/exit the vehicle"), "")
-    MSG_CENTER_NOTIF(VEHICLE_ENTER_GUNNER,              1,      0, 0, "pass_key",       CPID_VEHICLES,          "0 0",  _("^BGPress ^F2DROPFLAG%s^BG to enter the vehicle gunner"), "")
-    MSG_CENTER_NOTIF(VEHICLE_ENTER_STEAL,               1,      0, 0, "pass_key",       CPID_VEHICLES,          "0 0",  _("^BGPress ^F2DROPFLAG%s^BG to steal this vehicle"), "")
+    MSG_CENTER_NOTIF(VEHICLE_ENTER,                     1,      0, 0, "pass_key",       CPID_VEHICLES,          "0 0",  _("^BGPress ^F2%s^BG to enter/exit the vehicle"), "")
+    MSG_CENTER_NOTIF(VEHICLE_ENTER_GUNNER,              1,      0, 0, "pass_key",       CPID_VEHICLES,          "0 0",  _("^BGPress ^F2%s^BG to enter the vehicle gunner"), "")
+    MSG_CENTER_NOTIF(VEHICLE_ENTER_STEAL,               1,      0, 0, "pass_key",       CPID_VEHICLES,          "0 0",  _("^BGPress ^F2%s^BG to steal this vehicle"), "")
     MSG_CENTER_NOTIF(VEHICLE_STEAL,                     1,      0, 0, "",               CPID_VEHICLES_OTHER,    "0 0",  _("^F2The enemy is stealing one of your vehicles!\n^F4Stop them!"), "")
     MSG_CENTER_NOTIF(VEHICLE_STEAL_SELF,                1,      0, 0, "",               CPID_VEHICLES_OTHER,    "4 0",  _("^F2You have stolen the enemy's vehicle, you are now visible on their radar!"), "")
 
index 853280d6e023410758388258c2543e15beff954d..e4f082355bd9ad47d184b50a33f11116c26e3d78 100644 (file)
@@ -153,7 +153,7 @@ void Destroy_Notification_Entity(entity notif)
        if (notif.nent_icon != "") strunzone(notif.nent_icon);
        if (notif.nent_durcnt != "") strunzone(notif.nent_durcnt);
        if (notif.nent_string != "") strunzone(notif.nent_string);
-       remove(notif);
+       delete(notif);
 }
 
 void Destroy_All_Notifications()
@@ -572,7 +572,7 @@ void Create_Notification_Entity_InfoCenter(entity notif,
                                }
                                else if(icon != "")
                                {
-                                       LOG_WARNINGF(
+                                       LOG_WARNF(
                                                (
                                                        "^1NOTIFICATION HAS ICON BUT NO HUDARGS: "
                                                        "^7net_type = %s, net_name = %s.\n"
@@ -589,7 +589,7 @@ void Create_Notification_Entity_InfoCenter(entity notif,
 
                                        if (cpid == CPID_Null && durcnt != "0 0")
                                        {
-                                               LOG_WARNINGF(
+                                               LOG_WARNF(
                                                        (
                                                                "Notification has durcnt but no cpid: "
                                                                "net_type = %s, net_name = %s."
@@ -1210,7 +1210,7 @@ void Local_Notification(MSG net_type, Notification net_name, ...count)
                        Get_Notif_TypeName(net_type)
                ));
                #endif
-               LOG_WARNINGF("Incorrect usage of Local_Notification: %s\n", "Null notification");
+               LOG_WARNF("Incorrect usage of Local_Notification: %s", "Null notification");
                return;
        }
 
@@ -1491,7 +1491,7 @@ void Net_Notification_Remove(entity this)
        ));
        #endif
        for (int i = 0; i < this.nent_stringcount; ++i) { if (this.nent_strings[i]) strunzone(this.nent_strings[i]); }
-       remove(this);
+       delete(this);
 }
 
 bool Net_Write_Notification(entity this, entity client, int sf)
@@ -1523,7 +1523,7 @@ void Kill_Notification(
        #endif
 
        string checkargs = Notification_CheckArgs(broadcast, client);
-       if (checkargs != "") { LOG_WARNINGF("Incorrect usage of Kill_Notification: %s", checkargs); return; }
+       if (checkargs != "") { LOG_WARNF("Incorrect usage of Kill_Notification: %s", checkargs); return; }
 
        entity net_notif = new_pure(net_kill_notification);
        net_notif.nent_broadcast = broadcast;
@@ -1561,7 +1561,7 @@ void Send_Notification(
 
        if (!notif)
        {
-               LOG_WARNING("Send_Notification: Could not find notification entity!");
+               LOG_WARN("Send_Notification: Could not find notification entity!");
                return;
        }
 
@@ -1570,7 +1570,7 @@ void Send_Notification(
     if (!net_name) { checkargs = sprintf("No notification provided! %s", checkargs); }
        if (checkargs != "")
        {
-               LOG_WARNINGF("Incorrect usage of Send_Notification: %s", checkargs);
+               LOG_WARNF("Incorrect usage of Send_Notification: %s", checkargs);
                return;
        }
 
@@ -1594,7 +1594,7 @@ void Send_Notification(
 
        if ((notif.nent_stringcount + notif.nent_floatcount) != count)
        {
-               LOG_WARNINGF(
+               LOG_WARNF(
                        "Argument mismatch for Send_Notification(%s, ...)! "
                        "stringcount(%d) + floatcount(%d) != count(%d)\n"
                        "Check the definition and function call for accuracy...?\n",
index 7dcfec3534549fa9462be965e25abe06795d6f04..983b69f3f4562b3a6a96363ef94543940de4f983 100644 (file)
@@ -1,5 +1,4 @@
-#ifndef NOTIFICATIONS_H
-#define NOTIFICATIONS_H
+#pragma once
 
 #include <common/command/all.qh>
 
@@ -33,7 +32,7 @@ string Get_Notif_TypeName(MSG net_type)
                case MSG_MULTI: return "MSG_MULTI";
                case MSG_CHOICE: return "MSG_CHOICE";
        }
-       LOG_WARNINGF("Get_Notif_TypeName(%d): Improper net type!\n", ORDINAL(net_type));
+       LOG_WARNF("Get_Notif_TypeName(%d): Improper net type!", ORDINAL(net_type));
        return "";
 }
 
@@ -253,7 +252,7 @@ string Get_Notif_BroadcastName(NOTIF broadcast)
                case NOTIF_TEAM: return "NOTIF_TEAM";
                case NOTIF_TEAM_EXCEPT: return "NOTIF_TEAM_EXCEPT";
        }
-       LOG_WARNINGF("Get_Notif_BroadcastName(%d): Improper broadcast!\n", broadcast);
+       LOG_WARNF("Get_Notif_BroadcastName(%d): Improper broadcast!", broadcast);
        return "";
 }
 
@@ -408,7 +407,7 @@ string BUFF_NAME(int i);
        ARG_CASE(ARG_CS_SV,     "race_col",      CCR(((f1 == 1) ? "^F1" : "^F2"))) \
        ARG_CASE(ARG_CS_SV,     "race_diff",     ((f2 > f3) ? sprintf(CCR("^1[+%s]"), mmssss(f2 - f3)) : sprintf(CCR("^2[-%s]"), mmssss(f3 - f2)))) \
        ARG_CASE(ARG_CS,        "missing_teams", notif_arg_missing_teams(f1)) \
-       ARG_CASE(ARG_CS,        "pass_key",      ((((tmp_s = getcommandkey("pass", "+use")) != "pass") && !(strstrofs(tmp_s, "not bound", 0) >= 0)) ? sprintf(CCR(_(" ^F1(Press %s)")), tmp_s) : "")) \
+       ARG_CASE(ARG_CS,        "pass_key",      getcommandkey(_("drop flag"), "+use")) \
        ARG_CASE(ARG_CS,        "frag_ping",     notif_arg_frag_ping(true, f2)) \
        ARG_CASE(ARG_CS,        "frag_stats",    notif_arg_frag_stats(f2, f3, f4)) \
        /*ARG_CASE(ARG_CS,      "frag_pos",      ((Should_Print_Score_Pos(f1)) ? sprintf("\n^BG%s", Read_Score_Pos(f1)) : ""))*/ \
@@ -685,7 +684,7 @@ Notification Get_Notif_Ent(MSG net_type, int net_name)
 {
        Notification it = _Notifications_from(net_name, NULL);
        if (it.nent_type != net_type) {
-               LOG_WARNINGF("Get_Notif_Ent(%s (%d), %s (%d)): Improper net type '%s'!\n",
+               LOG_WARNF("Get_Notif_Ent(%s (%d), %s (%d)): Improper net type '%s'!",
                        Get_Notif_TypeName(net_type), net_type,
                        it.registered_id, net_name,
                        Get_Notif_TypeName(it.nent_type)
@@ -800,5 +799,3 @@ REGISTRY_END(Notifications)
 }
 
 #include "all.inc"
-
-#endif
index 250c3ba2b28e121d7e4568a4a87baf134d5ac45b..e0659a40c197ffcbeeffb775a974682974466212 100644 (file)
@@ -1,5 +1,4 @@
-#ifndef MOVELIB_H
-#define MOVELIB_H
+#pragma once
 
 #ifdef SVQC
 .vector moveto;
@@ -49,5 +48,3 @@ Yed need to set v_up and v_forward (generally by calling makevectors) before cal
 #endif
 
 void movelib_groundalign4point(entity this, float spring_length, float spring_up, float blendrate, float _max);
-
-#endif
index 090144dd16069f16573489d72f8a8cae53c7cdb0..1810fb841d3126ec2b1811915d963da2f9aeaa56 100644 (file)
 #ifdef SVQC
 void set_movetype(entity this, int mt)
 {
-       if(mt == MOVETYPE_PHYSICS || mt == MOVETYPE_PUSH || mt == MOVETYPE_FAKEPUSH)
-       {
-               this.movetype = this.move_movetype = mt; // we still set move_movetype, for other code that checks movetype
+       this.move_movetype = mt;
+       if (mt == MOVETYPE_PHYSICS || mt == MOVETYPE_PUSH || mt == MOVETYPE_FAKEPUSH) {
                this.move_qcphysics = false;
-               return;
        }
-
-       this.move_movetype = mt;
-
-       if(!this.move_qcphysics)
+       if (!this.move_qcphysics) {
                this.movetype = mt;
+       }
 }
 #elif defined(CSQC)
 void set_movetype(entity this, int mt)
@@ -452,12 +448,12 @@ bool _Movetype_UnstickEntity(entity this)  // SV_UnstickEntity
         X(17)
         #undef X
         {
-            LOG_DEBUGF("Can't unstick an entity (edict: %d, classname: %s, origin: %s)\n",
+            LOG_DEBUGF("Can't unstick an entity (edict: %d, classname: %s, origin: %s)",
                 etof(this), this.classname, vtos(this.origin));
             return false;
         }
        }
-       LOG_DEBUGF("Sucessfully unstuck an entity (edict: %d, classname: %s, origin: %s)\n",
+       LOG_DEBUGF("Sucessfully unstuck an entity (edict: %d, classname: %s, origin: %s)",
                etof(this), this.classname, vtos(this.origin));
        _Movetype_LinkEdict(this, true);
        return true;
@@ -573,7 +569,7 @@ void _Movetype_Physics_Frame(entity this, float movedt)
        {
                case MOVETYPE_PUSH:
                case MOVETYPE_FAKEPUSH:
-                       LOG_DEBUGF("Physics: Lacking QuakeC support for Push movetype, FIX ME by using engine physics!\n");
+                       LOG_DEBUGF("Physics: Lacking QuakeC support for Push movetype, FIX ME by using engine physics!");
                        break;
                case MOVETYPE_NONE:
                        break;
@@ -613,7 +609,7 @@ void _Movetype_Physics_ClientFrame(entity this, float movedt)
        {
                case MOVETYPE_PUSH:
                case MOVETYPE_FAKEPUSH:
-                       LOG_DEBUGF("Physics: Lacking QuakeC support for Push movetype, FIX ME by using engine physics!\n");
+                       LOG_DEBUGF("Physics: Lacking QuakeC support for Push movetype, FIX ME by using engine physics!");
                        break;
                case MOVETYPE_NONE:
                        break;
index 6b75d81c02eac80ec652a958c0903eef7e936689..db5d29cefda9ec18af34da81e6e57708630c53a4 100644 (file)
@@ -1,5 +1,4 @@
-#ifndef MOVETYPES_H
-#define MOVETYPES_H
+#pragma once
 
 #define IS_ONGROUND(s)                      boolean((s).flags & FL_ONGROUND)
 #define SET_ONGROUND(s)                     ((s).flags |= FL_ONGROUND)
@@ -10,10 +9,6 @@
 .float bouncefactor;
 #endif
 
-#ifdef SVQC
-.bool move_qcphysics;
-#endif
-
 void set_movetype(entity this, int mt);
 
 .float move_movetype;
@@ -94,5 +89,3 @@ const int MOVEFLAG_GRAVITYUNAFFECTEDBYTICRATE = BIT(2);
 #ifdef CSQC
 #define moveflags STAT(MOVEFLAGS)
 #endif
-
-#endif
index 1ef5faa59d87554dd9bad0d251e1ce687fa0c205..4fe8c88f516bc9425abc6b3ac0a2e5dd7c2a597d 100644 (file)
@@ -134,10 +134,6 @@ void PM_ClientMovement_UpdateStatus(entity this)
                do_crouch = false;
        if(STAT(FROZEN, this))
                do_crouch = false;
-       if((activeweapon.spawnflags & WEP_TYPE_MELEE_PRI) && viewmodel.animstate_startframe == viewmodel.anim_fire1_x && time < viewmodel.weapon_nextthink)
-               do_crouch = false;
-       if((activeweapon.spawnflags & WEP_TYPE_MELEE_SEC) && viewmodel.animstate_startframe == viewmodel.anim_fire2_x && time < viewmodel.weapon_nextthink)
-               do_crouch = false;
 
        if (do_crouch)
        {
@@ -154,12 +150,12 @@ void PM_ClientMovement_UpdateStatus(entity this)
                }
        }
 
-       if (IS_ONGROUND(this) || this.velocity.z <= 0 || pmove_waterjumptime <= 0)
-               pmove_waterjumptime = 0;
+       if (IS_ONGROUND(this) || this.velocity.z <= 0 || PHYS_WATERJUMP_TIME(this) <= 0)
+               PHYS_WATERJUMP_TIME(this) = 0;
 #endif
 }
 
-void CPM_PM_Aircontrol(entity this, vector wishdir, float wishspeed)
+void CPM_PM_Aircontrol(entity this, float dt, vector wishdir, float wishspeed)
 {
        float k = 32 * (2 * IsMoveInDirection(this.movement, 0) - 1);
        if (k <= 0)
@@ -176,7 +172,7 @@ void CPM_PM_Aircontrol(entity this, vector wishdir, float wishspeed)
 
        if (dot > 0) // we can't change direction while slowing down
        {
-               k *= pow(dot, PHYS_AIRCONTROL_POWER(this)) * PHYS_INPUT_TIMELENGTH;
+               k *= pow(dot, PHYS_AIRCONTROL_POWER(this)) * dt;
                xyspeed = max(0, xyspeed - PHYS_AIRCONTROL_PENALTY(this) * sqrt(max(0, 1 - dot*dot)) * k/32);
                k *= PHYS_AIRCONTROL(this);
                this.velocity = normalize(this.velocity * xyspeed + wishdir * k);
@@ -196,7 +192,7 @@ float AdjustAirAccelQW(float accelqw, float factor)
 //   sv_airaccel_sideways_friction 0
 //   prvm_globalset server speedclamp_mode 1
 //     (or 2)
-void PM_Accelerate(entity this, vector wishdir, float wishspeed, float wishspeed0, float accel, float accelqw, float stretchfactor, float sidefric, float speedlimit)
+void PM_Accelerate(entity this, float dt, 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
@@ -212,7 +208,7 @@ void PM_Accelerate(entity this, vector wishdir, float wishspeed, float wishspeed
        vector vel_xy = vec2(this.velocity);
        vector vel_perpend = vel_xy - vel_straight * wishdir;
 
-       float step = accel * PHYS_INPUT_TIMELENGTH * wishspeed0;
+       float step = accel * dt * wishspeed0;
 
        float vel_xy_current  = vlen(vel_xy);
        if (speedlimit)
@@ -225,7 +221,7 @@ void PM_Accelerate(entity this, vector wishdir, float wishspeed, float wishspeed
        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 f = max(0, 1 + dt * wishspeed * sidefric);
                float themin = (vel_xy_backward * vel_xy_backward - vel_straight * vel_straight) / (vel_perpend * vel_perpend);
                // assume: themin > 1
                // vel_xy_backward*vel_xy_backward - vel_straight*vel_straight > vel_perpend*vel_perpend
@@ -241,7 +237,7 @@ void PM_Accelerate(entity this, vector wishdir, float wishspeed, float wishspeed
                }
        }
        else
-               vel_perpend *= max(0, 1 - PHYS_INPUT_TIMELENGTH * wishspeed * sidefric);
+               vel_perpend *= max(0, 1 - dt * wishspeed * sidefric);
 
        vel_xy = vel_straight * wishdir + vel_perpend;
 
@@ -260,7 +256,7 @@ void PM_Accelerate(entity this, vector wishdir, float wishspeed, float wishspeed
        this.velocity = vel_xy + vel_z * '0 0 1';
 }
 
-void PM_AirAccelerate(entity this, vector wishdir, float wishspeed)
+void PM_AirAccelerate(entity this, float dt, vector wishdir, float wishspeed)
 {
        if (wishspeed == 0)
                return;
@@ -270,18 +266,18 @@ void PM_AirAccelerate(entity this, vector wishdir, float wishspeed)
        float curspeed = vlen(curvel);
 
        if (wishspeed > curspeed * 1.01)
-               wishspeed = min(wishspeed, curspeed + PHYS_WARSOWBUNNY_AIRFORWARDACCEL(this) * PHYS_MAXSPEED(this) * PHYS_INPUT_TIMELENGTH);
+               wishspeed = min(wishspeed, curspeed + PHYS_WARSOWBUNNY_AIRFORWARDACCEL(this) * PHYS_MAXSPEED(this) * dt);
        else
        {
                float f = max(0, (PHYS_WARSOWBUNNY_TOPSPEED(this) - curspeed) / (PHYS_WARSOWBUNNY_TOPSPEED(this) - PHYS_MAXSPEED(this)));
-               wishspeed = max(curspeed, PHYS_MAXSPEED(this)) + PHYS_WARSOWBUNNY_ACCEL(this) * f * PHYS_MAXSPEED(this) * PHYS_INPUT_TIMELENGTH;
+               wishspeed = max(curspeed, PHYS_MAXSPEED(this)) + PHYS_WARSOWBUNNY_ACCEL(this) * f * PHYS_MAXSPEED(this) * dt;
        }
        vector wishvel = wishdir * wishspeed;
        vector acceldir = wishvel - curvel;
        float addspeed = vlen(acceldir);
        acceldir = normalize(acceldir);
 
-       float accelspeed = min(addspeed, PHYS_WARSOWBUNNY_TURNACCEL(this) * PHYS_MAXSPEED(this) * PHYS_INPUT_TIMELENGTH);
+       float accelspeed = min(addspeed, PHYS_WARSOWBUNNY_TURNACCEL(this) * PHYS_MAXSPEED(this) * dt);
 
        if (PHYS_WARSOWBUNNY_BACKTOSIDERATIO(this) < 1)
        {
@@ -378,7 +374,7 @@ bool PlayerJump(entity this)
        {
 #ifdef SVQC
                if(autocvar_speedmeter)
-                       LOG_TRACE(strcat("landing velocity: ", vtos(this.velocity), " (abs: ", ftos(vlen(this.velocity)), ")\n"));
+                       LOG_TRACE("landing velocity: ", vtos(this.velocity), " (abs: ", ftos(vlen(this.velocity)), ")");
 #endif
                if(this.lastground < time - 0.3)
                {
@@ -388,7 +384,7 @@ bool PlayerJump(entity this)
                }
 #ifdef SVQC
                if(this.jumppadcount > 1)
-                       LOG_TRACE(strcat(ftos(this.jumppadcount), "x jumppad combo\n"));
+                       LOG_TRACE(ftos(this.jumppadcount), "x jumppad combo");
                this.jumppadcount = 0;
 #endif
        }
@@ -434,7 +430,7 @@ void CheckWaterJump(entity this)
                #ifdef SVQC
                        PHYS_TELEPORT_TIME(this) = time + 2;    // safety net
                #elif defined(CSQC)
-                       pmove_waterjumptime = 2;
+                       PHYS_WATERJUMP_TIME(this) = 2;
                #endif
                }
        }
@@ -579,12 +575,12 @@ void PM_check_nickspam(entity this)
 #endif
 }
 
-void PM_check_punch(entity this)
+void PM_check_punch(entity this, float dt)
 {
 #ifdef SVQC
        if (this.punchangle != '0 0 0')
        {
-               float f = vlen(this.punchangle) - 10 * PHYS_INPUT_TIMELENGTH;
+               float f = vlen(this.punchangle) - 10 * dt;
                if (f > 0)
                        this.punchangle = normalize(this.punchangle) * f;
                else
@@ -593,7 +589,7 @@ void PM_check_punch(entity this)
 
        if (this.punchvector != '0 0 0')
        {
-               float f = vlen(this.punchvector) - 30 * PHYS_INPUT_TIMELENGTH;
+               float f = vlen(this.punchvector) - 30 * dt;
                if (f > 0)
                        this.punchvector = normalize(this.punchvector) * f;
                else
@@ -681,184 +677,9 @@ void PM_check_blocked(entity this)
 #endif
 }
 
-void PM_fly(entity this, float maxspd_mod)
-{
-       // noclipping or flying
-       UNSET_ONGROUND(this);
-
-       this.velocity = this.velocity * (1 - PHYS_INPUT_TIMELENGTH * PHYS_FRICTION(this));
-       makevectors(this.v_angle);
-       //wishvel = v_forward * this.movement.x + v_right * this.movement.y + v_up * this.movement.z;
-       vector wishvel = v_forward * this.movement.x
-                                       + v_right * this.movement.y
-                                       + '0 0 1' * this.movement.z;
-       // acceleration
-       vector wishdir = normalize(wishvel);
-       float wishspeed = min(vlen(wishvel), PHYS_MAXSPEED(this) * maxspd_mod);
-#ifdef SVQC
-       if(time >= PHYS_TELEPORT_TIME(this))
-#elif defined(CSQC)
-       if(pmove_waterjumptime <= 0)
-#endif
-               PM_Accelerate(this, wishdir, wishspeed, wishspeed, PHYS_ACCELERATE(this) * maxspd_mod, 1, 0, 0, 0);
-}
-
-void PM_swim(entity this, float maxspd_mod)
-{
-       // swimming
-       UNSET_ONGROUND(this);
-
-       float jump = PHYS_INPUT_BUTTON_JUMP(this);
-       // water jump only in certain situations
-       // this mimics quakeworld code
-       if (jump && this.waterlevel == WATERLEVEL_SWIMMING && this.velocity_z >= -180 && !this.viewloc)
-       {
-               vector yawangles = '0 1 0' * this.v_angle.y;
-               makevectors(yawangles);
-               vector forward = v_forward;
-               vector spot = this.origin + 24 * forward;
-               spot_z += 8;
-               traceline(spot, spot, MOVE_NOMONSTERS, this);
-               if (trace_startsolid)
-               {
-                       spot_z += 24;
-                       traceline(spot, spot, MOVE_NOMONSTERS, this);
-                       if (!trace_startsolid)
-                       {
-                               this.velocity = forward * 50;
-                               this.velocity_z = 310;
-                               UNSET_ONGROUND(this);
-                               SET_JUMP_HELD(this);
-                       }
-               }
-       }
-       makevectors(this.v_angle);
-       float wishdown = this.movement.z;
-       if(PHYS_INPUT_BUTTON_CROUCH(this))
-               wishdown = -PHYS_MAXSPEED(this);
-       //wishvel = v_forward * this.movement.x + v_right * this.movement.y + v_up * this.movement.z;
-       vector wishvel = v_forward * this.movement.x
-                                       + v_right * this.movement.y
-                                       + '0 0 1' * wishdown;
-       if(this.viewloc)
-               wishvel.z = -160; // drift anyway
-       else if (wishvel == '0 0 0')
-               wishvel = '0 0 -60'; // drift towards bottom
-
-       vector wishdir = normalize(wishvel);
-       float wishspeed = min(vlen(wishvel), PHYS_MAXSPEED(this) * maxspd_mod) * 0.7;
-
-//     if (pmove_waterjumptime <= 0) // TODO: use
-    {
-               // water friction
-               float f = 1 - PHYS_INPUT_TIMELENGTH * PHYS_FRICTION(this);
-               f = min(max(0, f), 1);
-               this.velocity *= f;
-
-               f = wishspeed - this.velocity * wishdir;
-               if (f > 0)
-               {
-                       float accelspeed = min(PHYS_ACCELERATE(this) * PHYS_INPUT_TIMELENGTH * wishspeed, f);
-                       this.velocity += accelspeed * wishdir;
-               }
-
-               // holding jump button swims upward slowly
-               if (jump && !this.viewloc)
-               {
-#if 0
-                       if (this.watertype & CONTENT_LAVA)
-                               this.velocity_z =  50;
-                       else if (this.watertype & CONTENT_SLIME)
-                               this.velocity_z =  80;
-                       else
-                       {
-                               if (IS_NEXUIZ_DERIVED(gamemode))
-#endif
-                               if(this.waterlevel >= WATERLEVEL_SUBMERGED)
-                                       this.velocity_z = PHYS_MAXSPEED(this);
-                               else
-                                       this.velocity_z = 200;
-#if 0
-                               else
-                                       this.velocity_z = 100;
-                       }
-#endif
-               }
-       }
-       if(this.viewloc)
-       {
-               const float addspeed = wishspeed - this.velocity * wishdir;
-               if (addspeed > 0)
-               {
-                       const float accelspeed = min(PHYS_ACCELERATE(this) * PHYS_INPUT_TIMELENGTH * wishspeed, addspeed);
-                       this.velocity += accelspeed * wishdir;
-               }
-       }
-       else
-       {
-               // water acceleration
-               PM_Accelerate(this, wishdir, wishspeed, wishspeed, PHYS_ACCELERATE(this) * maxspd_mod, 1, 0, 0, 0);
-       }
-}
-
 .vector oldmovement;
-void PM_ladder(entity this, float maxspd_mod)
-{
-       // on a spawnfunc_func_ladder or swimming in spawnfunc_func_water
-       UNSET_ONGROUND(this);
-
-       float g;
-       g = PHYS_GRAVITY(this) * PHYS_INPUT_TIMELENGTH;
-       if (PHYS_ENTGRAVITY(this))
-               g *= PHYS_ENTGRAVITY(this);
-       if (GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE)
-       {
-               g *= 0.5;
-               this.velocity_z += g;
-       }
 
-       this.velocity = this.velocity * (1 - PHYS_INPUT_TIMELENGTH * PHYS_FRICTION(this));
-       makevectors(this.v_angle);
-       //wishvel = v_forward * this.movement.x + v_right * this.movement.y + v_up * this.movement.z;
-       vector wishvel = v_forward * this.movement_x
-                                       + v_right * this.movement_y
-                                       + '0 0 1' * this.movement_z;
-       if(this.viewloc)
-               wishvel.z = this.oldmovement.x;
-       this.velocity_z += g;
-       if (this.ladder_entity.classname == "func_water")
-       {
-               float f = vlen(wishvel);
-               if (f > this.ladder_entity.speed)
-                       wishvel *= (this.ladder_entity.speed / f);
-
-               this.watertype = this.ladder_entity.skin;
-               f = this.ladder_entity.origin_z + this.ladder_entity.maxs_z;
-               if ((this.origin_z + this.view_ofs_z) < f)
-                       this.waterlevel = WATERLEVEL_SUBMERGED;
-               else if ((this.origin_z + (this.mins_z + this.maxs_z) * 0.5) < f)
-                       this.waterlevel = WATERLEVEL_SWIMMING;
-               else if ((this.origin_z + this.mins_z + 1) < f)
-                       this.waterlevel = WATERLEVEL_WETFEET;
-               else
-               {
-                       this.waterlevel = WATERLEVEL_NONE;
-                       this.watertype = CONTENT_EMPTY;
-               }
-       }
-       // acceleration
-       vector wishdir = normalize(wishvel);
-       float wishspeed = min(vlen(wishvel), PHYS_MAXSPEED(this) * maxspd_mod);
-#ifdef SVQC
-       if(time >= PHYS_TELEPORT_TIME(this))
-#elif defined(CSQC)
-       if(pmove_waterjumptime <= 0)
-#endif
-               // water acceleration
-               PM_Accelerate(this, wishdir, wishspeed, wishspeed, PHYS_ACCELERATE(this)*maxspd_mod, 1, 0, 0, 0);
-}
-
-void PM_jetpack(entity this, float maxspd_mod)
+void PM_jetpack(entity this, float maxspd_mod, float dt)
 {
        //makevectors(this.v_angle.y * '0 1 0');
        makevectors(this.v_angle);
@@ -943,7 +764,7 @@ void PM_jetpack(entity this, float maxspd_mod)
 
        fvel = min(1, vlen(wishvel) / best);
        if (PHYS_JETPACK_FUEL(this) && !(ITEMS_STAT(this) & IT_UNLIMITED_WEAPON_AMMO))
-               f = min(1, PHYS_AMMO_FUEL(this) / (PHYS_JETPACK_FUEL(this) * PHYS_INPUT_TIMELENGTH * fvel));
+               f = min(1, PHYS_AMMO_FUEL(this) / (PHYS_JETPACK_FUEL(this) * dt * fvel));
        else
                f = 1;
 
@@ -951,12 +772,12 @@ void PM_jetpack(entity this, float maxspd_mod)
 
        if (f > 0 && wishvel != '0 0 0')
        {
-               this.velocity = this.velocity + wishvel * f * PHYS_INPUT_TIMELENGTH;
+               this.velocity = this.velocity + wishvel * f * dt;
                UNSET_ONGROUND(this);
 
 #ifdef SVQC
                if (!(ITEMS_STAT(this) & IT_UNLIMITED_WEAPON_AMMO))
-                       this.ammo_fuel -= PHYS_JETPACK_FUEL(this) * PHYS_INPUT_TIMELENGTH * fvel * f;
+                       this.ammo_fuel -= PHYS_JETPACK_FUEL(this) * dt * fvel * f;
 
                ITEMS_STAT(this) |= IT_USING_JETPACK;
 
@@ -966,146 +787,6 @@ void PM_jetpack(entity this, float maxspd_mod)
        }
 }
 
-void PM_walk(entity this, float maxspd_mod)
-{
-       if (!WAS_ONGROUND(this))
-       {
-#ifdef SVQC
-               if (autocvar_speedmeter)
-                       LOG_TRACE(strcat("landing velocity: ", vtos(this.velocity), " (abs: ", ftos(vlen(this.velocity)), ")\n"));
-#endif
-               if (this.lastground < time - 0.3)
-                       this.velocity *= (1 - PHYS_FRICTION_ONLAND(this));
-#ifdef SVQC
-               if (this.jumppadcount > 1)
-                       LOG_TRACE(strcat(ftos(this.jumppadcount), "x jumppad combo\n"));
-               this.jumppadcount = 0;
-#endif
-       }
-
-       // walking
-       makevectors(this.v_angle.y * '0 1 0');
-       const vector wishvel = v_forward * this.movement.x
-                                               + v_right * this.movement.y;
-       // acceleration
-       const vector wishdir = normalize(wishvel);
-       float wishspeed = vlen(wishvel);
-       wishspeed = min(wishspeed, PHYS_MAXSPEED(this) * maxspd_mod);
-       if (IS_DUCKED(this)) wishspeed *= 0.5;
-
-       // apply edge friction
-       const float f2 = vlen2(vec2(this.velocity));
-       if (f2 > 0)
-       {
-               trace_dphitq3surfaceflags = 0;
-               tracebox(this.origin, this.mins, this.maxs, this.origin - '0 0 1', MOVE_NOMONSTERS, this);
-               // TODO: apply edge friction
-               // apply ground friction
-               const int realfriction = (trace_dphitq3surfaceflags & Q3SURFACEFLAG_SLICK)
-                       ? PHYS_FRICTION_SLICK(this)
-                       : PHYS_FRICTION(this);
-
-               float f = sqrt(f2);
-               f = 1 - PHYS_INPUT_TIMELENGTH * realfriction * ((f < PHYS_STOPSPEED(this)) ? (PHYS_STOPSPEED(this) / f) : 1);
-               f = max(0, f);
-               this.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(this) / v0) * PHYS_FRICTION(this))
-                         = v0 - PHYS_INPUT_TIMELENGTH * PHYS_STOPSPEED(this) * PHYS_FRICTION(this)
-                       v0 = v + PHYS_INPUT_TIMELENGTH * PHYS_STOPSPEED(this) * PHYS_FRICTION(this)
-                  and
-                       v = v0 * (1 - PHYS_INPUT_TIMELENGTH * PHYS_FRICTION(this))
-                       v0 = v / (1 - PHYS_INPUT_TIMELENGTH * PHYS_FRICTION(this))
-
-                  These cases would be chosen ONLY if:
-                       v0 < PHYS_STOPSPEED(this)
-                       v + PHYS_INPUT_TIMELENGTH * PHYS_STOPSPEED(this) * PHYS_FRICTION(this) < PHYS_STOPSPEED(this)
-                       v < PHYS_STOPSPEED(this) * (1 - PHYS_INPUT_TIMELENGTH * PHYS_FRICTION(this))
-                  and, respectively:
-                       v0 >= PHYS_STOPSPEED(this)
-                       v / (1 - PHYS_INPUT_TIMELENGTH * PHYS_FRICTION(this)) >= PHYS_STOPSPEED(this)
-                       v >= PHYS_STOPSPEED(this) * (1 - PHYS_INPUT_TIMELENGTH * PHYS_FRICTION(this))
-                */
-       }
-       const float addspeed = wishspeed - this.velocity * wishdir;
-       if (addspeed > 0)
-       {
-               const float accelspeed = min(PHYS_ACCELERATE(this) * PHYS_INPUT_TIMELENGTH * wishspeed, addspeed);
-               this.velocity += accelspeed * wishdir;
-       }
-}
-
-void PM_air(entity this, float buttons_prev, float maxspd_mod)
-{
-       makevectors(this.v_angle.y * '0 1 0');
-       vector wishvel = v_forward * this.movement.x
-                                       + v_right * this.movement.y;
-       // acceleration
-       vector wishdir = normalize(wishvel);
-       float wishspeed = vlen(wishvel);
-
-#ifdef SVQC
-       if(time >= PHYS_TELEPORT_TIME(this))
-#elif defined(CSQC)
-       if(pmove_waterjumptime <= 0)
-#endif
-       {
-               float maxairspd = PHYS_MAXAIRSPEED(this) * min(maxspd_mod, 1);
-
-               // apply air speed limit
-               float airaccelqw = PHYS_AIRACCEL_QW(this);
-               float wishspeed0 = wishspeed;
-               wishspeed = min(wishspeed, maxairspd);
-               if (IS_DUCKED(this))
-                       wishspeed *= 0.5;
-               float airaccel = PHYS_AIRACCELERATE(this) * min(maxspd_mod, 1);
-
-               float accelerating = (this.velocity * wishdir > 0);
-               float wishspeed2 = wishspeed;
-
-               // CPM: air control
-               if (PHYS_AIRSTOPACCELERATE(this))
-               {
-                       vector curdir = normalize(vec2(this.velocity));
-                       airaccel += (PHYS_AIRSTOPACCELERATE(this)*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(this.movement, -90) + IsMoveInDirection(this.movement, +90); // if one is nonzero, other is always zero
-               if (PHYS_MAXAIRSTRAFESPEED(this))
-                       wishspeed = min(wishspeed, GeomLerp(PHYS_MAXAIRSPEED(this)*maxspd_mod, strafity, PHYS_MAXAIRSTRAFESPEED(this)*maxspd_mod));
-               if (PHYS_AIRSTRAFEACCELERATE(this))
-                       airaccel = GeomLerp(airaccel, strafity, PHYS_AIRSTRAFEACCELERATE(this)*maxspd_mod);
-               if (PHYS_AIRSTRAFEACCEL_QW(this))
-                       airaccelqw =
-               (((strafity > 0.5 ? PHYS_AIRSTRAFEACCEL_QW(this) : PHYS_AIRACCEL_QW(this)) >= 0) ? +1 : -1)
-               *
-               (1 - GeomLerp(1 - fabs(PHYS_AIRACCEL_QW(this)), strafity, 1 - fabs(PHYS_AIRSTRAFEACCEL_QW(this))));
-               // !CPM
-
-               if (PHYS_WARSOWBUNNY_TURNACCEL(this) && accelerating && this.movement.y == 0 && this.movement.x != 0)
-                       PM_AirAccelerate(this, wishdir, wishspeed2);
-               else {
-                   float sidefric = maxairspd ? (PHYS_AIRACCEL_SIDEWAYS_FRICTION(this) / maxairspd) : 0;
-                       PM_Accelerate(this, wishdir, wishspeed, wishspeed0, airaccel, airaccelqw, PHYS_AIRACCEL_QW_STRETCHFACTOR(this), sidefric, PHYS_AIRSPEEDLIMIT_NONQW(this));
-        }
-
-               if (PHYS_AIRCONTROL(this))
-                       CPM_PM_Aircontrol(this, wishdir, wishspeed2);
-       }
-}
-
 // used for calculating airshots
 bool IsFlying(entity this)
 {
@@ -1119,267 +800,15 @@ bool IsFlying(entity this)
        return true;
 }
 
-void PM_Main(entity this)
-{
-       int buttons = PHYS_INPUT_BUTTON_MASK(this);
-#ifdef CSQC
-       this.items = STAT(ITEMS);
-
-       this.movement = PHYS_INPUT_MOVEVALUES(this);
-
-       this.spectatorspeed = STAT(SPECTATORSPEED);
-
-       this.team = myteam + 1; // is this correct?
-       if (!(PHYS_INPUT_BUTTON_JUMP(this))) // !jump
-               UNSET_JUMP_HELD(this); // canjump = true
-       pmove_waterjumptime -= PHYS_INPUT_TIMELENGTH;
-
-       PM_ClientMovement_UpdateStatus(this);
-#endif
-
-       this.oldmovement = this.movement;
-
-
-#ifdef SVQC
-       WarpZone_PlayerPhysics_FixVAngle(this);
-#endif
-       float maxspeed_mod = 1;
-       maxspeed_mod *= PHYS_HIGHSPEED(this);
-
-#ifdef SVQC
-       Physics_UpdateStats(this, maxspeed_mod);
-
-       if (this.PlayerPhysplug)
-               if (this.PlayerPhysplug(this))
-                       return;
-#elif defined(CSQC)
-       if(hud != HUD_NORMAL)
-               return; // no vehicle prediction (yet)
-#endif
-
-#ifdef SVQC
-       anticheat_physics(this);
-#endif
-
-       if (PM_check_specialcommand(this, buttons))
-               return;
-#ifdef SVQC
-       if (sv_maxidle > 0)
-       {
-               if (buttons != this.buttons_old || this.movement != this.movement_old || this.v_angle != this.v_angle_old)
-                       this.parm_idlesince = time;
-       }
-#endif
-       int buttons_prev = this.buttons_old;
-       this.buttons_old = buttons;
-       this.movement_old = this.movement;
-       this.v_angle_old = this.v_angle;
-
-       PM_check_nickspam(this);
-
-       PM_check_punch(this);
-#ifdef SVQC
-       if (IS_BOT_CLIENT(this))
-       {
-               if (playerdemo_read(this))
-                       return;
-               bot_think(this);
-       }
-#endif
-
-#ifdef SVQC
-       if (IS_PLAYER(this))
-       {
-               const bool allowed_to_move = (time >= game_starttime);
-               if (!allowed_to_move)
-               {
-                       this.velocity = '0 0 0';
-                       set_movetype(this, MOVETYPE_NONE);
-                       this.disableclientprediction = 2;
-               }
-               else if (this.disableclientprediction == 2)
-               {
-                       if (this.move_movetype == MOVETYPE_NONE)
-                               set_movetype(this, MOVETYPE_WALK);
-                       this.disableclientprediction = 0;
-               }
-       }
-#endif
-
-#ifdef SVQC
-       if (this.move_movetype == MOVETYPE_NONE)
-               return;
-
-       // when we get here, disableclientprediction cannot be 2
-       this.disableclientprediction = (this.move_qcphysics) ? -1 : 0;
-#endif
-
-       viewloc_PlayerPhysics(this);
-
-       PM_check_frozen(this);
-
-       PM_check_blocked(this);
-
-       maxspeed_mod = 1;
-
-       if (this.in_swamp)
-               maxspeed_mod *= this.swamp_slowdown; //cvar("g_balance_swamp_moverate");
-
-       // conveyors: first fix velocity
-       if (this.conveyor.state)
-               this.velocity -= this.conveyor.movedir;
-
-       MUTATOR_CALLHOOK(PlayerPhysics, this);
-
-       if (!IS_PLAYER(this))
-       {
-#ifdef SVQC
-               maxspeed_mod = autocvar_sv_spectator_speed_multiplier;
-               if (!this.spectatorspeed)
-                       this.spectatorspeed = maxspeed_mod;
-               if (this.impulse && this.impulse <= 19 || (this.impulse >= 200 && this.impulse <= 209) || (this.impulse >= 220 && this.impulse <= 229))
-               {
-                       if (this.lastclassname != STR_PLAYER)
-                       {
-                               if (this.impulse == 10 || this.impulse == 15 || this.impulse == 18 || (this.impulse >= 200 && this.impulse <= 209))
-                                       this.spectatorspeed = bound(1, this.spectatorspeed + 0.5, 5);
-                               else if (this.impulse == 11)
-                                       this.spectatorspeed = maxspeed_mod;
-                               else if (this.impulse == 12 || this.impulse == 16  || this.impulse == 19 || (this.impulse >= 220 && this.impulse <= 229))
-                                       this.spectatorspeed = bound(1, this.spectatorspeed - 0.5, 5);
-                               else if (this.impulse >= 1 && this.impulse <= 9)
-                                       this.spectatorspeed = 1 + 0.5 * (this.impulse - 1);
-                       } // otherwise just clear
-                       this.impulse = 0;
-               }
-#endif
-               maxspeed_mod = this.spectatorspeed;
-       }
-#ifdef SVQC
-
-       float spd = max(PHYS_MAXSPEED(this), PHYS_MAXAIRSPEED(this)) * maxspeed_mod;
-       if(this.speed != spd)
-       {
-               this.speed = spd;
-               string temps = ftos(spd);
-               stuffcmd(this, strcat("cl_forwardspeed ", temps, "\n"));
-               stuffcmd(this, strcat("cl_backspeed ", temps, "\n"));
-               stuffcmd(this, strcat("cl_sidespeed ", temps, "\n"));
-               stuffcmd(this, strcat("cl_upspeed ", temps, "\n"));
-       }
-
-       if(this.jumpspeedcap_min != autocvar_sv_jumpspeedcap_min)
-       {
-               this.jumpspeedcap_min = autocvar_sv_jumpspeedcap_min;
-               stuffcmd(this, sprintf("\ncl_jumpspeedcap_min \"%s\"\n", autocvar_sv_jumpspeedcap_min));
-       }
-       if(this.jumpspeedcap_max != autocvar_sv_jumpspeedcap_max)
-       {
-               this.jumpspeedcap_max = autocvar_sv_jumpspeedcap_max;
-               stuffcmd(this, sprintf("\ncl_jumpspeedcap_max \"%s\"\n", autocvar_sv_jumpspeedcap_max));
-       }
-#endif
-
-       if(IS_DEAD(this))
-       {
-               // handle water here
-               vector midpoint = ((this.absmin + this.absmax) * 0.5);
-               if(pointcontents(midpoint) == CONTENT_WATER)
-               {
-                       this.velocity = this.velocity * 0.5;
-
-                       // do we want this?
-                       //if(pointcontents(midpoint + '0 0 2') == CONTENT_WATER)
-                               //{ this.velocity_z = 70; }
-               }
-               goto end;
-       }
-
-#ifdef SVQC
-       if (!this.fixangle)
-               this.angles = '0 1 0' * this.v_angle.y;
-#endif
-
-       if (IS_PLAYER(this) && IS_ONGROUND(this))
-       {
-               PM_check_hitground(this);
-               PM_Footsteps(this);
-       }
-
-#ifdef SVQC
-       if(IsFlying(this))
-               this.wasFlying = 1;
-#endif
-
-       if (IS_PLAYER(this))
-               CheckPlayerJump(this);
-
-       if (this.flags & FL_WATERJUMP)
-       {
-               this.velocity_x = this.movedir.x;
-               this.velocity_y = this.movedir.y;
-               if (this.waterlevel == WATERLEVEL_NONE
-               #ifdef CSQC
-                       || pmove_waterjumptime <= 0
-               #elif defined(SVQC)
-                       || time > PHYS_TELEPORT_TIME(this)
-               #endif
-                       )
-               {
-                       this.flags &= ~FL_WATERJUMP;
-               #ifdef CSQC
-                       pmove_waterjumptime = 0;
-               #elif defined(CSQC)
-                       PHYS_TELEPORT_TIME(this) = 0;
-               #endif
-               }
-       }
-
-       else if (MUTATOR_CALLHOOK(PM_Physics, this, maxspeed_mod))
-               { }
-
-#ifdef SVQC
-       else if (this.move_movetype == MOVETYPE_NOCLIP || this.move_movetype == MOVETYPE_FLY || this.move_movetype == MOVETYPE_FLY_WORLDONLY || MUTATOR_CALLHOOK(IsFlying, this))
-#elif defined(CSQC)
-       else if (this.move_movetype == MOVETYPE_NOCLIP || this.move_movetype == MOVETYPE_FLY || this.move_movetype == MOVETYPE_FLY_WORLDONLY || MUTATOR_CALLHOOK(IsFlying, this))
-#endif
-               PM_fly(this, maxspeed_mod);
-
-       else if (this.waterlevel >= WATERLEVEL_SWIMMING)
-               PM_swim(this, maxspeed_mod);
-
-       else if (time < this.ladder_time)
-               PM_ladder(this, maxspeed_mod);
-
-       else if (ITEMS_STAT(this) & IT_USING_JETPACK)
-               PM_jetpack(this, maxspeed_mod);
-
-       else if (IS_ONGROUND(this))
-               PM_walk(this, maxspeed_mod);
-
-       else
-               PM_air(this, buttons_prev, maxspeed_mod);
-
-LABEL(end)
-       if (IS_ONGROUND(this))
-               this.lastground = time;
-
-       // conveyors: then break velocity again
-       if(this.conveyor.state)
-               this.velocity += this.conveyor.movedir;
-
-       this.lastflags = this.flags;
-
-       this.lastclassname = this.classname;
-}
 
+void sys_phys_update(entity this, float dt);
 #if defined(SVQC)
 void SV_PlayerPhysics(entity this)
 #elif defined(CSQC)
 void CSQC_ClientMovement_PlayerMove_Frame(entity this)
 #endif
 {
-       PM_Main(this);
+       sys_phys_update(this, PHYS_INPUT_TIMELENGTH);
 
 #ifdef SVQC
        this.pm_frametime = frametime;
index c74602daba5ab22ccc529f2a54cab83e5ff404ce..9e7b799d027257e72d1201f6f013fcbffe57eb99 100644 (file)
@@ -1,5 +1,4 @@
-#ifndef COMMON_PHYSICS_H
-#define COMMON_PHYSICS_H
+#pragma once
 
 // Client/server mappings
 
@@ -25,7 +24,7 @@
 .vector v_angle_old;
 .string lastclassname;
 
-.float(entity) PlayerPhysplug;
+.float(entity,float) PlayerPhysplug;
 float AdjustAirAccelQW(float accelqw, float factor);
 
 bool IsFlying(entity a);
@@ -160,14 +159,18 @@ STATIC_INIT(PHYS_INPUT_BUTTON_JETPACK)
 #define ITEMS_STAT(s)                       ((s).items)
 
 .float teleport_time;
+#define PHYS_TELEPORT_TIME(s)               ((s).teleport_time)
+
+.float waterjump_time;
+#define PHYS_WATERJUMP_TIME(s)               ((s).waterjump_time)
 
 #ifdef CSQC
 
+       #define PHYS_FIXANGLE(s) ('0 0 0')
+
        string autocvar_cl_jumpspeedcap_min;
        string autocvar_cl_jumpspeedcap_max;
 
-       noref float pmove_waterjumptime;
-
        const int FL_WATERJUMP = 2048;  // player jumping out of water
        const int FL_JUMPRELEASED = 4096;  // for jump debouncing
 
@@ -191,8 +194,6 @@ STATIC_INIT(PHYS_INPUT_BUTTON_JETPACK)
 
        #define PHYS_GRAVITY(s)                     STAT(MOVEVARS_GRAVITY, s)
 
-       #define PHYS_TELEPORT_TIME(s)               ((s).teleport_time)
-
        #define TICRATE                             ticrate
 
        #define PHYS_INPUT_ANGLES(s)                input_angles
@@ -241,6 +242,8 @@ STATIC_INIT(PHYS_INPUT_BUTTON_JETPACK)
 
 #elif defined(SVQC)
 
+       #define PHYS_FIXANGLE(s) ((s).fixangle)
+
        bool Physics_Valid(string thecvar);
 
        .float stat_sv_airspeedlimit_nonqw = _STAT(MOVEVARS_AIRSPEEDLIMIT_NONQW);
@@ -250,8 +253,6 @@ STATIC_INIT(PHYS_INPUT_BUTTON_JETPACK)
        .string jumpspeedcap_min;
        .string jumpspeedcap_max;
 
-       #define PHYS_TELEPORT_TIME(s)               ((s).teleport_time)
-
        #define PHYS_GRAVITY(s)                     autocvar_sv_gravity
 
        #define TICRATE sys_frametime
@@ -323,5 +324,3 @@ NET_HANDLE(setpause, bool)
        return true;
 }
 #endif
-
-#endif
index 7e99bebea7480cfe32a9e32e670b3e58945f2a5e..ad58221269f0466b1733733a2b925982f10a5504 100644 (file)
@@ -379,9 +379,9 @@ void PlayerStats_GameReport_Handler(entity fh, entity pass, float status)
                {
                        // url_fclose is processing, we got a response for writing the data
                        // this must come from HTTP
-                       LOG_TRACE("Got response from player stats server:\n");
-                       while((s = url_fgets(fh))) { LOG_TRACE("  ", s, "\n"); }
-                       LOG_TRACE("End of response.\n");
+                       LOG_TRACE("Got response from player stats server:");
+                       while((s = url_fgets(fh))) { LOG_TRACE("  ", s); }
+                       LOG_TRACE("End of response.");
                        url_fclose(fh);
                        break;
                }
@@ -389,7 +389,7 @@ void PlayerStats_GameReport_Handler(entity fh, entity pass, float status)
                case URL_READY_CLOSED:
                {
                        // url_fclose has finished
-                       LOG_TRACE("Player stats written\n");
+                       LOG_TRACE("Player stats written");
                        PlayerStats_GameReport_DelayMapVote = false;
                        if(PS_GR_OUT_DB >= 0)
                        {
@@ -416,19 +416,21 @@ void PlayerStats_GameReport_Handler(entity fh, entity pass, float status)
 
 void PlayerStats_PlayerBasic(entity joiningplayer, float newrequest)
 {
+       PlayerScore_Add(joiningplayer, SP_ELO, -1);
        // http://stats.xonotic.org/player/GgXRw6piDtFIbMArMuiAi8JG4tiin8VLjZgsKB60Uds=/elo.txt
        if(autocvar_g_playerstats_playerbasic_uri != "")
        {
                string uri = autocvar_g_playerstats_playerbasic_uri;
-               if(joiningplayer.crypto_idfp != "")
-               {
+               if (joiningplayer.crypto_idfp == "") {
+                       PlayerScore_Add(joiningplayer, SP_ELO, -1);
+               } else {
                        // create the database if it doesn't already exist
                        if(PS_B_IN_DB < 0)
                                PS_B_IN_DB = db_create();
 
                        // now request the information
                        uri = strcat(uri, "/player/", uri_escape(uri_escape(uri_escape(joiningplayer.crypto_idfp))), "/elo.txt");
-                       LOG_TRACE("Retrieving playerstats from URL: ", uri, "\n");
+                       LOG_TRACE("Retrieving playerstats from URL: ", uri);
                        url_single_fopen(
                                uri,
                                FILE_APPEND,
@@ -452,6 +454,7 @@ void PlayerStats_PlayerBasic(entity joiningplayer, float newrequest)
        else
        {
                // server has this disabled, kill the DB and set status to idle
+               PlayerScore_Add(joiningplayer, SP_ELO, -1);
                if(PS_B_IN_DB >= 0)
                {
                        db_close(PS_B_IN_DB);
@@ -466,12 +469,10 @@ void PlayerStats_PlayerBasic_CheckUpdate(entity joiningplayer)
 {
        // determine whether we should retrieve playerbasic information again
 
-       #if 0
-       LOG_INFOF("PlayerStats_PlayerBasic_CheckUpdate('%s'): %f\n",
+       LOG_TRACEF("PlayerStats_PlayerBasic_CheckUpdate('%s'): %f",
                joiningplayer.netname,
                time
        );
-       #endif
 
        // TODO: check to see if this playerid is inside the database already somehow...
        // for now we'll just check the field, but this won't work for players who disconnect and reconnect properly
@@ -491,7 +492,7 @@ void PlayerStats_PlayerBasic_Handler(entity fh, entity p, float status)
        {
                case URL_READY_CANWRITE:
                {
-                       LOG_TRACE("-- Sending data to player stats server\n");
+                       LOG_TRACE("-- Sending data to player stats server");
                        /*url_fputs(fh, "V 1\n");
                        #ifdef WATERMARK
                        url_fputs(fh, sprintf("R %s\n", WATERMARK));
@@ -503,76 +504,76 @@ void PlayerStats_PlayerBasic_Handler(entity fh, entity p, float status)
                        url_fputs(fh, sprintf("m %s %s\n", cvar_string("_cl_playermodel"), cvar_string("_cl_playerskin"))); // model/skin
                        */url_fputs(fh, "\n");
                        url_fclose(fh);
-                       break;
+                       return;
                }
 
                case URL_READY_CANREAD:
                {
-                       string s = "";
-                       LOG_TRACE("-- Got response from player stats server:\n");
-                       //string gametype = string_null;
-                       while((s = url_fgets(fh)))
-                       {
-                               LOG_TRACE("  ", s, "\n");
-                               /*
+                       bool handled = false;
+                       string gt = string_null;
+                       for (string s = ""; (s = url_fgets(fh)); ) {
+                               int n = tokenizebyseparator(s, " "); // key value? data
+                               if (n == 1) continue;
                                string key = "", value = "", data = "";
-
-                               n = tokenizebyseparator(s, " "); // key (value) data
-                               if (n == 1)
-                                       continue;
-                               else if (n == 2)
-                               {
-                               key = argv(0);
-                               data = argv(1);
-                               }
-                               else if (n >= 3)
-                               {
-                                                               key = argv(0);
-                                                               value = argv(1);
-                                                               data = argv(2);
-                               }
-
-                               if (data == "")
-                               continue;
-
-                               if (key == "#")
-                               continue;
-                               else if (key == "V")
-                               PlayerInfo_AddItem(p, "_version", data);
-                               else if (key == "R")
-                               PlayerInfo_AddItem(p, "_release", data);
-                               else if (key == "T")
-                               PlayerInfo_AddItem(p, "_time", data);
-                               else if (key == "S")
-                               PlayerInfo_AddItem(p, "_statsurl", data);
-                               else if (key == "P")
-                               PlayerInfo_AddItem(p, "_hashkey", data);
-                               else if (key == "n")
-                               PlayerInfo_AddItem(p, "_playernick", data);
-                               else if (key == "i")
-                               PlayerInfo_AddItem(p, "_playerid", data);
-                               else if (key == "G")
-                               gametype = data;
-                               else if (key == "e" && value != "")
-                               {
-                               if (gametype == "")
-                               PlayerInfo_AddItem(p, value, data);
-                               else
-                               PlayerInfo_AddItem(p, sprintf("%s/%s", gametype, value), data);
+                               if (n == 2) {
+                    key = argv(0);
+                    data = argv(1);
+                               } else if (n >= 3) {
+                    key = argv(0);
+                    value = argv(1);
+                    data = argv(2);
                                }
-                               else
-                               continue;
-                               */
+                switch (key) {
+                    case "V":
+                        // PlayerInfo_AddItem(p, "_version", data);
+                        break;
+                    case "R":
+                        // PlayerInfo_AddItem(p, "_release", data);
+                        break;
+                    case "T":
+                        // PlayerInfo_AddItem(p, "_time", data);
+                        break;
+                    case "S":
+                        // PlayerInfo_AddItem(p, "_statsurl", data);
+                        break;
+                    case "P":
+                        // PlayerInfo_AddItem(p, "_hashkey", data);
+                        break;
+                    case "n":
+                        // PlayerInfo_AddItem(p, "_playernick", data);
+                        break;
+                    case "i":
+                        // PlayerInfo_AddItem(p, "_playerid", data);
+                        // p.xonstat_id = stof(data);
+                        break;
+                    case "G":
+                        gt = data;
+                        break;
+                    case "e":
+                        LOG_TRACE("G: ", gt);
+                        LOG_TRACE("e: ", data);
+                        if (gt == GetGametype()) {
+                            handled = true;
+                            float e = stof(data);
+                            PlayerScore_Add(p, SP_ELO, +1 + e);
+                        }
+                        if (gt == "") {
+                            // PlayerInfo_AddItem(p, value, data);
+                        } else {
+                            // PlayerInfo_AddItem(p, sprintf("%s/%s", gt, value), data);
+                        }
+                        break;
+                }
                        }
-                       LOG_TRACE("-- End of response.\n");
                        url_fclose(fh);
+                       if (handled) return;
                        break;
                }
                case URL_READY_CLOSED:
                {
                        // url_fclose has finished
                        LOG_INFO("Player stats synchronized with server\n");
-                       break;
+                       return;
                }
 
                case URL_READY_ERROR:
@@ -582,6 +583,7 @@ void PlayerStats_PlayerBasic_Handler(entity fh, entity p, float status)
                        break;
                }
        }
+       PlayerScore_Add(p, SP_ELO, -1);
 }
 #endif // SVQC
 
@@ -617,7 +619,7 @@ void PlayerStats_PlayerDetail_AddItem(string event, string data)
 
        // now actually set the event data
        db_put(PS_D_IN_DB, sprintf("#%s", event), data);
-       LOG_TRACE("Added item ", sprintf("#%s", event), "=", data, " to PS_D_IN_DB\n");
+       LOG_TRACE("Added item ", sprintf("#%s", event), "=", data, " to PS_D_IN_DB");
 }
 
 void PlayerStats_PlayerDetail()
@@ -630,7 +632,7 @@ void PlayerStats_PlayerDetail()
                        PS_D_IN_DB = db_create();
 
                //uri = strcat(uri, "/player/", uri_escape(crypto_getmyidfp(0)));
-               LOG_TRACE("Retrieving playerstats from URL: ", autocvar_g_playerstats_playerdetail_uri, "\n");
+               LOG_TRACE("Retrieving playerstats from URL: ", autocvar_g_playerstats_playerdetail_uri);
                url_single_fopen(
                        autocvar_g_playerstats_playerdetail_uri,
                        FILE_APPEND,
@@ -685,7 +687,7 @@ void PlayerStats_PlayerDetail_Handler(entity fh, entity unused, float status)
        {
                case URL_READY_CANWRITE:
                {
-                       LOG_TRACE("PlayerStats_PlayerDetail_Handler(): Sending data to player stats server...\n");
+                       LOG_TRACE("PlayerStats_PlayerDetail_Handler(): Sending data to player stats server...");
                        url_fputs(fh, "V 1\n");
                        #ifdef WATERMARK
                        url_fputs(fh, sprintf("R %s\n", WATERMARK));
index ec309c4f4c191fc9d46500e57ff8de3d0571e2ab..73496ba7639bd1b168b54c60fce009e2dbdd9916 100644 (file)
@@ -1,5 +1,4 @@
-#ifndef PLAYERSTATS_H
-#define PLAYERSTATS_H
+#pragma once
 
 #ifdef SVQC
 //float PS_PM_IN_DB = -1;   // playerstats_prematch_in_db      // db for info COLLECTED at the beginning of a match
@@ -116,4 +115,3 @@ void PlayerStats_PlayerDetail();
 void PlayerStats_PlayerDetail_CheckUpdate();
 void PlayerStats_PlayerDetail_Handler(entity fh, entity p, float status);
 #endif
-#endif
index a7fe25f17d1e324d07069f46e16057efbd22ba96..b7b296341b5a02ba5829035e158f13ad673cbefe 100644 (file)
@@ -1,9 +1,8 @@
-#ifndef SOUNDS_ALL_H
-#define SOUNDS_ALL_H
+#pragma once
 
 #include "sound.qh"
 
-REGISTRY(Sounds, BITS(8))
+REGISTRY(Sounds, BITS(9))
 #define Sounds_from(i) _Sounds_from(i, SND_Null)
 REGISTER_REGISTRY(Sounds)
 
@@ -21,4 +20,3 @@ PRECACHE(Sounds) {
 SOUND(Null, "misc/null");
 #include "all.inc"
 #include "all.qc"
-#endif
index 519f910b0d3fee4721a698c549a59316841d658b..8c4aecbda029829c753e9b1641ceeb490cc04259 100644 (file)
@@ -1,5 +1,4 @@
-#ifndef SOUND_H
-#define SOUND_H
+#pragma once
 
 // negative = SVQC autochannels
 // positive = one per entity
@@ -94,8 +93,8 @@ const float VOL_MUFFLED = 0.35;
        } MACRO_END
 
 CLASS(Sound, Object)
-       ATTRIB(Sound, m_id, int, 0)
-       ATTRIB(Sound, sound_str, string(), func_null)
+       ATTRIB(Sound, m_id, int, 0);
+       ATTRIB(Sound, sound_str, string());
        CONSTRUCTOR(Sound, string() path)
        {
                CONSTRUCT(Sound);
@@ -115,7 +114,7 @@ CLASS(Sound, Object)
                        /**/
                #define tryext(ext) { string s = strcat(base, "." #ext); if (fexists(strcat("sound/", s))) return s; }
                extensions(tryext);
-               LOG_WARNINGF("Missing sound: \"%s\"\n", strcat("sound/", base));
+               LOG_WARNF("Missing sound: \"%s\"", strcat("sound/", base));
                #undef tryext
                #undef extensions
                return string_null;
@@ -126,9 +125,7 @@ CLASS(Sound, Object)
            TC(Sound, this);
                string s = Sound_fixpath(this);
                if (!s) return;
-               profile(sprintf("precache_sound(\"%s\")\n", s));
+               profile(sprintf("precache_sound(\"%s\")", s));
                precache_sound(s);
        }
 ENDCLASS(Sound)
-
-#endif
index 7c6882088dba4a604998fe824b866a66a16f2d68..891461c6a4dd24f92886c1c89522af11e67f2093 100644 (file)
@@ -16,14 +16,14 @@ void PlayerState_detach(entity this)
        if (!ps) return;  // initial connect
        PS(this) = NULL;
 
+       if (ps.m_client != this) return;  // don't own state, spectator
        ps.m_switchweapon = WEP_Null;
        ps.m_weapon = WEP_Null;
        ps.m_switchingweapon = WEP_Null;
        ps.ps_push(ps, this);
-
-       if (ps.m_client != this) return;  // don't own state, spectator
+       
        FOREACH_CLIENT(PS(it) == ps, { PS(it) = NULL; });
-       remove(ps);
+       delete(ps);
 
     Inventory_delete(this);
 }
@@ -45,13 +45,12 @@ void ClientState_attach(entity this)
 
     GetCvars(this, 0);  // get other cvars from player
 
-       if (IS_REAL_CLIENT(this)) { PlayerStats_PlayerBasic_CheckUpdate(this); }
-
        // TODO: fold all of these into ClientState
 
        DecodeLevelParms(this);
 
        PlayerScore_Attach(this);
+       PlayerStats_PlayerBasic_CheckUpdate(this);
        ClientData_Attach(this);
        accuracy_init(this);
        entcs_attach(this);
@@ -73,7 +72,7 @@ void PlayerScore_Detach(entity this);
 
 void ClientState_detach(entity this)
 {
-       remove(CS(this));
+       delete(CS(this));
        this._cs = NULL;
 
     GetCvars(this, -1);  // free cvars
index 110df1c575840421fb05a47ebb66cc16c89f8efa..94b9bc325f26288ebe8ccc8ff8cf67756366c334 100644 (file)
@@ -6,15 +6,15 @@
  * Server: instance per client, clients decoupled from players
  */
 CLASS(PlayerState, Object)
-       ATTRIB(PlayerState, m_client, entity, NULL)
+       ATTRIB(PlayerState, m_client, entity);
        CONSTRUCTOR(PlayerState, entity client)
        {
                CONSTRUCT(PlayerState);
                this.m_client = client;
        }
-       ATTRIB(PlayerState, m_switchingweapon, Weapon, Weapons_from(-1))
-       ATTRIB(PlayerState, m_switchweapon, Weapon, Weapons_from(-1))
-       ATTRIB(PlayerState, m_weapon, Weapon, Weapons_from(-1))
+       ATTRIB(PlayerState, m_switchingweapon, Weapon, Weapons_from(-1));
+       ATTRIB(PlayerState, m_switchweapon, Weapon, Weapons_from(-1));
+       ATTRIB(PlayerState, m_weapon, Weapon, Weapons_from(-1));
        METHOD(PlayerState, ps_push, void(PlayerState this, entity cl))
        {
            TC(PlayerState, this);
@@ -37,7 +37,7 @@ void PlayerState_detach(entity this);
  * Server: instance per client
  */
 CLASS(ClientState, Object)
-       ATTRIB(ClientState, m_client, entity, NULL)
+       ATTRIB(ClientState, m_client, entity);
        CONSTRUCTOR(ClientState, entity client)
        {
                CONSTRUCT(ClientState);
index bbf315183d12cd24c0f4749fdbb72919b31a1ed5..a24243bb6d4ec659532b39018fe458f7fc4078ea 100644 (file)
@@ -1,5 +1,4 @@
-#ifndef STATS_H
-#define STATS_H
+#pragma once
 
 #ifdef SVQC
 #include <server/cl_client.qh>
@@ -124,6 +123,7 @@ REGISTER_STAT(BUFF_TIME, float)
 REGISTER_STAT(CTF_FLAGSTATUS, int)
 REGISTER_STAT(ENTRAP_ORB, float)
 REGISTER_STAT(ENTRAP_ORB_ALPHA, float)
+REGISTER_STAT(ITEMSTIME, int, autocvar_sv_itemstime)
 
 #ifdef SVQC
 int autocvar_g_multijump;
@@ -322,6 +322,3 @@ REGISTER_STAT(GUNALIGN, int, this.cvar_cl_gunalign)
 #ifdef SVQC
 SPECTATE_COPYFIELD(_STAT(GUNALIGN))
 #endif
-
-
-#endif
index 8563349fd920f74e725c66bd4cd9609ae8142fa3..bc914d853da3594145faeb8d21e7cc653cbb241b 100644 (file)
@@ -4,8 +4,7 @@
 
 #if defined(SVQC)
 
-    #include "../server/bot/bot.qh"
-    #include "../server/bot/waypoints.qh"
+    #include "../server/bot/api.qh"
 
     #include <server/mutators/all.qh>
 
@@ -35,6 +34,7 @@ REGISTER_NET_LINKED(ENT_CLIENT_ITEM)
 
 #ifdef CSQC
 bool autocvar_cl_ghost_items_vehicle = true;
+.vector item_glowmod;
 void Item_SetAlpha(entity this)
 {
        bool veh_hud = (hud && autocvar_cl_ghost_items_vehicle);
@@ -42,7 +42,8 @@ void Item_SetAlpha(entity this)
        if(!veh_hud && (this.ItemStatus & ITS_AVAILABLE))
        {
                this.alpha = 1;
-               this.colormod = this.glowmod = '1 1 1';
+               this.colormod = '1 1 1';
+               this.glowmod = this.item_glowmod;
        }
        else
        {
@@ -194,7 +195,7 @@ NET_HANDLE(ENT_CLIENT_ITEM, bool isnew)
     if(sf & ISF_MODEL)
     {
         this.drawmask  = MASK_NORMAL;
-               this.move_movetype = MOVETYPE_TOSS;
+               set_movetype(this, MOVETYPE_TOSS);
                if (isnew) IL_PUSH(g_drawables, this);
         this.draw       = ItemDraw;
         this.solid = SOLID_TRIGGER;
@@ -229,7 +230,7 @@ NET_HANDLE(ENT_CLIENT_ITEM, bool isnew)
             else
             {
                 this.draw = ItemDraw;
-                LOG_TRACE("Simple item requested for ", _fn, " but no model exists for it\n");
+                LOG_TRACE("Simple item requested for ", _fn, " but no model exists for it");
             }
         }
 
@@ -238,7 +239,7 @@ NET_HANDLE(ENT_CLIENT_ITEM, bool isnew)
 
 
         if(this.mdl == "")
-            LOG_TRACE("^1WARNING!^7 this.mdl is unset for item ", this.classname, ", tell tZork about this!\n");
+            LOG_TRACE("^1WARNING!^7 this.mdl is unset for item ", this.classname, ", tell tZork about this!");
 
         precache_model(this.mdl);
         _setmodel(this, this.mdl);
@@ -247,14 +248,19 @@ NET_HANDLE(ENT_CLIENT_ITEM, bool isnew)
     }
 
     if(sf & ISF_COLORMAP)
+    {
         this.colormap = ReadShort();
+        this.item_glowmod_x = ReadByte() / 255.0;
+        this.item_glowmod_y = ReadByte() / 255.0;
+        this.item_glowmod_z = ReadByte() / 255.0;
+    }
 
     if(sf & ISF_DROP)
     {
         this.gravity = 1;
         this.pushable = true;
         //this.angles = '0 0 0';
-        this.move_movetype = MOVETYPE_TOSS;
+        set_movetype(this, MOVETYPE_TOSS);
         this.velocity_x = ReadCoord();
         this.velocity_y = ReadCoord();
         this.velocity_z = ReadCoord();
@@ -328,14 +334,19 @@ bool ItemSend(entity this, entity to, int sf)
                WriteShort(MSG_ENTITY, this.fade_start);
 
                if(this.mdl == "")
-                       LOG_TRACE("^1WARNING!^7 this.mdl is unset for item ", this.classname, "exspect a crash just aboute now\n");
+                       LOG_TRACE("^1WARNING!^7 this.mdl is unset for item ", this.classname, "expect a crash just about now");
 
                WriteString(MSG_ENTITY, this.mdl);
        }
 
 
        if(sf & ISF_COLORMAP)
+       {
                WriteShort(MSG_ENTITY, this.colormap);
+               WriteByte(MSG_ENTITY, this.glowmod.x * 255.0);
+        WriteByte(MSG_ENTITY, this.glowmod.y * 255.0);
+        WriteByte(MSG_ENTITY, this.glowmod.z * 255.0);
+       }
 
        if(sf & ISF_DROP)
        {
@@ -447,7 +458,7 @@ void Item_Show (entity e, float mode)
                //setmodel(e, "null");
                e.solid = SOLID_NOT;
                e.colormod = '0 0 0';
-               e.glowmod = e.colormod;
+               //e.glowmod = e.colormod;
                e.spawnshieldtime = 1;
                e.ItemStatus &= ~ITS_AVAILABLE;
        }}
@@ -768,7 +779,7 @@ void Item_Touch(entity this, entity toucher)
        {
                if (ITEM_TOUCH_NEEDKILL())
                {
-                       remove(this);
+                       delete(this);
                        return;
                }
        }
@@ -817,7 +828,7 @@ LABEL(pickup)
        _sound (toucher, (this.itemdef.instanceOfPowerup ? CH_TRIGGER_SINGLE : CH_TRIGGER), (this.item_pickupsound ? this.item_pickupsound : Sound_fixpath(this.item_pickupsound_ent)), VOL_BASE, ATTEN_NORM);
 
        if (this.classname == "droppedweapon")
-               remove (this);
+               delete (this);
        else if (this.spawnshieldtime)
        {
                entity e;
@@ -867,7 +878,7 @@ void Item_FindTeam(entity this)
        if(this.effects & EF_NODRAW)
        {
                // marker for item team search
-               LOG_TRACE("Initializing item team ", ftos(this.team), "\n");
+               LOG_TRACE("Initializing item team ", ftos(this.team));
                RandomSelection_Init();
                FOREACH_ENTITY_FLOAT(team, this.team,
                {
@@ -904,7 +915,7 @@ void RemoveItem(entity this)
 {
        if(wasfreed(this) || !this) { return; }
        Send_Effect(EFFECT_ITEM_PICKUP, CENTER_OR_VIEWOFS(this), '0 0 0', 1);
-       remove(this);
+       delete(this);
 }
 
 // pickup evaluation functions
@@ -1069,7 +1080,7 @@ void _StartItem(entity this, entity def, float defaultrespawntime, float default
        if(MUTATOR_CALLHOOK(FilterItem, this)) // error means we do not want the item
        {
                startitem_failed = true;
-               remove(this);
+               delete(this);
                return;
        }
 
@@ -1098,7 +1109,7 @@ void _StartItem(entity this, entity def, float defaultrespawntime, float default
                if (trace_dpstartcontents & DPCONTENTS_NODROP)
                {
                        startitem_failed = true;
-                       remove(this);
+                       delete(this);
                        return;
                }
        }
@@ -1107,7 +1118,7 @@ void _StartItem(entity this, entity def, float defaultrespawntime, float default
                if(!have_pickup_item(this))
                {
                        startitem_failed = true;
-                       remove (this);
+                       delete (this);
                        return;
                }
 
@@ -1155,7 +1166,7 @@ void _StartItem(entity this, entity def, float defaultrespawntime, float default
             // why not flags & fl_item?
                    FOREACH_ENTITY_RADIUS(this.origin, 3, it.is_item, {
                 LOG_TRACE("XXX Found duplicated item: ", itemname, vtos(this.origin));
-                LOG_TRACE(" vs ", it.netname, vtos(it.origin), "\n");
+                LOG_TRACE(" vs ", it.netname, vtos(it.origin));
                 error("Mapper sucks.");
             });
                        this.is_item = true;
@@ -1205,7 +1216,7 @@ void _StartItem(entity this, entity def, float defaultrespawntime, float default
                        this.gravity = 1;
                if (!(this.spawnflags & 1024))
                        this.ItemStatus |= ITS_ANIMATE1;
-               this.ItemStatus |= ISF_COLORMAP;
+               this.SendFlags |= ISF_COLORMAP;
        }
 
        this.state = 0;
@@ -1226,7 +1237,7 @@ void _StartItem(entity this, entity def, float defaultrespawntime, float default
        if (MUTATOR_CALLHOOK(Item_Spawn, this))
        {
                startitem_failed = true;
-               remove(this);
+               delete(this);
                return;
        }
 }
@@ -1423,7 +1434,7 @@ void target_items_use(entity this, entity actor, entity trigger)
        if(actor.classname == "droppedweapon")
        {
                EXACTTRIGGER_TOUCH(this, trigger);
-               remove(actor);
+               delete(actor);
                return;
        }
 
@@ -1439,7 +1450,7 @@ void target_items_use(entity this, entity actor, entity trigger)
        FOREACH_ENTITY_ENT(enemy, actor,
        {
                if(it.classname == "droppedweapon")
-                       remove(it);
+                       delete(it);
        });
 
        if(GiveItems(actor, 0, tokenize_console(this.netname)))
index 1ed807c7c1ecea93a1059a50eb96f42bf577beed..1c65e806af7e97544ef801904c7f9c1aeb0e741d 100644 (file)
@@ -1,5 +1,4 @@
-#ifndef T_ITEMS_H
-#define T_ITEMS_H
+#pragma once
 
 const int AMMO_COUNT = 4; // amount of ammo types to show in the inventory panel
 
@@ -133,4 +132,3 @@ void GiveRot(entity e, float v0, float v1, .float rotfield, float rottime, .floa
 
 float GiveItems(entity e, float beginarg, float endarg);
 #endif
-#endif
index aeaf078dce4b564b6c2a77df146821ff5a77c935..1f8a603dd01744b1dde6a4f13f98b5b32bb61d03 100644 (file)
@@ -1,5 +1,4 @@
-#ifndef TEAMS_H
-#define TEAMS_H
+#pragma once
 
 #ifdef TEAMNUMBERS_THAT_ARENT_STUPID
 const int NUM_TEAM_1 = 1;  // red
@@ -177,5 +176,3 @@ float Team_TeamToNumber(float teamid)
 // safe team comparisons
 #define SAME_TEAM(a,b) (teamplay ? (a.team == b.team) : (a == b))
 #define DIFF_TEAM(a,b) (teamplay ? (a.team != b.team) : (a != b))
-
-#endif
index 6763701d31fa91d52468af4e71f657d0986313e7..29d6c6a269ec3d4181a3ae8a9bb168b7e8682c50 100644 (file)
@@ -2,7 +2,7 @@
 
 #include <server/g_subs.qh>
 #include <server/g_damage.qh>
-#include <server/bot/bot.qh>
+#include <server/bot/api.qh>
 #include <common/csqcmodel_settings.qh>
 #include <lib/csqcmodel/sv_model.qh>
 #include <server/weapons/common.qh>
index 75cfb94c690cf09d51c5ad8eaa1211bf5012043c..761a2c7a98f350fe53629bc13f74e3874eb19673 100644 (file)
@@ -1,8 +1,5 @@
-#ifndef TRIGGERS_FUNC_BREAKABLE_H
-#define TRIGGERS_FUNC_BREAKABLE_H
+#pragma once
 
 #ifdef SVQC
 spawnfunc(func_breakable);
 #endif
-
-#endif
index 8bd6016f28a5498f33cb0a0c544fbeca29a93d3d..73ceb639408ea20361504d6489d80fc569223a12 100644 (file)
@@ -154,7 +154,7 @@ void conveyor_init(entity this)
        IL_PUSH(g_drawables, this);
        this.drawmask = MASK_NORMAL;
 
-       this.move_movetype = MOVETYPE_NONE;
+       set_movetype(this, MOVETYPE_NONE);
        this.model = "";
        this.solid = SOLID_TRIGGER;
        this.move_time = time;
index a0fb12a4c4806c10140a7f32645e75f6b190ae70..706784eda7b18b13918269cbece6bad46d0bc3eb 100644 (file)
@@ -525,7 +525,7 @@ void LinkDoors(entity this)
                        break;
                }
        }
-       LOG_TRACE("\n");
+       LOG_TRACE("");
 
        // collect health, targetname, message, size
        cmins = this.absmin;
@@ -815,7 +815,7 @@ NET_HANDLE(ENT_CLIENT_DOOR, bool isnew)
                this.SUB_LTIME = ReadCoord();
 
                this.solid = SOLID_BSP;
-               this.move_movetype = MOVETYPE_PUSH;
+               set_movetype(this, MOVETYPE_PUSH);
                this.use = door_use;
 
                LinkDoors(this);
@@ -824,7 +824,7 @@ NET_HANDLE(ENT_CLIENT_DOOR, bool isnew)
                        door_init_startopen(this);
 
                this.move_time = time;
-               this.move_movetype = MOVETYPE_PUSH;
+               set_movetype(this, MOVETYPE_PUSH);
        }
 
        if(sf & SF_TRIGGER_RESET)
index 628355cb79aa0280f2173848d03c0bca5387e419..4e8b94cd1c88779b56d0ec81fc99b429bc0bcf55 100644 (file)
@@ -1,8 +1,5 @@
-#ifndef TRIGGERS_FUNC_INCLUDE_H
-#define TRIGGERS_FUNC_INCLUDE_H
+#pragma once
 
 #include "door.qh"
 #include "ladder.qh"
 #include "train.qh"
-
-#endif
index 341ca460feb28eef5bcf954e59b3f9aee7c18c30..396636e8cd214cf8c96e8f7f95b0ae90a920e192 100644 (file)
@@ -168,7 +168,7 @@ NET_HANDLE(ENT_CLIENT_PLAT, bool isnew)
 
                this.classname = "plat";
                this.solid = SOLID_BSP;
-               this.move_movetype = MOVETYPE_PUSH;
+               set_movetype(this, MOVETYPE_PUSH);
                this.drawmask = MASK_NORMAL;
                this.draw = plat_draw;
                if (isnew) IL_PUSH(g_drawables, this);
@@ -177,7 +177,7 @@ NET_HANDLE(ENT_CLIENT_PLAT, bool isnew)
 
                plat_reset(this); // also called here
 
-               this.move_movetype = MOVETYPE_PUSH;
+               set_movetype(this, MOVETYPE_PUSH);
                this.move_time = time;
 
                plat_spawn_inside_trigger(this);
index 29c7d0a7b125898ae519ced47c7bd42fc1ac850f..247bfb0fc1e5e34703fc23f42e751e0d57be681a 100644 (file)
@@ -307,7 +307,7 @@ NET_HANDLE(ENT_CLIENT_TRAIN, bool isnew)
 
                this.classname = "func_train";
                this.solid = SOLID_BSP;
-               this.move_movetype = MOVETYPE_PUSH;
+               set_movetype(this, MOVETYPE_PUSH);
                this.drawmask = MASK_NORMAL;
                this.draw = train_draw;
                if (isnew) IL_PUSH(g_drawables, this);
@@ -325,7 +325,7 @@ NET_HANDLE(ENT_CLIENT_TRAIN, bool isnew)
                // but we will need these
                train_next(this);
 
-               this.move_movetype = MOVETYPE_PUSH;
+               set_movetype(this, MOVETYPE_PUSH);
                this.move_time = time;
        }
 
index 25688e3ecb692e7114c6ec739d5dbf83236d7aa9..f3f81738a19f7a73106863b91a90a0bee7c47c3d 100644 (file)
@@ -1,5 +1,4 @@
-#ifndef TRIGGERS_INCLUDE_H
-#define TRIGGERS_INCLUDE_H
+#pragma once
 
 // some required common stuff
 #ifdef CSQC
@@ -18,5 +17,3 @@
 
 // trigger
 #include "trigger/include.qh"
-
-#endif
index fa242beb97ceb0fe6adec70a4bd34dee60468be3..d19d9da0853c856dd5132dff40fa42d22945c042 100644 (file)
@@ -41,7 +41,7 @@ void follow_init(entity this)
                }
 
                dst.solid = SOLID_NOT; // solid doesn't work with attachment
-               remove(this);
+               delete(this);
        }
        else
        {
@@ -58,7 +58,7 @@ void follow_init(entity this)
                        follow_sameorigin(dst, src);
                }
 
-               remove(this);
+               delete(this);
        }
 }
 
index 391172fe0f157fc17a3585abd98dfc007df81737..7b9ffd9c5007d573e724e8c0462c83698bbc2ccd 100644 (file)
@@ -53,7 +53,7 @@ void plat_spawn_inside_trigger(entity this)
                        }
 
        // otherwise, something is fishy...
-       remove(trigger);
+       delete(trigger);
        objerror(this, "plat_spawn_inside_trigger: platform has odd size or lip, can't spawn");
 }
 
index f0727be3ca1fe59cf57b8779d60e20178ffc533b..c40467494f367adf9c68af7390dbd55ee6ec120c 100644 (file)
@@ -1,5 +1,4 @@
-#ifndef PLATFORMS_H
-#define PLATFORMS_H
+#pragma once
 
 .float dmgtime2;
 
@@ -12,5 +11,3 @@ void plat_crush(entity this, entity blocker);
 const float PLAT_LOW_TRIGGER = 1;
 
 .float dmg;
-
-#endif
index 3120aa33d90361b1e5f88a75f49f72ae0f16c220..66f0253d95e1bcce3987fc33c2f1f50943905e4b 100644 (file)
@@ -40,7 +40,7 @@ void SUB_VanishOrRemove (entity ent)
        else
        {
                // remove
-               remove (ent);
+               delete (ent);
        }
 }
 
@@ -144,7 +144,7 @@ void SUB_CalcMove_controller_think (entity this)
                // derivative: delta + 2 * delta2 (e.g. for angle positioning)
                entity own = this.owner;
                SUB_THINK(own, this.think1);
-               remove(this);
+               delete(this);
                SUB_THUNK(own)(own);
        }
 }
index 096022c848644ac499c5c674e4f0fe1c709079e1..4f98d5ae15cd92335c4b76282814566358ba1fa7 100644 (file)
@@ -1,5 +1,4 @@
-#ifndef SUBS_H
-#define SUBS_H
+#pragma once
 
 #define SUB_ANGLES(s)          (s).angles
 #define SUB_VELOCITY           velocity
@@ -69,5 +68,3 @@ float STATE_DOWN              = 3;
 
 .float         max_health;             // players maximum health is stored here
 #endif
-
-#endif
index 4e44b9762b901a762436b82ba5f507ebb840cfb4..c0f7cad443a0fd62f5cfad147ba3f207e0b662b5 100644 (file)
@@ -1,6 +1,3 @@
-#ifndef TRIGGERS_TARGET_INCLUDE_H
-#define TRIGGERS_TARGET_INCLUDE_H
+#pragma once
 
 #include "music.qh"
-
-#endif
index 7abcd67403391fb821bbdfd45ff02de704dc5664..ff195f03f9bff35a12f6adad94dfe66e1cec8656 100644 (file)
@@ -223,7 +223,7 @@ void Net_TargetMusic()
                _sound(e, CH_BGM_SINGLE, e.noise, 0, ATTEN_NONE);
                if(getsoundtime(e, CH_BGM_SINGLE) < 0)
                {
-                       LOG_TRACEF("Cannot initialize sound %s\n", e.noise);
+                       LOG_TRACEF("Cannot initialize sound %s", e.noise);
                        strunzone(e.noise);
                        e.noise = string_null;
                }
@@ -310,7 +310,7 @@ NET_HANDLE(ENT_CLIENT_TRIGGER_MUSIC, bool isnew)
                        _sound(this, CH_BGM_SINGLE, this.noise, 0, ATTEN_NONE);
                        if(getsoundtime(this, CH_BGM_SINGLE) < 0)
                        {
-                               LOG_TRACEF("Cannot initialize sound %s\n", this.noise);
+                               LOG_TRACEF("Cannot initialize sound %s", this.noise);
                                strunzone(this.noise);
                                this.noise = string_null;
                        }
index a9232107ebbbed9407716c1e112acfab553a35b8..80b3684a4e9a768b8ef17e4ea596f463d9cc886d 100644 (file)
@@ -1,5 +1,4 @@
-#ifndef TARGET_MUSIC_H
-#define TARGET_MUSIC_H
+#pragma once
 
 .float lifetime;
 
@@ -25,5 +24,3 @@ void Ent_TriggerMusic_Remove(entity this);
 #elif defined(SVQC)
 void target_music_kill();
 #endif
-
-#endif
index 7db93a3d1e46c665227b15b5d7223e6003651376..f8f1c0ace5d32f38da5e6f3086b1f82011618eab 100644 (file)
@@ -115,7 +115,7 @@ spawnfunc(target_speaker)
        else if(this.spawnflags & 1) // LOOPED_ON
        {
                ambientsound (this.origin, this.noise, VOL_BASE * this.volume, this.atten);
-               remove(this);
+               delete(this);
        }
        else if(this.spawnflags & 2) // LOOPED_OFF
        {
@@ -125,7 +125,7 @@ spawnfunc(target_speaker)
        {
                // Quake/Nexuiz fallback
                ambientsound (this.origin, this.noise, VOL_BASE * this.volume, this.atten);
-               remove(this);
+               delete(this);
        }
 }
 #endif
index c0f45f263d588087d724d1e52a59e590275f6b38..513ed3e26928460e636b36940fa0d009c5213241 100644 (file)
@@ -1,5 +1,4 @@
-#ifndef T_TELEPORTERS_H
-#define T_TELEPORTERS_H
+#pragma once
 
 .entity pusher;
 const float TELEPORT_FLAG_SOUND = 1;
@@ -92,5 +91,3 @@ void WarpZone_PostTeleportPlayer_Callback(entity pl);
                        if(head.isplayermodel) \
                                if(boxesoverlap(deathmin, deathmax, head.absmin, head.absmax))
 #endif
-
-#endif
index efddf8c77f89eb99787af0075e448e1035ad4082..62b21e66f4fe4dbe8bcc5010c83e1b6c1500ce8d 100644 (file)
@@ -2,7 +2,7 @@
 void gamestart_use(entity this, entity actor, entity trigger)
 {
        SUB_UseTargets(this, this, trigger);
-       remove(this);
+       delete(this);
 }
 
 void gamestart_use_this(entity this)
index cef8cb8bbe5f94838504e47b154e8f7e052549c7..88b73c4dfcdd1d15c979c3bf2cebda4172ce0020 100644 (file)
@@ -6,7 +6,7 @@ void trigger_gravity_remove(entity own)
        {
                UpdateCSQCProjectile(own);
                own.gravity = own.trigger_gravity_check.gravity;
-               remove(own.trigger_gravity_check);
+               delete(own.trigger_gravity_check);
        }
        else
                backtrace("Removing a trigger_gravity_check with no valid owner");
@@ -22,7 +22,7 @@ void trigger_gravity_check_think(entity this)
                if(this.owner.trigger_gravity_check == this)
                        trigger_gravity_remove(this.owner);
                else
-                       remove(this);
+                       delete(this);
                return;
        }
        else
index cdf4a72918b79c9ab5326814dd1040e12f061620..43bac947e127908930ca816e0f9115b82b5f4127 100644 (file)
@@ -17,7 +17,7 @@ void trigger_impulse_touch1(entity this, entity toucher)
        if(!targ)
        {
                objerror(this, "trigger_force without a (valid) .target!\n");
-               remove(this);
+               delete(this);
                return;
        }
 
index 67d6361fbed2ea61c76c4bafb8e2952d6f06d485..a6961f5d2e7693920f56dac39df1d78011b88f91 100644 (file)
@@ -1,10 +1,7 @@
-#ifndef TRIGGER_IMPULSE_H
-#define TRIGGER_IMPULSE_H
+#pragma once
 
 // tZorks trigger impulse / gravity
 .float radius;
 .float falloff;
 .float strength;
 .float lastpushtime;
-
-#endif
index 63cdb019017254c0fdeba69e347dc8bc21d7256c..8aa6b2b1729244d8f548102d7d8ebd8b6c3a4a34 100644 (file)
@@ -1,5 +1,4 @@
-#ifndef TRIGGERS_TRIGGER_INCLUDE_H
-#define TRIGGERS_TRIGGER_INCLUDE_H
+#pragma once
 
 #include "multi.qh"
 #include "jumppads.qh"
@@ -8,5 +7,3 @@
 #include "keylock.qh"
 #include "impulse.qh"
 #include "viewloc.qh"
-
-#endif
index 4a30ca69510d59a5c1aac0577f6a92fed64095d1..519ba2691586fb5e5d0d99a99021361310b8c5bb 100644 (file)
@@ -174,11 +174,11 @@ void trigger_push_touch(entity this, entity toucher)
                switch(toucher.move_movetype)
                {
                        case MOVETYPE_FLY:
-                               toucher.move_movetype = MOVETYPE_TOSS;
+                               set_movetype(toucher, MOVETYPE_TOSS);
                                toucher.gravity = 1;
                                break;
                        case MOVETYPE_BOUNCEMISSILE:
-                               toucher.move_movetype = MOVETYPE_BOUNCE;
+                               set_movetype(toucher, MOVETYPE_BOUNCE);
                                toucher.gravity = 1;
                                break;
                }
@@ -235,6 +235,7 @@ void trigger_push_touch(entity this, entity toucher)
        if (toucher.flags & FL_PROJECTILE)
        {
                toucher.angles = vectoangles (toucher.velocity);
+               toucher.com_phys_gravity_factor = 1;
                switch(toucher.move_movetype)
                {
                        case MOVETYPE_FLY:
@@ -291,7 +292,7 @@ void trigger_push_findtarget(entity this)
                        tracetoss(e, e);
                        if(e.move_movetype == MOVETYPE_NONE)
                                waypoint_spawnforteleporter(this, trace_endpos, vlen(trace_endpos - org) / vlen(e.velocity));
-                       remove(e);
+                       delete(e);
 #endif
                }
 
@@ -323,7 +324,7 @@ void trigger_push_findtarget(entity this)
                e.velocity = this.movedir;
                tracetoss(e, e);
                waypoint_spawnforteleporter(this, trace_endpos, vlen(trace_endpos - org) / vlen(e.velocity));
-               remove(e);
+               delete(e);
        }
 
        trigger_push_link(this);
index e03f14d335a2bf9aad0db26bbc11e1bcf7b9e832..76d244da55b2d0b8e814b1d3574b53f293c01ff6 100644 (file)
@@ -1,5 +1,4 @@
-#ifndef T_JUMPPADS_H
-#define T_JUMPPADS_H
+#pragma once
 
 const float PUSH_ONCE          = 1;
 const float PUSH_SILENT                = 2;
@@ -59,4 +58,3 @@ spawnfunc(target_push);
 spawnfunc(info_notnull);
 spawnfunc(target_position);
 #endif
-#endif
index 2cc81e597c0815a6de9d60b5780a24c240dfc210..eabb84f57ac4bb5c06960e855659ba34a1bbce96 100644 (file)
@@ -15,7 +15,7 @@ void trigger_keylock_kill(string s)
 {
        entity t;
        for(t = NULL; (t = find(t, targetname, s)); )
-               remove(t);
+               delete(t);
 }
 
 void trigger_keylock_touch(entity this, entity toucher)
@@ -74,7 +74,7 @@ void trigger_keylock_touch(entity this, entity toucher)
                if(this.killtarget)
                        trigger_keylock_kill(this.killtarget);
 
-               remove(this);
+               delete(this);
        }
 
 }
@@ -121,7 +121,7 @@ message2 and noise2 will be resent to the player every 2 seconds while he is in
 */
 spawnfunc(trigger_keylock)
 {
-       if(!this.itemkeys) { remove(this); return; }
+       if(!this.itemkeys) { delete(this); return; }
 
        // set unlocked message
        if(this.message == "")
index b54f99dcd411eead96c2cfcc723767ba3b087850..9260c01ac2817e1f6920139f1f7b9c1c42895056 100644 (file)
@@ -34,7 +34,7 @@ void trigger_secret_touch(entity this, entity toucher)
 
        // handle normal trigger features
        multi_touch(this, toucher);
-       remove(this);
+       delete(this);
 }
 
 /*QUAKED trigger_secret (.5 .5 .5) ?
index c2a155ce72e0114e790e092d56dceacca0f25c74..e483316a4086da58721cea32794b1d5f5de3453c 100644 (file)
@@ -1,5 +1,4 @@
-#ifndef SECRET_H
-#define SECRET_H
+#pragma once
 #ifdef SVQC
 
 /**
@@ -21,4 +20,3 @@ float secrets_found;
  */
 void secrets_setstatus(entity this);
 #endif
-#endif
index 0f8d1a73eebb46b4780f2b2e1758fbeda3d7aff2..99eb846c7305be7dafb0c711bfd28637241c3eed 100644 (file)
@@ -45,7 +45,7 @@ void swampslug_think(entity this)
        if(this.health <= 0)
        {
                this.owner.in_swamp = 0;
-               remove(this);
+               delete(this);
                //centerprint(this.owner,"Killing slug...\n");
                return;
        }
index 7ae50bac42a9b7d4bbc7fc6ba5582b6fd2fd4993..f4df98378d544659b1c22f0c663919fb95f90c17 100644 (file)
@@ -1,5 +1,4 @@
-#ifndef TRIGGER_SWAMP_H
-#define TRIGGER_SWAMP_H
+#pragma once
 
 .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 (!?)
@@ -7,5 +6,3 @@
 
 .float in_swamp;              // bool
 .entity swampslug;            // Uses this to release from swamp ("untouch" fix)
-
-#endif
index 9d675bbc734dbba6ad08ea4a549b005297b779cc..f2a0e86cc33be9aadae80058f36ddd603e53ac0b 100644 (file)
@@ -71,7 +71,7 @@ void viewloc_init(entity this)
                        break;
                }
 
-       if(!this.enemy) { LOG_INFO("^1FAIL!\n"); remove(this); return; }
+       if(!this.enemy) { LOG_INFO("^1FAIL!\n"); delete(this); return; }
 
        if(!this.goalentity)
                this.goalentity = this.enemy; // make them match so CSQC knows what to do
@@ -85,7 +85,7 @@ void viewloc_init(entity this)
 spawnfunc(trigger_viewlocation)
 {
        // we won't check target2 here yet, as it may not even need to exist
-       if(this.target == "") { LOG_INFO("^1FAIL!\n"); remove(this); return; }
+       if(this.target == "") { LOG_INFO("^1FAIL!\n"); delete(this); return; }
 
        EXACTTRIGGER_INIT;
        InitializeEntity(this, viewloc_init, INITPRIO_FINDTARGET);
index 881197a3b82fb57b7c96bc4f16ed3c14fd527b04..167fc218f7707c5f00b2f70d612d654f21ee1999 100644 (file)
@@ -1,5 +1,4 @@
-#ifndef T_VIEWLOC_H
-#define T_VIEWLOC_H
+#pragma once
 
 .entity viewloc;
 
@@ -8,5 +7,3 @@
 .entity enemy;
 .vector movedir;
 #endif
-
-#endif
index a9050357f6e97b5bf7851968239bb266404b5f57..849d3e8acb27ef9efba748c6ab5bab0b14178ab7 100644 (file)
@@ -5,7 +5,7 @@ void SUB_UseTargets(entity this, entity actor, entity trigger);
 void DelayThink(entity this)
 {
        SUB_UseTargets (this, this.enemy, NULL);
-       remove(this);
+       delete(this);
 }
 
 void FixSize(entity e)
@@ -225,7 +225,7 @@ void SUB_UseTargets(entity this, entity actor, entity trigger)
        if (s != "")
        {
                for(entity t = NULL; (t = find(t, targetname, s)); )
-                       remove(t);
+                       delete(t);
        }
 #endif
 
index 82c0916c19228c2dd6605b24a6f503d6b3c07061..8a8eb566c19b2ed844035390e6236e78fd1e18b3 100644 (file)
@@ -1,5 +1,4 @@
-#ifndef TRIGGERS_H
-#define TRIGGERS_H
+#pragma once
 
 const float SF_TRIGGER_INIT = 1;
 const float SF_TRIGGER_UPDATE = 2;
@@ -50,5 +49,3 @@ const int ACTIVE_IDLE                 = 2;
 const int ACTIVE_BUSY          = 2;
 const int ACTIVE_TOGGLE                = 3;
 #endif
-
-#endif
index a993b9218a22cf77ae2df4f80870d2115b3b9fde..476da2d18e0423d7c242963fc14408ff3e7d7ad1 100644 (file)
@@ -1,5 +1,4 @@
-#ifndef TURRETS_ALL_H
-#define TURRETS_ALL_H
+#pragma once
 
 #include <common/command/all.qh>
 #include "config.qh"
@@ -75,5 +74,3 @@ const int TUR_FIRST = 1;
 REGISTER_TURRET(Null, NEW(Turret));
 
 #include "turret/_mod.inc"
-
-#endif
index dc48fd1156bacf3c114c23dd04740ee5726d4921..fb56d3ecc93026e892066e1d193d9030791bb3c1 100644 (file)
@@ -56,7 +56,7 @@ void turret_checkpoint_init(entity this)
     {
         this.enemy = find(NULL, targetname, this.target);
         if(this.enemy == NULL)
-            LOG_TRACE("A turret_checkpoint faild to find its target!\n");
+            LOG_TRACE("A turret_checkpoint faild to find its target!");
     }
     //setthink(this, turret_checkpoint_think);
     //this.nextthink = time + tc_acum + 0.25;
index 8fd5cb08cf363e9dac1ee8f074082083234e0b3e..29658b56b459ade61ef0f89a2e8a3f58fed3d2ec 100644 (file)
@@ -1,6 +1,6 @@
 void turret_remove(entity this)
 {
-       remove(this.tur_head);
+       delete(this.tur_head);
        //remove(this.enemy);
        this.tur_head = NULL;
 }
@@ -202,7 +202,7 @@ void turret_draw2d(entity this)
                        );
 }
 
-void turret_construct(entity this)
+void turret_construct(entity this, bool isnew)
 {
        entity tur = get_turretinfo(this.m_id);
 
@@ -238,11 +238,16 @@ void turret_construct(entity this)
        this.tur_head.drawmask                  = MASK_NORMAL;
        this.anim_start_time                    = 0;
        this.draw2d = turret_draw2d;
-       IL_PUSH(g_drawables_2d, this);
        this.maxdistance = autocvar_g_waypointsprite_turrets_maxdist;
        this.teamradar_color = '1 0 0';
        this.alpha = 1;
 
+       if(isnew)
+       {
+               IL_PUSH(g_drawables, this);
+               IL_PUSH(g_drawables_2d, this);
+       }
+
        tur.tr_setup(tur, this);
 }
 
@@ -259,14 +264,14 @@ void turret_gib_draw(entity this)
                if(time >= this.nextthink)
                {
                        turret_gibboom(this);
-                       remove(this);
+                       delete(this);
                }
        }
        else
        {
                this.alpha = bound(0, this.nextthink - time, 1);
                if(this.alpha < ALPHA_MIN_VISIBLE)
-                       remove(this);
+                       delete(this);
        }
 }
 
@@ -370,7 +375,7 @@ NET_HANDLE(ENT_CLIENT_TURRET, bool isnew)
                this.angles_x = ReadAngle();
                this.angles_y = ReadAngle();
 
-               turret_construct(this);
+               turret_construct(this, isnew);
                this.colormap = 1024;
                this.glowmod = '0 1 1';
                this.tur_head.colormap = this.colormap;
index bb2a81b847eb740251b5ba126335dfd8295e5e49..caa68a86487dcd3780eb9c277f93aab8eacaa635 100644 (file)
@@ -1,5 +1,4 @@
-#ifndef TURRETS_CONFIG_H
-#define TURRETS_CONFIG_H
+#pragma once
 
 #ifdef SVQC
 
@@ -17,5 +16,3 @@ string tur_config_queue[MAX_TUR_CONFIG];
 
 
 #endif
-
-#endif
index 71181f209eeed787652d166d2a9e0e1e345a425c..a387fefc47c459797da84069f3476fbe5dd0ffe8 100644 (file)
@@ -193,8 +193,8 @@ void turret_die(entity this)
        {
                tur.tr_death(tur, this);
 
-               remove(this.tur_head);
-               remove(this);
+               delete(this.tur_head);
+               delete(this);
        }
        else
        {
@@ -440,7 +440,7 @@ void turret_projectile_explode(entity this)
 #else
        RadiusDamage (this, this.realowner, this.owner.shot_dmg, 0, this.owner.shot_radius, this, NULL, this.owner.shot_force, this.totalfrags, NULL);
 #endif
-       remove(this);
+       delete(this);
 }
 
 void turret_projectile_touch(entity this, entity toucher)
@@ -476,7 +476,8 @@ entity turret_projectile(entity actor, Sound _snd, float _size, float _health, f
        proj.nextthink    = time + 9;
        set_movetype(proj, MOVETYPE_FLYMISSILE);
        proj.velocity           = normalize(actor.tur_shotdir_updated + randomvec() * actor.shot_spread) * actor.shot_speed;
-       proj.flags                = FL_PROJECTILE;
+       proj.flags = FL_PROJECTILE;
+       IL_PUSH(g_projectiles, proj);
        proj.enemy                = actor.enemy;
        proj.totalfrags  = _death;
        PROJECTILE_MAKETRIGGER(proj);
@@ -824,7 +825,7 @@ float turret_validate_target(entity e_turret, entity e_target, float validate_fl
        */
 
 #ifdef TURRET_DEBUG_TARGETSELECT
-       LOG_TRACE("Target:",e_target.netname," is a valid target for ",e_turret.netname,"\n");
+       LOG_TRACE("Target:",e_target.netname," is a valid target for ",e_turret.netname);
 #endif
 
        return 1;
@@ -1174,7 +1175,7 @@ void turret_think(entity this)
 */
 void turret_use(entity this, entity actor, entity trigger)
 {
-       LOG_TRACE("Turret ",this.netname, " used by ", actor.classname, "\n");
+       LOG_TRACE("Turret ",this.netname, " used by ", actor.classname);
 
        this.team = actor.team;
 
@@ -1199,7 +1200,8 @@ void turrets_manager_think(entity this)
 
        if (autocvar_g_turrets_reloadcvars == 1)
        {
-               FOREACH_ENTITY_FLAGS(turret_flags, TUR_FLAG_ISTURRET, {
+               IL_EACH(g_turrets, true,
+               {
                        load_unit_settings(it, true);
                        Turret tur = get_turretinfo(it.m_id);
                        tur.tr_think(tur, it);
@@ -1248,6 +1250,7 @@ bool turret_initialize(entity this, Turret tur)
        // if tur_head exists, we can assume this turret re-spawned
        if(!this.tur_head) {
                tur.tr_precache(tur);
+               IL_PUSH(g_turrets, this);
        }
 
        entity e = find(NULL, classname, "turret_manager");
@@ -1349,7 +1352,7 @@ bool turret_initialize(entity this, Turret tur)
        this.tur_head.owner                     = this;
        this.tur_head.takedamage        = DAMAGE_NO;
        this.tur_head.solid                     = SOLID_NOT;
-       this.tur_head.move_movetype             = this.move_movetype;
+       set_movetype(this.tur_head, this.move_movetype);
 
        if(!this.tur_defend)
        if(this.target != "")
@@ -1358,7 +1361,7 @@ bool turret_initialize(entity this, Turret tur)
                if (this.tur_defend == NULL)
                {
                        this.target = "";
-                       LOG_TRACE("Turret has invalid defendpoint!\n");
+                       LOG_TRACE("Turret has invalid defendpoint!");
                }
        }
 
index 29d08c6290fd6a0699204197e2484283b591c669..c5a3728d134cf20b1e2f068dc803ff943b647cad 100644 (file)
@@ -1,5 +1,4 @@
-#ifndef SV_TURRETS_H
-#define SV_TURRETS_H
+#pragma once
 
 entity turret_projectile(entity actor, Sound _snd, float _size, float _health, float _death, float _proj_type, float _cull, float _cli_anim);
 void turret_projectile_explode(entity this);
@@ -119,5 +118,3 @@ vector tvt_tadv; // turret angle diff vector, updated by a successful call to tu
 float tvt_thadf; // turret head angle diff float, updated by a successful call to turret_validate_target
 float tvt_tadf; // turret angle diff float, updated by a successful call to turret_validate_target
 float tvt_dist; // turret distance, updated by a successful call to turret_validate_target
-
-#endif
index 62ed2fb722dc6cca55a20d4460f391681cc058e3..ca94f2b4e1fbee55b2a219b1959d2f5bd8c9c94f 100644 (file)
@@ -16,7 +16,7 @@ void turret_targettrigger_touch(entity this, entity toucher)
 */
 spawnfunc(turret_targettrigger)
 {
-    if(!autocvar_g_turrets) { remove(this); return; }
+    if(!autocvar_g_turrets) { delete(this); return; }
 
     InitTrigger(this);
 
index a66952833a10fe877c7ba2a806cc474da50be5ba..649fd51ae697eb4454871b8aa063cb1612f49419 100644 (file)
@@ -1,27 +1,26 @@
-#ifndef TURRET_H
-#define TURRET_H
+#pragma once
 
 #include <common/weapons/all.qh>
 
 CLASS(Turret, Object)
-    ATTRIB(Turret, m_id, int, 0)
+    ATTRIB(Turret, m_id, int, 0);
 
     /** short name */
-    ATTRIB(Turret, netname, string, string_null)
+    ATTRIB(Turret, netname, string);
     /** human readable name */
-    ATTRIB(Turret, turret_name, string, _("Turret"))
+    ATTRIB(Turret, turret_name, string, _("Turret"));
     /** currently a copy of the model */
-    ATTRIB(Turret, mdl, string, string_null)
+    ATTRIB(Turret, mdl, string);
     /** full name of model */
-    ATTRIB(Turret, model, string, string_null)
+    ATTRIB(Turret, model, string);
     /** full name of tur_head model */
-    ATTRIB(Turret, head_model, string, string_null)
+    ATTRIB(Turret, head_model, string);
 
-    ATTRIB(Turret, spawnflags, int, 0)
+    ATTRIB(Turret, spawnflags, int, 0);
     /** turret hitbox size */
-    ATTRIB(Turret, mins, vector, '-0 -0 -0')
+    ATTRIB(Turret, mins, vector, '-0 -0 -0');
     /** turret hitbox size */
-    ATTRIB(Turret, maxs, vector, '0 0 0')
+    ATTRIB(Turret, maxs, vector, '0 0 0');
 
     METHOD(Turret, display, void(Turret this, void(string name, string icon) returns)) {
         returns(this.turret_name, string_null);
@@ -42,7 +41,7 @@ CLASS(Turret, Object)
     METHOD(Turret, tr_precache, void(Turret this)) {
 
     }
-    ATTRIB(Turret, m_weapon, Weapon, WEP_Null)
+    ATTRIB(Turret, m_weapon, Weapon);
 #ifdef SVQC
     /** (SERVER) called when turret attacks */
     METHOD(Turret, tr_attack, void(Turret this, entity it)) {
@@ -176,5 +175,3 @@ const int TNSF_MOVE         = 64;
 const int TNSF_ANIM         = 128;
 
 const int TNSF_FULL_UPDATE  = 16777215;
-
-#endif
index 62d7222ce496003b284e43342d766159a08f3ab1..a86acdb274d8ba99c45c53f3dba3ec59d216c593 100644 (file)
@@ -133,7 +133,7 @@ void ewheel_move_idle(entity this)
         movelib_brake_simple(this, (autocvar_g_turrets_unit_ewheel_speed_stop));
 }
 
-spawnfunc(turret_ewheel) { if(!turret_initialize(this, TUR_EWHEEL)) remove(this); }
+spawnfunc(turret_ewheel) { if(!turret_initialize(this, TUR_EWHEEL)) delete(this); }
 
 METHOD(EWheel, tr_think, void(EWheel thistur, entity it))
 {
@@ -196,12 +196,12 @@ METHOD(EWheel, tr_setup, void(EWheel this, entity it))
             e = find(NULL, targetname, it.target);
             if (!e)
             {
-                LOG_TRACE("Initital waypoint for ewheel does NOT exsist, fix your map!\n");
+                LOG_TRACE("Initital waypoint for ewheel does NOT exsist, fix your map!");
                 it.target = "";
             }
 
             if (e.classname != "turret_checkpoint")
-                LOG_TRACE("Warning: not a turrret path\n");
+                LOG_TRACE("Warning: not a turrret path");
             else
             {
 
@@ -257,7 +257,7 @@ void ewheel_draw(entity this)
         METHOD(EWheel, tr_setup, void(EWheel this, entity it))
         {
             it.gravity         = 1;
-            it.move_movetype = MOVETYPE_BOUNCE;
+            set_movetype(it, MOVETYPE_BOUNCE);
             it.move_time               = time;
             it.draw                    = ewheel_draw;
         }
index 17df7dac04ad81c8e7fc742b87a203d67cccdc97..e77b534022423e2ae72de04f2de5e4822c2de027 100644 (file)
@@ -12,7 +12,7 @@ METHOD(EWheelAttack, wr_think, void(entity thiswep, entity actor, .entity weapon
     if (!isPlayer || weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR_PRI(electro, refire))) {
         if (isPlayer) {
             turret_initparams(actor);
-            W_SetupShot_Dir(actor, v_forward, false, 0, SND_EWheelAttack_FIRE, CH_WEAPON_B, 0);
+            W_SetupShot_Dir(actor, weaponentity, v_forward, false, 0, SND_EWheelAttack_FIRE, CH_WEAPON_B, 0);
             actor.tur_shotdir_updated = w_shotdir;
             actor.tur_shotorg = w_shotorg;
             actor.tur_head = actor;
index 64b32d4a7c53f6cbd34210cf958ff18f024ef6c0..20eeb7759589b5d415a386b141954ce9e1456e5b 100644 (file)
@@ -22,7 +22,7 @@ REGISTER_TURRET(FLAC, NEW(Flac));
 
 #ifdef SVQC
 
-spawnfunc(turret_flac) { if (!turret_initialize(this, TUR_FLAC)) remove(this); }
+spawnfunc(turret_flac) { if (!turret_initialize(this, TUR_FLAC)) delete(this); }
 
 METHOD(Flac, tr_setup, void(Flac this, entity it))
 {
index 3037f65d0d3c9554abb200494c193abfa9657f15..357bba975d853cfcd6cb50af66692cb16165a099 100644 (file)
@@ -12,7 +12,7 @@ METHOD(FlacAttack, wr_think, void(entity thiswep, entity actor, .entity weaponen
     if (!isPlayer || weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR_PRI(electro, refire))) {
         if (isPlayer) {
             turret_initparams(actor);
-            W_SetupShot_Dir(actor, v_forward, false, 0, SND_FlacAttack_FIRE, CH_WEAPON_B, 0);
+            W_SetupShot_Dir(actor, weaponentity, v_forward, false, 0, SND_FlacAttack_FIRE, CH_WEAPON_B, 0);
             actor.tur_shotdir_updated = w_shotdir;
             actor.tur_shotorg = w_shotorg;
             actor.tur_head = actor;
@@ -49,7 +49,7 @@ void turret_flac_projectile_think_explode(entity this)
 #else
     RadiusDamage (this, this.realowner, this.owner.shot_dmg, this.owner.shot_dmg, this.owner.shot_radius, this, NULL, this.owner.shot_force, this.totalfrags, NULL);
 #endif
-    remove(this);
+    delete(this);
 }
 
 #endif
index 945b35dd0a4af2839772a953bfb7d7ac2c348385..cd7dbec72d34bc62fc573875d4244eb767694c55 100644 (file)
@@ -46,7 +46,7 @@ bool turret_fusionreactor_firecheck(entity this)
     return true;
 }
 
-spawnfunc(turret_fusionreactor) { if (!turret_initialize(this, TUR_FUSIONREACTOR)) remove(this); }
+spawnfunc(turret_fusionreactor) { if (!turret_initialize(this, TUR_FUSIONREACTOR)) delete(this); }
 
 METHOD(FusionReactor, tr_attack, void(FusionReactor this, entity it))
 {
index fde81bfea02e8dd5b8acac71edb090efa8efd902..61203ddf75cb5a599a517251e76d3636f5e0311f 100644 (file)
@@ -22,7 +22,7 @@ REGISTER_TURRET(HELLION, NEW(Hellion));
 
 #ifdef SVQC
 
-spawnfunc(turret_hellion) { if (!turret_initialize(this, TUR_HELLION)) remove(this); }
+spawnfunc(turret_hellion) { if (!turret_initialize(this, TUR_HELLION)) delete(this); }
 
 METHOD(Hellion, tr_think, void(Hellion thistur, entity it))
 {
index 9e737ea6cf12e921fb2e48828b739ef382a5f0e3..ea392ec4ed9540f94fde30c999c5ae8aed3c1841 100644 (file)
@@ -15,7 +15,7 @@ METHOD(HellionAttack, wr_think, void(entity thiswep, entity actor, .entity weapo
     if (!isPlayer || weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR_PRI(electro, refire))) {
         if (isPlayer) {
             turret_initparams(actor);
-            W_SetupShot_Dir(actor, v_forward, false, 0, SND_HellionAttack_FIRE, CH_WEAPON_B, 0);
+            W_SetupShot_Dir(actor, weaponentity, v_forward, false, 0, SND_HellionAttack_FIRE, CH_WEAPON_B, 0);
             actor.tur_shotdir_updated = w_shotdir;
             actor.tur_shotorg = w_shotorg;
             actor.tur_head = actor;
@@ -33,7 +33,6 @@ METHOD(HellionAttack, wr_think, void(entity thiswep, entity actor, .entity weapo
         te_explosion (missile.origin);
         setthink(missile, turret_hellion_missile_think);
         missile.nextthink      = time;
-        missile.flags          = FL_PROJECTILE;
         missile.max_health   = time + 9;
         missile.tur_aimpos   = randomvec() * 128;
         missile.missile_flags = MIF_SPLASH | MIF_PROXY | MIF_GUIDED_HEAT;
index da107922f19e5c9cc46cf0a6d3d71e93f9b9ef55..9cb60df4c63a227932d91be5bb7d5b716db05523 100644 (file)
@@ -28,7 +28,7 @@ REGISTER_TURRET(HK, NEW(HunterKiller));
 .float atime;
 #endif
 
-spawnfunc(turret_hk) { if(!turret_initialize(this, TUR_HK)) remove(this); }
+spawnfunc(turret_hk) { if(!turret_initialize(this, TUR_HK)) delete(this); }
 
 METHOD(HunterKiller, tr_think, void(HunterKiller thistur, entity it))
 {
index c2e9d6a14691dc5d5d3be5e31bd9e8bd75e87c1c..ddad35d025e68e973f0b0520dc09a70a9cd17f94 100644 (file)
@@ -20,7 +20,7 @@ METHOD(HunterKillerAttack, wr_think, void(entity thiswep, entity actor, .entity
        if (!isPlayer || weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR_PRI(electro, refire))) {
                if (isPlayer) {
             turret_initparams(actor);
-            W_SetupShot_Dir(actor, v_forward, false, 0, SND_HunterKillerAttack_FIRE, CH_WEAPON_B, 0);
+            W_SetupShot_Dir(actor, weaponentity, v_forward, false, 0, SND_HunterKillerAttack_FIRE, CH_WEAPON_B, 0);
             actor.tur_shotdir_updated = w_shotdir;
             actor.tur_shotorg = w_shotorg;
             actor.tur_head = actor;
index 5dac49efc785a3d76f8236659f39bd4ae22f9f9c..8addd9542802a4c07cf80c750187cada65fafcdf 100644 (file)
@@ -22,7 +22,7 @@ REGISTER_TURRET(MACHINEGUN, NEW(MachineGunTurret));
 
 #ifdef SVQC
 
-spawnfunc(turret_machinegun) { if (!turret_initialize(this, TUR_MACHINEGUN)) remove(this); }
+spawnfunc(turret_machinegun) { if (!turret_initialize(this, TUR_MACHINEGUN)) delete(this); }
 
 METHOD(MachineGunTurret, tr_setup, void(MachineGunTurret this, entity it))
 {
index 34cd32d74279c07a8ebda0744d5cab5e422a1810..44c8d645990152caf90e8b7b67e70e79e559f089 100644 (file)
@@ -4,7 +4,7 @@
 
 #ifdef SVQC
 
-void W_MachineGun_MuzzleFlash(entity actor);
+void W_MachineGun_MuzzleFlash(entity actor, .entity weaponentity);
 SOUND(MachineGunTurretAttack_FIRE, W_Sound("electro_fire"));
 METHOD(MachineGunTurretAttack, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
 {
@@ -13,15 +13,15 @@ METHOD(MachineGunTurretAttack, wr_think, void(entity thiswep, entity actor, .ent
     if (!isPlayer || weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR(machinegun, sustained_refire))) {
         if (isPlayer) {
             turret_initparams(actor);
-            W_SetupShot_Dir(actor, v_forward, false, 0, SND_MachineGunTurretAttack_FIRE, CH_WEAPON_B, 0);
+            W_SetupShot_Dir(actor, weaponentity, v_forward, false, 0, SND_MachineGunTurretAttack_FIRE, CH_WEAPON_B, 0);
             actor.tur_shotdir_updated = w_shotdir;
             actor.tur_shotorg = w_shotorg;
             actor.tur_head = actor;
             weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, 0, w_ready);
         }
         fireBullet (actor, actor.tur_shotorg, actor.tur_shotdir_updated, actor.shot_spread, 0, actor.shot_dmg, actor.shot_force, DEATH_TURRET_MACHINEGUN.m_id, 0);
-        W_MachineGun_MuzzleFlash(actor);
-        setattachment(actor.muzzle_flash, actor.tur_head, "tag_fire");
+        W_MachineGun_MuzzleFlash(actor, weaponentity);
+        setattachment(actor.(weaponentity).muzzle_flash, actor.tur_head, "tag_fire");
     }
 }
 
index bce27118a2ce34dc9ba605aa47d1adf78ea416c2..316d3b9a0589f9d4941c962ee365cc20c5ede8c7 100644 (file)
@@ -22,7 +22,7 @@ REGISTER_TURRET(MLRS, NEW(MLRSTurret));
 
 #ifdef SVQC
 
-spawnfunc(turret_mlrs) { if (!turret_initialize(this, TUR_MLRS)) remove(this); }
+spawnfunc(turret_mlrs) { if (!turret_initialize(this, TUR_MLRS)) delete(this); }
 
 METHOD(MLRSTurret, tr_think, void(MLRSTurret thistur, entity it))
 {
@@ -30,8 +30,8 @@ METHOD(MLRSTurret, tr_think, void(MLRSTurret thistur, entity it))
     it.tur_head.frame = bound(0, 6 - floor(0.1 + it.ammo / it.shot_dmg), 6);
     if(it.tur_head.frame < 0)
     {
-        LOG_TRACE("ammo:",ftos(it.ammo),"\n");
-        LOG_TRACE("shot_dmg:",ftos(it.shot_dmg),"\n");
+        LOG_TRACE("ammo:",ftos(it.ammo));
+        LOG_TRACE("shot_dmg:",ftos(it.shot_dmg));
     }
 }
 METHOD(MLRSTurret, tr_setup, void(MLRSTurret this, entity it))
index 305392cd5ad03a65020d33fb0e8aca7300ab616f..cfd51c732076b2686fc9ae12e96adae33db462ea 100644 (file)
@@ -11,7 +11,7 @@ METHOD(MLRSTurretAttack, wr_think, void(entity thiswep, entity actor, .entity we
     if (!isPlayer || weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR(machinegun, sustained_refire))) {
         if (isPlayer) {
             turret_initparams(actor);
-            W_SetupShot_Dir(actor, v_forward, false, 0, SND_MLRSTurretAttack_FIRE, CH_WEAPON_B, 0);
+            W_SetupShot_Dir(actor, weaponentity, v_forward, false, 0, SND_MLRSTurretAttack_FIRE, CH_WEAPON_B, 0);
             actor.tur_shotdir_updated = w_shotdir;
             actor.tur_shotorg = w_shotorg;
             actor.tur_head = actor;
index f604b0466953707f98a59082ae7b0258cc06e665..7c5d336212694b662262ee9da99372b2857d6ace 100644 (file)
@@ -22,7 +22,7 @@ REGISTER_TURRET(PHASER, NEW(PhaserTurret));
 
 #ifdef SVQC
 
-spawnfunc(turret_phaser) { if (!turret_initialize(this, TUR_PHASER)) remove(this); }
+spawnfunc(turret_phaser) { if (!turret_initialize(this, TUR_PHASER)) delete(this); }
 
 .int fireflag;
 
index df68e1ce7feb7e3db811ef084a3798938ed6ab8f..2e08f5eb3d723cedefe9d790dbea66ee1c572f4e 100644 (file)
@@ -14,7 +14,7 @@ METHOD(PhaserTurretAttack, wr_think, void(entity thiswep, entity actor, .entity
     if (!isPlayer || weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR_PRI(electro, refire))) {
         if (isPlayer) {
             turret_initparams(actor);
-            W_SetupShot_Dir(actor, v_forward, false, 0, SND_PhaserTurretAttack_FIRE, CH_WEAPON_B, 0);
+            W_SetupShot_Dir(actor, weaponentity, v_forward, false, 0, SND_PhaserTurretAttack_FIRE, CH_WEAPON_B, 0);
             actor.tur_shotdir_updated = w_shotdir;
             actor.tur_shotorg = w_shotorg;
             actor.tur_head = actor;
@@ -60,7 +60,7 @@ void beam_think(entity this)
         this.owner.fireflag = 2;
         this.owner.tur_head.frame = 10;
         sound (this, CH_SHOTS_SINGLE, SND_Null, VOL_BASE, ATTEN_NORM);
-        remove(this);
+        delete(this);
         return;
     }
 
index 7b71ccfc7fa78be080d7b1fa1dba7f189550111d..82aa1abe67cbf198bfcd51c58e97af98741d5174 100644 (file)
@@ -22,7 +22,7 @@ REGISTER_TURRET(PLASMA, NEW(PlasmaTurret));
 
 #ifdef SVQC
 
-spawnfunc(turret_plasma) { if (!turret_initialize(this, TUR_PLASMA)) remove(this); }
+spawnfunc(turret_plasma) { if (!turret_initialize(this, TUR_PLASMA)) delete(this); }
 
 METHOD(PlasmaTurret, tr_attack, void(PlasmaTurret this, entity it))
 {
index 86df15059bfc136ae83102ac93ed6cae39dbcbc1..9430bc69211147c6fb125330c2b9976c4c7c3d18 100644 (file)
@@ -28,7 +28,7 @@ REGISTER_TURRET(PLASMA_DUAL, NEW(DualPlasmaTurret));
 
 #ifdef SVQC
 
-spawnfunc(turret_plasma_dual) { if (!turret_initialize(this, TUR_PLASMA_DUAL)) remove(this); }
+spawnfunc(turret_plasma_dual) { if (!turret_initialize(this, TUR_PLASMA_DUAL)) delete(this); }
 
 METHOD(DualPlasmaTurret, tr_attack, void(DualPlasmaTurret thistur, entity it))
 {
index 535e8b4754661fa7fcf772415484e0c3a84f70c0..f6f717f85ff6b612974ec854de8888913199aa20 100644 (file)
@@ -10,7 +10,7 @@ METHOD(PlasmaAttack, wr_think, void(entity thiswep, entity actor, .entity weapon
        if (!isPlayer || weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR_PRI(electro, refire))) {
                if (isPlayer) {
             turret_initparams(actor);
-            W_SetupShot_Dir(actor, v_forward, false, 0, SND_PlasmaAttack_FIRE, CH_WEAPON_B, 0);
+            W_SetupShot_Dir(actor, weaponentity, v_forward, false, 0, SND_PlasmaAttack_FIRE, CH_WEAPON_B, 0);
             actor.tur_shotdir_updated = w_shotdir;
             actor.tur_shotorg = w_shotorg;
             actor.tur_head = actor;
index cdc6ba3ceb95a7d4fba543e26a0532d01dcdda4d..b0755f32b57d03e0371bb13734df96ca22b41886 100644 (file)
@@ -22,7 +22,7 @@ REGISTER_TURRET(TESLA, NEW(TeslaCoil));
 
 #ifdef SVQC
 
-spawnfunc(turret_tesla) { if (!turret_initialize(this, TUR_TESLA)) remove(this); }
+spawnfunc(turret_tesla) { if (!turret_initialize(this, TUR_TESLA)) delete(this); }
 
 METHOD(TeslaCoil, tr_think, void(TeslaCoil thistur, entity it))
 {
index 38a9335f7a8937d67a07802629f556cc0c2736e2..a173d8b675cbd590d1defb4ef85f424542fc736b 100644 (file)
@@ -12,7 +12,7 @@ METHOD(TeslaCoilTurretAttack, wr_think, void(entity thiswep, entity actor, .enti
     if (!isPlayer || weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR_PRI(electro, refire))) {
         if (isPlayer) {
             turret_initparams(actor);
-            W_SetupShot_Dir(actor, v_forward, false, 0, SND_TeslaCoilTurretAttack_FIRE, CH_WEAPON_B, 0);
+            W_SetupShot_Dir(actor, weaponentity, v_forward, false, 0, SND_TeslaCoilTurretAttack_FIRE, CH_WEAPON_B, 0);
             actor.tur_shotdir_updated = w_shotdir;
             actor.tur_shotorg = w_shotorg;
             actor.tur_head = actor;
@@ -27,7 +27,7 @@ METHOD(TeslaCoilTurretAttack, wr_think, void(entity thiswep, entity actor, .enti
         actor.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_MISSILES | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK;
 
         entity t = toast(actor, e,r,d);
-        remove(e);
+        delete(e);
 
         if (t == NULL) return;
 
index 3f55280e8fa372cf790d726b29eb41bde633e703..727da27f945aa4ef67a3a58a44504a4380b2e92a 100644 (file)
@@ -100,7 +100,7 @@ void walker_setnoanim(entity this)
 void walker_rocket_explode(entity this)
 {
     RadiusDamage (this, this.owner, (autocvar_g_turrets_unit_walker_rocket_damage), 0, (autocvar_g_turrets_unit_walker_rocket_radius), this, NULL, (autocvar_g_turrets_unit_walker_rocket_force), DEATH_TURRET_WALK_ROCKET.m_id, NULL);
-    remove (this);
+    delete (this);
 }
 
 void walker_rocket_touch(entity this, entity toucher)
@@ -259,7 +259,8 @@ void walker_fire_rocket(entity this, vector org)
     rocket.velocity               = normalize((v_forward + v_up * 0.5) + (randomvec() * 0.2)) * (autocvar_g_turrets_unit_walker_rocket_speed);
     rocket.angles                       = vectoangles(rocket.velocity);
     settouch(rocket, walker_rocket_touch);
-    rocket.flags                         = FL_PROJECTILE;
+    rocket.flags = FL_PROJECTILE;
+    IL_PUSH(g_projectiles, rocket);
     rocket.solid                         = SOLID_BBOX;
     rocket.max_health           = time + 9;
     rocket.missile_flags = MIF_SPLASH | MIF_PROXY | MIF_GUIDED_HEAT;
@@ -344,7 +345,7 @@ void walker_move_path(entity this)
 #endif
 }
 
-spawnfunc(turret_walker) { if(!turret_initialize(this, TUR_WALKER)) remove(this); }
+spawnfunc(turret_walker) { if(!turret_initialize(this, TUR_WALKER)) delete(this); }
 
 METHOD(WalkerTurret, tr_think, void(WalkerTurret thistur, entity it))
 {
@@ -607,12 +608,12 @@ METHOD(WalkerTurret, tr_setup, void(WalkerTurret this, entity it))
         e = find(NULL, targetname, it.target);
         if (!e)
         {
-            LOG_TRACE("Initital waypoint for walker does NOT exsist, fix your map!\n");
+            LOG_TRACE("Initital waypoint for walker does NOT exsist, fix your map!");
             it.target = "";
         }
 
         if (e.classname != "turret_checkpoint")
-            LOG_TRACE("Warning: not a turrret path\n");
+            LOG_TRACE("Warning: not a turrret path");
         else
         {
 #ifdef WALKER_FANCYPATHING
@@ -652,7 +653,7 @@ void walker_draw(entity this)
         METHOD(WalkerTurret, tr_setup, void(WalkerTurret this, entity it))
         {
             it.gravity         = 1;
-            it.move_movetype   = MOVETYPE_BOUNCE;
+            set_movetype(it, MOVETYPE_BOUNCE);
             it.move_time               = time;
             it.draw                    = walker_draw;
         }
index 91e4345a95b3f6c6c0e58f79dfe8d7b5198c5867..88b18b9198385bb8b5027fc2139c61750f0680eb 100644 (file)
@@ -11,7 +11,7 @@ METHOD(WalkerTurretAttack, wr_think, void(entity thiswep, entity actor, .entity
     if (!isPlayer || weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR_PRI(electro, refire))) {
         if (isPlayer) {
             turret_initparams(actor);
-            W_SetupShot_Dir(actor, v_forward, false, 0, SND_WalkerTurretAttack_FIRE, CH_WEAPON_B, 0);
+            W_SetupShot_Dir(actor, weaponentity, v_forward, false, 0, SND_WalkerTurretAttack_FIRE, CH_WEAPON_B, 0);
             actor.tur_shotdir_updated = w_shotdir;
             actor.tur_shotorg = w_shotorg;
             actor.tur_head = actor;
index 2c33c165a7fa3a2acf39e375a46c17f393969fe0..8a6a5ee87bc06716cfebceb362af3217420a4476 100644 (file)
@@ -6,7 +6,7 @@ float turret_tag_fire_update(entity this)
 {
        if(!this.tur_head)
        {
-               LOG_DEBUG("Call to turret_tag_fire_update with this.tur_head missing!\n");
+               LOG_DEBUG("Call to turret_tag_fire_update with this.tur_head missing!");
                this.tur_shotorg = '0 0 0';
                return false;
        }
index d5c948d573e85fb46b2cc28de60d413989766392..5f52695bafe7b2df5d9c26e8c6f74ffaa78b73b0 100644 (file)
@@ -1,5 +1,4 @@
-#ifndef TURRETS_UTIL_H
-#define TURRETS_UTIL_H
+#pragma once
 
 float shortangle_f(float ang1, float ang2);
 float anglemods(float v);
@@ -8,5 +7,3 @@ vector shortangle_vxy(vector ang1, vector ang2);
 vector angleofs(entity from, entity to);
 vector angleofs3(vector from, vector from_a, entity to);
 void FireImoBeam(entity this, vector start, vector end, vector smin, vector smax, float bforce, float f_dmg, float f_velfactor, float deathtype);
-
-#endif
index d04fdecd68dc791f05a8fe93878ed0e6185822b4..9cf439f52bdca0e9a33e93bb626246f8ba4a3886 100644 (file)
@@ -325,7 +325,7 @@ float compressShortVector(vector vec)
        return (p * 0x1000) + (y * 0x80) + len;
 }
 
-void compressShortVector_init()
+STATIC_INIT(compressShortVector)
 {
        float l = 1;
        float f = pow(2, 1/8);
@@ -472,7 +472,7 @@ void get_mi_min_max(float mode)
 
        mi_min = mi;
        mi_max = ma;
-       MapInfo_Get_ByName(mi_shortname, 0, 0);
+       MapInfo_Get_ByName(mi_shortname, 0, NULL);
        if(MapInfo_Map_mins.x < MapInfo_Map_maxs.x)
        {
                mi_min = MapInfo_Map_mins;
@@ -592,7 +592,7 @@ float cvar_settemp(string tmp_cvar, string tmp_value)
 
        if (!(tmp_cvar || tmp_value))
        {
-               LOG_TRACE("Error: Invalid usage of cvar_settemp(string, string); !\n");
+               LOG_TRACE("Error: Invalid usage of cvar_settemp(string, string); !");
                return 0;
        }
 
@@ -635,7 +635,7 @@ int cvar_settemp_restore()
                        cvar_set(it.netname, it.message);
                        strunzone(it.netname);
                        strunzone(it.message);
-                       remove(it);
+                       delete(it);
                        ++j;
                }
                else
@@ -649,7 +649,7 @@ int cvar_settemp_restore()
                if(cvar_type(e.netname))
                {
                        cvar_set(e.netname, e.message);
-                       remove(e);
+                       delete(e);
                        ++j;
                }
                else
@@ -932,7 +932,7 @@ string textShortenToLength(string theText, float maxWidth, textLengthUpToLength_
                return strcat(substring(theText, 0, textLengthUpToLength(theText, maxWidth - tw("..."), tw)), "...");
 }
 
-float isGametypeInFilter(float gt, float tp, float ts, string pattern)
+float isGametypeInFilter(Gametype gt, float tp, float ts, string pattern)
 {
        string subpattern, subpattern2, subpattern3, subpattern4;
        subpattern = strcat(",", MapInfo_Type_ToString(gt), ",");
index fa17a06a328af4414350a1a9a29632f5114cd34b..599dd4d43c5b4bc5abd6f8be6d1a2e28608a0fa4 100644 (file)
@@ -1,5 +1,4 @@
-#ifndef COMMON_UTIL_H
-#define COMMON_UTIL_H
+#pragma once
 
 #ifndef MENUQC
 
@@ -64,7 +63,6 @@ const float TIME_FACTOR = 100;
 
 string ScoreString(float vflags, float value);
 
-void compressShortVector_init();
 vector decompressShortVector(float data);
 float compressShortVector(vector vec);
 
@@ -126,7 +124,7 @@ string getWrappedLine_remaining;
 string getWrappedLine(float w, vector size, textLengthUpToWidth_widthFunction_t tw);
 string getWrappedLineLen(float w, textLengthUpToLength_lenFunction_t tw);
 
-float isGametypeInFilter(float gt, float tp, float ts, string pattern);
+float isGametypeInFilter(entity gt, float tp, float ts, string pattern);
 
 string swapwords(string str, float i, float j);
 string shufflewords(string str);
@@ -233,9 +231,6 @@ float ReadApproxPastTime();
 void execute_next_frame();
 void queue_to_execute_next_frame(string s);
 
-// for marking written-to values as unused where it's a good idea to do this
-noref float unused_float;
-
 // a function f with:
 // f(0) = 0
 // f(1) = 1
@@ -297,4 +292,3 @@ vector bezier_quadratic_getderivative(vector a, vector p, vector b, float t);
 
 // Returns the correct difference between two always increasing numbers
 #define COMPARE_INCREASING(to,from) (to < from ? from + to + 2 : to - from)
-#endif
index b58389d4abb7955feb7c3c80934583fadd4f6f1b..158492f661e7e1326cc248283c3b4841bb64c76a 100644 (file)
@@ -1,5 +1,4 @@
-#ifndef VEHICLES_ALL_H
-#define VEHICLES_ALL_H
+#pragma once
 
 #include "vehicle.qh"
 
@@ -22,5 +21,3 @@ const int VEH_FIRST = 1;
 REGISTER_VEHICLE(Null, NEW(Vehicle));
 
 #include "vehicle/_mod.inc"
-
-#endif
index aeb7de83b7a60b77b22e9fdcfc2b67fbc44c2ab2..e08490976d15b253e303441933f2b122c69cac4c 100644 (file)
@@ -104,7 +104,7 @@ NET_HANDLE(TE_CSQC_VEHICLESETUP, bool isnew)
                        if(axh != NULL && !wasfreed(axh))
                        {
                                AuxiliaryXhair[i] = NULL;
-                               remove(axh);
+                               delete(axh);
                        }
                }
                return;
@@ -116,7 +116,7 @@ NET_HANDLE(TE_CSQC_VEHICLESETUP, bool isnew)
                entity axh = AuxiliaryXhair[i];
 
                if(axh != NULL && !wasfreed(axh))  // MADNESS? THIS IS QQQQCCCCCCCCC (wasfreed, why do you exsist?)
-                       remove(axh);
+                       delete(axh);
 
                axh              = spawn();
                axh.draw2d       = func_null;
@@ -187,7 +187,7 @@ void Vehicles_drawHUD(
                tmpPos.x = vehicleHud_Pos.x + vehicleHud_Size.x * (96/256) - tmpSize.x;
                tmpPos.y = vehicleHud_Pos.y;
                tmpSize = '1 1 1' * hud_fontsize;
-               drawstring(tmpPos, sprintf(_("Press %s"), getcommandkey("dropweapon", "dropweapon")), tmpSize, '1 0 0' + '0 1 1' * tmpblinkValue, hudAlpha, DRAWFLAG_NORMAL);
+               drawstring(tmpPos, sprintf(_("Press %s"), getcommandkey(_("drop weapon"), "dropweapon")), tmpSize, '1 0 0' + '0 1 1' * tmpblinkValue, hudAlpha, DRAWFLAG_NORMAL);
        }
 
        // Model
index 5293030c19fe9ecda1aad3c8e733edabc29eda72..327074b98641e72631bbb3089ecc3829b008dca5 100644 (file)
@@ -1,5 +1,4 @@
-#ifndef CL_VEHICLES_H
-#define CL_VEHICLES_H
+#pragma once
 
 vector vehicleHud_Size;
 vector vehicleHud_Pos;
@@ -8,5 +7,3 @@ void RaptorCBShellfragDraw(entity this);
 void RaptorCBShellfragToss(vector _org, vector _vel, vector _ang);
 
 #define weapon2mode STAT(VEHICLESTAT_W2MODE)
-
-#endif
index 4fd9a0d5231d38abfe5941e419717db50f2ae98d..39f959d14b9f03f851f6b8edebf6d3efd90008e3 100644 (file)
@@ -214,7 +214,7 @@ void vehicles_projectile_explode(entity this, entity toucher)
        this.event_damage = func_null;
        RadiusDamage (this, this.realowner, this.shot_dmg, 0, this.shot_radius, this, NULL, this.shot_force, this.totalfrags, toucher);
 
-       remove (this);
+       delete (this);
 }
 
 void vehicles_projectile_explode_think(entity this)
@@ -247,7 +247,8 @@ entity vehicles_projectile(entity this, string _mzlfx, Sound _mzlsound,
        proj.totalfrags    = _deahtype;
        proj.solid                      = SOLID_BBOX;
        set_movetype(proj, MOVETYPE_FLYMISSILE);
-       proj.flags                      = FL_PROJECTILE;
+       proj.flags = FL_PROJECTILE;
+       IL_PUSH(g_projectiles, proj);
        proj.bot_dodge          = true;
        proj.bot_dodgerating  = _dmg;
        proj.velocity            = _vel;
@@ -265,7 +266,7 @@ entity vehicles_projectile(entity this, string _mzlfx, Sound _mzlsound,
                proj.health                = _health;
        }
        else
-               proj.flags                 = FL_PROJECTILE | FL_NOTARGET;
+               proj.flags |= FL_NOTARGET;
 
        if(_mzlsound != SND_Null)
                sound (this, CH_WEAPON_A, _mzlsound, VOL_BASE, ATTEN_NORM);
@@ -285,7 +286,7 @@ void vehicles_gib_explode(entity this)
        sound (this, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM);
        Send_Effect(EFFECT_EXPLOSION_SMALL, randomvec() * 80 + (this.origin + '0 0 100'), '0 0 0', 1);
        Send_Effect(EFFECT_EXPLOSION_SMALL, this.wp00.origin + '0 0 64', '0 0 0', 1);
-       remove(this);
+       delete(this);
 }
 
 void vehicles_gib_touch(entity this, entity toucher)
@@ -297,7 +298,7 @@ void vehicles_gib_think(entity this)
 {
        this.alpha -= 0.1;
        if(this.cnt >= time)
-               remove(this);
+               delete(this);
        else
                this.nextthink = time + 0.1;
 }
@@ -338,7 +339,7 @@ bool vehicle_addplayerslot( entity _owner,
                                                                entity _slot,
                                                                int _hud,
                                                                Model _hud_model,
-                                                               bool(entity) _framefunc,
+                                                               bool(entity,float) _framefunc,
                                                                void(entity,bool) _exitfunc, float(entity, entity) _enterfunc)
 {
        if(!(_owner.vehicle_flags & VHF_MULTISLOT))
@@ -457,7 +458,7 @@ void vehicles_return(entity this)
        if(this.waypointsprite_attached)
                WaypointSprite_Kill(this.waypointsprite_attached);
 
-       remove(this);
+       delete(this);
 }
 
 void vehicles_showwp_goaway(entity this)
@@ -465,7 +466,7 @@ void vehicles_showwp_goaway(entity this)
        if(this.waypointsprite_attached)
                WaypointSprite_Kill(this.waypointsprite_attached);
 
-       remove(this);
+       delete(this);
 }
 
 void vehicles_showwp(entity this)
@@ -531,7 +532,7 @@ void vehicles_setreturn(entity veh)
 
 void vehicle_use(entity this, entity actor, entity trigger)
 {
-       LOG_DEBUG("vehicle ", this.netname, " used by ", actor.classname, "\n");
+       LOG_DEBUG("vehicle ", this.netname, " used by ", actor.classname);
 
        this.tur_head.team = actor.team;
 
@@ -542,7 +543,7 @@ void vehicle_use(entity this, entity actor, entity trigger)
 
        if(this.active == ACTIVE_ACTIVE && !IS_DEAD(this) && !gameover)
        {
-               LOG_DEBUG("Respawning vehicle: ", this.netname, "\n");
+               LOG_DEBUG("Respawning vehicle: ", this.netname);
                if(this.effects & EF_NODRAW)
                {
                        setthink(this, vehicles_spawn);
@@ -764,7 +765,7 @@ void vehicles_exit(entity vehic, bool eject)
 
        if(vehicles_exit_running)
        {
-               LOG_TRACE("^1vehicles_exit already running! this is not good...\n");
+               LOG_TRACE("^1vehicles_exit already running! this is not good...");
                return;
        }
 
@@ -1059,7 +1060,7 @@ void vehicles_reset(entity this)
 // initialization
 void vehicles_spawn(entity this)
 {
-       LOG_DEBUG("Spawning vehicle: ", this.classname, "\n");
+       LOG_DEBUG("Spawning vehicle: ", this.classname);
 
        // disown & reset
        this.vehicle_hudmodel.viewmodelforclient = this;
@@ -1115,14 +1116,17 @@ bool vehicle_initialize(entity this, Vehicle info, bool nodrop)
                return false;
 
        if(!this.tur_head)
+       {
                info.vr_precache(info);
+               IL_PUSH(g_vehicles, this);
+       }
 
        if(this.targetname && this.targetname != "")
        {
                this.vehicle_controller = find(NULL, target, this.targetname);
                if(!this.vehicle_controller)
                {
-                       LOG_DEBUG("^1WARNING: ^7Vehicle with invalid .targetname\n");
+                       LOG_DEBUG("^1WARNING: ^7Vehicle with invalid .targetname");
                        this.active = ACTIVE_ACTIVE;
                }
                else
index e593922fcb0f4beb788cc77ad65d1b0bf754cca2..158191f654eed354806d07cf2140d7a6db1176b4 100644 (file)
@@ -1,5 +1,4 @@
-#ifndef VEHICLES_DEF_H
-#define VEHICLES_DEF_H
+#pragma once
 #ifdef SVQC
 
 #include <common/turrets/sv_turrets.qh>
@@ -110,4 +109,3 @@ bool vehicles_crushable(entity e);
 float vehicle_altitude(entity this, float amax);
 
 #endif
-#endif
index 927465ea6b933ee0d98cf4bbdffc553567d56f7d..cb4225a27df3030664b3b0e624de795433f1be23 100644 (file)
@@ -1,40 +1,39 @@
-#ifndef VEHICLE_H
-#define VEHICLE_H
+#pragma once
 
 CLASS(Vehicle, Object)
-    ATTRIB(Vehicle, vehicleid, int, 0)
+    ATTRIB(Vehicle, vehicleid, int, 0);
     /** hud icon */
-    ATTRIB(Vehicle, m_icon, string, string_null)
+    ATTRIB(Vehicle, m_icon, string);
     /** short name */
-    ATTRIB(Vehicle, netname, string, "")
+    ATTRIB(Vehicle, netname, string, "");
     /** human readable name */
-    ATTRIB(Vehicle, vehicle_name, string, "Vehicle")
+    ATTRIB(Vehicle, vehicle_name, string, "Vehicle");
     /** full name of model */
-    ATTRIB(Vehicle, model, string, "")
+    ATTRIB(Vehicle, model, string, "");
     /** currently a copy of the model */
-    ATTRIB(Vehicle, mdl, string, "")
+    ATTRIB(Vehicle, mdl, string, "");
     /** full name of tur_head model */
-    ATTRIB(Vehicle, head_model, string, "")
+    ATTRIB(Vehicle, head_model, string, "");
     /** cockpit model */
-    ATTRIB(Vehicle, hud_model, string, "")
+    ATTRIB(Vehicle, hud_model, string, "");
     /** tur_head model tag */
-    ATTRIB(Vehicle, tag_head, string, string_null)
+    ATTRIB(Vehicle, tag_head, string);
     /** hud model tag */
-    ATTRIB(Vehicle, tag_hud, string, string_null)
+    ATTRIB(Vehicle, tag_hud, string);
     /** cockpit model tag */
-    ATTRIB(Vehicle, tag_view, string, string_null)
+    ATTRIB(Vehicle, tag_view, string);
     /** player physics mod */
-    ATTRIB(Vehicle, PlayerPhysplug, bool(entity), func_null)
+    ATTRIB(Vehicle, PlayerPhysplug, bool(entity,float));
     /**  */
-    ATTRIB(Vehicle, spawnflags, int, 0)
+    ATTRIB(Vehicle, spawnflags, int, 0);
     /** vehicle hitbox size */
-    ATTRIB(Vehicle, mins, vector, '-0 -0 -0')
+    ATTRIB(Vehicle, mins, vector, '-0 -0 -0');
     /** vehicle hitbox size */
-    ATTRIB(Vehicle, maxs, vector, '0 0 0')
+    ATTRIB(Vehicle, maxs, vector, '0 0 0');
     /** vehicle 3rd person view offset */
-    ATTRIB(Vehicle, view_ofs, vector, '0 0 0')
+    ATTRIB(Vehicle, view_ofs, vector, '0 0 0');
     /** vehicle 3rd person view distance */
-    ATTRIB(Vehicle, height, float, 0)
+    ATTRIB(Vehicle, height, float, 0);
 
     /** (BOTH) setup vehicle data */
     METHOD(Vehicle, vr_setup, void(Vehicle this, entity instance)) { }
@@ -76,5 +75,3 @@ const int VHF_PLAYERSLOT              = BIT(14); /// This ent is a player slot on a multi-pe
 
 // fields:
 .entity tur_head;
-
-#endif
index ff7f333ab27ce189d65aaac74740c0e04cf94f12..9f718e34b98a1ec28f22a8c01acf60970468ba85 100644 (file)
@@ -99,7 +99,7 @@ vector autocvar_g_vehicle_bumblebee_bouncepain = '1 100 200';
 
 bool autocvar_g_vehicle_bumblebee = true;
 
-bool bumblebee_gunner_frame(entity this)
+bool bumblebee_gunner_frame(entity this, float dt)
 {
        entity vehic = this.vehicle.owner;
        entity gun = this.vehicle;
@@ -313,7 +313,7 @@ bool bumblebee_gunner_enter(entity this, entity player)
        }
        else if(!vehic.gunner1 && time >= vehic.gun1.phase)     { gunner = vehic.gun1; vehic.gunner1 = player; }
        else if(!vehic.gunner2 && time >= vehic.gun2.phase)             { gunner = vehic.gun2; vehic.gunner2 = player; }
-       else { LOG_TRACE("Vehicle is full, fail\n"); return false; }
+       else { LOG_TRACE("Vehicle is full, fail"); return false; }
 
        player.vehicle                  = gunner;
        player.angles                   = vehic.angles;
@@ -394,28 +394,28 @@ void bumblebee_touch(entity this, entity toucher)
        vehicles_touch(this, toucher);
 }
 
-void bumblebee_regen(entity this)
+void bumblebee_regen(entity this, float dt)
 {
        if(this.gun1.delay + autocvar_g_vehicle_bumblebee_cannon_ammo_regen_pause < time)
                this.gun1.vehicle_energy = min(autocvar_g_vehicle_bumblebee_cannon_ammo,
-                                                                          this.gun1.vehicle_energy + autocvar_g_vehicle_bumblebee_cannon_ammo_regen * frametime);
+                                                                          this.gun1.vehicle_energy + autocvar_g_vehicle_bumblebee_cannon_ammo_regen * dt);
 
        if(this.gun2.delay + autocvar_g_vehicle_bumblebee_cannon_ammo_regen_pause < time)
                this.gun2.vehicle_energy = min(autocvar_g_vehicle_bumblebee_cannon_ammo,
-                                                                          this.gun2.vehicle_energy + autocvar_g_vehicle_bumblebee_cannon_ammo_regen * frametime);
+                                                                          this.gun2.vehicle_energy + autocvar_g_vehicle_bumblebee_cannon_ammo_regen * dt);
 
        if(this.vehicle_flags  & VHF_SHIELDREGEN)
-               vehicles_regen(this, this.dmg_time, vehicle_shield, autocvar_g_vehicle_bumblebee_shield, autocvar_g_vehicle_bumblebee_shield_regen_pause, autocvar_g_vehicle_bumblebee_shield_regen, frametime, true);
+               vehicles_regen(this, this.dmg_time, vehicle_shield, autocvar_g_vehicle_bumblebee_shield, autocvar_g_vehicle_bumblebee_shield_regen_pause, autocvar_g_vehicle_bumblebee_shield_regen, dt, true);
 
        if(this.vehicle_flags  & VHF_HEALTHREGEN)
-               vehicles_regen(this, this.dmg_time, vehicle_health, autocvar_g_vehicle_bumblebee_health, autocvar_g_vehicle_bumblebee_health_regen_pause, autocvar_g_vehicle_bumblebee_health_regen, frametime, false);
+               vehicles_regen(this, this.dmg_time, vehicle_health, autocvar_g_vehicle_bumblebee_health, autocvar_g_vehicle_bumblebee_health_regen_pause, autocvar_g_vehicle_bumblebee_health_regen, dt, false);
 
        if(this.vehicle_flags  & VHF_ENERGYREGEN)
-               vehicles_regen(this, this.wait, vehicle_energy, autocvar_g_vehicle_bumblebee_energy, autocvar_g_vehicle_bumblebee_energy_regen_pause, autocvar_g_vehicle_bumblebee_energy_regen, frametime, false);
+               vehicles_regen(this, this.wait, vehicle_energy, autocvar_g_vehicle_bumblebee_energy, autocvar_g_vehicle_bumblebee_energy_regen_pause, autocvar_g_vehicle_bumblebee_energy_regen, dt, false);
 
 }
 
-bool bumblebee_pilot_frame(entity this)
+bool bumblebee_pilot_frame(entity this, float dt)
 {
        entity vehic = this.vehicle;
        return = true;
@@ -435,7 +435,7 @@ bool bumblebee_pilot_frame(entity this)
                return;
        }
 
-       bumblebee_regen(vehic);
+       bumblebee_regen(vehic, dt);
 
        crosshair_trace(this);
 
@@ -486,7 +486,7 @@ bool bumblebee_pilot_frame(entity this)
                else if(this.movement.y > 0)
                        newvel += v_right * autocvar_g_vehicle_bumblebee_speed_strafe;
                ftmp = newvel * v_right;
-               ftmp *= frametime * 0.1;
+               ftmp *= dt * 0.1;
                vehic.angles_z = bound(-15, vehic.angles.z + ftmp, 15);
        }
        else
@@ -501,7 +501,7 @@ bool bumblebee_pilot_frame(entity this)
        else if(PHYS_INPUT_BUTTON_JUMP(this))
                newvel +=  v_up * autocvar_g_vehicle_bumblebee_speed_up;
 
-       vehic.velocity  += newvel * frametime;
+       vehic.velocity  += newvel * dt;
        this.velocity = this.movement  = vehic.velocity;
 
 
@@ -542,7 +542,7 @@ bool bumblebee_pilot_frame(entity this)
                                          autocvar_g_vehicle_bumblebee_raygun_turnlimit_sides * -1,  autocvar_g_vehicle_bumblebee_raygun_turnlimit_sides,  autocvar_g_vehicle_bumblebee_raygun_turnspeed);
 
        if(!forbidWeaponUse(this))
-       if((PHYS_INPUT_BUTTON_ATCK(this) || PHYS_INPUT_BUTTON_ATCK2(this)) && (vehic.vehicle_energy > autocvar_g_vehicle_bumblebee_raygun_dps * sys_frametime || autocvar_g_vehicle_bumblebee_raygun == 0))
+       if((PHYS_INPUT_BUTTON_ATCK(this) || PHYS_INPUT_BUTTON_ATCK2(this)) && (vehic.vehicle_energy > autocvar_g_vehicle_bumblebee_raygun_dps * PHYS_INPUT_FRAMETIME || autocvar_g_vehicle_bumblebee_raygun == 0))
        {
                vehic.gun3.enemy.realowner = this;
                vehic.gun3.enemy.effects &= ~EF_NODRAW;
@@ -556,8 +556,8 @@ bool bumblebee_pilot_frame(entity this)
                {
                        if(autocvar_g_vehicle_bumblebee_raygun)
                        {
-                               Damage(trace_ent, vehic, this, autocvar_g_vehicle_bumblebee_raygun_dps * sys_frametime, DEATH_GENERIC.m_id, trace_endpos, v_forward * autocvar_g_vehicle_bumblebee_raygun_fps * sys_frametime);
-                               vehic.vehicle_energy -= autocvar_g_vehicle_bumblebee_raygun_aps * sys_frametime;
+                               Damage(trace_ent, vehic, this, autocvar_g_vehicle_bumblebee_raygun_dps * PHYS_INPUT_FRAMETIME, DEATH_GENERIC.m_id, trace_endpos, v_forward * autocvar_g_vehicle_bumblebee_raygun_fps * PHYS_INPUT_FRAMETIME);
+                               vehic.vehicle_energy -= autocvar_g_vehicle_bumblebee_raygun_aps * PHYS_INPUT_FRAMETIME;
                        }
                        else
                        {
@@ -568,25 +568,25 @@ bool bumblebee_pilot_frame(entity this)
                                                if(IS_VEHICLE(trace_ent))
                                                {
                                                        if(autocvar_g_vehicle_bumblebee_healgun_sps && trace_ent.vehicle_health <= trace_ent.max_health)
-                                                               trace_ent.vehicle_shield = min(trace_ent.vehicle_shield + autocvar_g_vehicle_bumblebee_healgun_sps * frametime, trace_ent.tur_head.max_health);
+                                                               trace_ent.vehicle_shield = min(trace_ent.vehicle_shield + autocvar_g_vehicle_bumblebee_healgun_sps * dt, trace_ent.tur_head.max_health);
 
                                                        if(autocvar_g_vehicle_bumblebee_healgun_hps)
-                                                               trace_ent.vehicle_health = min(trace_ent.vehicle_health + autocvar_g_vehicle_bumblebee_healgun_hps * frametime, trace_ent.max_health);
+                                                               trace_ent.vehicle_health = min(trace_ent.vehicle_health + autocvar_g_vehicle_bumblebee_healgun_hps * dt, trace_ent.max_health);
                                                }
                                                else if(IS_CLIENT(trace_ent))
                                                {
                                                        if(trace_ent.health <= autocvar_g_vehicle_bumblebee_healgun_hmax && autocvar_g_vehicle_bumblebee_healgun_hps)
-                                                               trace_ent.health = min(trace_ent.health + autocvar_g_vehicle_bumblebee_healgun_hps * frametime, autocvar_g_vehicle_bumblebee_healgun_hmax);
+                                                               trace_ent.health = min(trace_ent.health + autocvar_g_vehicle_bumblebee_healgun_hps * dt, autocvar_g_vehicle_bumblebee_healgun_hmax);
 
                                                        if(trace_ent.armorvalue <= autocvar_g_vehicle_bumblebee_healgun_amax && autocvar_g_vehicle_bumblebee_healgun_aps)
-                                                               trace_ent.armorvalue = min(trace_ent.armorvalue + autocvar_g_vehicle_bumblebee_healgun_aps * frametime, autocvar_g_vehicle_bumblebee_healgun_amax);
+                                                               trace_ent.armorvalue = min(trace_ent.armorvalue + autocvar_g_vehicle_bumblebee_healgun_aps * dt, autocvar_g_vehicle_bumblebee_healgun_amax);
 
-                                                       trace_ent.health = min(trace_ent.health + autocvar_g_vehicle_bumblebee_healgun_hps * frametime, autocvar_g_vehicle_bumblebee_healgun_hmax);
+                                                       trace_ent.health = min(trace_ent.health + autocvar_g_vehicle_bumblebee_healgun_hps * dt, autocvar_g_vehicle_bumblebee_healgun_hmax);
                                                }
                                                else if(IS_TURRET(trace_ent))
                                                {
                                                        if(trace_ent.health  <= trace_ent.max_health && autocvar_g_vehicle_bumblebee_healgun_hps)
-                                                               trace_ent.health = min(trace_ent.health + autocvar_g_vehicle_bumblebee_healgun_hps * frametime, trace_ent.max_health);
+                                                               trace_ent.health = min(trace_ent.health + autocvar_g_vehicle_bumblebee_healgun_hps * dt, trace_ent.max_health);
                                                        //else ..hmmm what? ammo?
 
                                                        trace_ent.SendFlags |= TNSF_STATUS;
@@ -633,7 +633,7 @@ void bumblebee_land(entity this)
        float hgt;
 
        hgt = vehicle_altitude(this, 512);
-       this.velocity = (this.velocity * 0.9) + ('0 0 -1800' * (hgt / 256) * sys_frametime);
+       this.velocity = (this.velocity * 0.9) + ('0 0 -1800' * (hgt / 256) * PHYS_INPUT_FRAMETIME);
        this.angles_x *= 0.95;
        this.angles_z *= 0.95;
 
@@ -701,7 +701,7 @@ void bumblebee_blowup(entity this)
        if(this.owner.deadflag == DEAD_DYING)
                this.owner.deadflag = DEAD_DEAD;
 
-       remove(this);
+       delete(this);
 }
 
 void bumblebee_dead_touch(entity this, entity toucher)
@@ -725,8 +725,8 @@ void bumblebee_diethink(entity this)
 
 spawnfunc(vehicle_bumblebee)
 {
-       if(!autocvar_g_vehicle_bumblebee) { remove(this); return; }
-       if(!vehicle_initialize(this, VEH_BUMBLEBEE, false)) { remove(this); return; }
+       if(!autocvar_g_vehicle_bumblebee) { delete(this); return; }
+       if(!vehicle_initialize(this, VEH_BUMBLEBEE, false)) { delete(this); return; }
 }
 
 METHOD(Bumblebee, vr_impact, void(Bumblebee thisveh, entity instance))
index b043038921460bb2768aca34238932a49352e566..b675185d49454681ed545b493921aceb421735c1 100644 (file)
@@ -1,9 +1,6 @@
-#ifndef BUMBLEBEE_H
-#define BUMBLEBEE_H
+#pragma once
 
 #ifdef CSQC
 
 void CSQC_BUMBLE_GUN_HUD();
 #endif
-
-#endif
index 277326ffd2a18e055ab6c2b3ff8258356c23639a..2bccec21a041af2b455231b88dac6861bbdd95f0 100644 (file)
@@ -170,7 +170,7 @@ void racer_fire_rocket_aim(entity player, string tagname, entity trg)
        racer_fire_rocket(player, v, v_forward, trg);
 }
 
-bool racer_frame(entity this)
+bool racer_frame(entity this, float dt)
 {
        entity vehic = this.vehicle;
        return = true;
@@ -195,22 +195,22 @@ bool racer_frame(entity this)
                return;
        }
 
-       racer_align4point(vehic, PHYS_INPUT_TIMELENGTH);
+       racer_align4point(vehic, dt);
 
        PHYS_INPUT_BUTTON_ZOOM(this) = PHYS_INPUT_BUTTON_CROUCH(this) = false;
 
        vehic.angles_x *= -1;
 
        // Yaw
-       float ftmp = autocvar_g_vehicle_racer_turnspeed * PHYS_INPUT_TIMELENGTH;
+       float ftmp = autocvar_g_vehicle_racer_turnspeed * dt;
        ftmp = bound(-ftmp, shortangle_f(this.v_angle_y - vehic.angles_y, vehic.angles_y), ftmp);
        vehic.angles_y = anglemods(vehic.angles_y + ftmp);
 
        // Roll
-       vehic.angles_z += -ftmp * autocvar_g_vehicle_racer_turnroll * PHYS_INPUT_TIMELENGTH;
+       vehic.angles_z += -ftmp * autocvar_g_vehicle_racer_turnroll * dt;
 
        // Pitch
-       ftmp = autocvar_g_vehicle_racer_pitchspeed  * PHYS_INPUT_TIMELENGTH;
+       ftmp = autocvar_g_vehicle_racer_pitchspeed  * dt;
        ftmp = bound(-ftmp, shortangle_f(this.v_angle_x - vehic.angles_x, vehic.angles_x), ftmp);
        vehic.angles_x = bound(-autocvar_g_vehicle_racer_pitchlimit, anglemods(vehic.angles_x + ftmp), autocvar_g_vehicle_racer_pitchlimit);
 
@@ -256,7 +256,7 @@ bool racer_frame(entity this)
 #endif
 
        // Afterburn
-       if (PHYS_INPUT_BUTTON_JUMP(this) && vehic.vehicle_energy >= (autocvar_g_vehicle_racer_afterburn_cost * PHYS_INPUT_TIMELENGTH))
+       if (PHYS_INPUT_BUTTON_JUMP(this) && vehic.vehicle_energy >= (autocvar_g_vehicle_racer_afterburn_cost * dt))
        {
 #ifdef SVQC
                if(time - vehic.wait > 0.2)
@@ -267,12 +267,12 @@ bool racer_frame(entity this)
 
                if(cont & DPCONTENTS_LIQUIDSMASK)
                {
-                       vehic.vehicle_energy -= autocvar_g_vehicle_racer_waterburn_cost * PHYS_INPUT_TIMELENGTH;
+                       vehic.vehicle_energy -= autocvar_g_vehicle_racer_waterburn_cost * dt;
                        df += (v_forward * autocvar_g_vehicle_racer_waterburn_speed);
                }
                else
                {
-                       vehic.vehicle_energy -= autocvar_g_vehicle_racer_afterburn_cost * PHYS_INPUT_TIMELENGTH;
+                       vehic.vehicle_energy -= autocvar_g_vehicle_racer_afterburn_cost * dt;
                        df += (v_forward * autocvar_g_vehicle_racer_speed_afterburn);
                }
 
@@ -307,7 +307,7 @@ bool racer_frame(entity this)
                dforce = autocvar_g_vehicle_racer_water_downforce;
 
        df -= v_up * (vlen(vehic.velocity) * dforce);
-       this.movement = vehic.velocity += df * PHYS_INPUT_TIMELENGTH;
+       this.movement = vehic.velocity += df * dt;
 
 #ifdef SVQC
 
@@ -335,8 +335,8 @@ bool racer_frame(entity this)
                {
                        crosshair_trace(this);
 
-                       vehicles_locktarget(vehic, (1 / autocvar_g_vehicle_racer_rocket_locking_time) * frametime,
-                                                        (1 / autocvar_g_vehicle_racer_rocket_locking_releasetime) * frametime,
+                       vehicles_locktarget(vehic, (1 / autocvar_g_vehicle_racer_rocket_locking_time) * dt,
+                                                        (1 / autocvar_g_vehicle_racer_rocket_locking_releasetime) * dt,
                                                         autocvar_g_vehicle_racer_rocket_locked_time);
 
                        vehic.vehicle_last_trace = time + autocvar_g_vehicle_racer_thinkrate;
@@ -382,13 +382,13 @@ bool racer_frame(entity this)
        this.vehicle_reload2 = bound(0, 100 * ((time - vehic.lip) / (vehic.delay - vehic.lip)), 100);
 
        if(vehic.vehicle_flags  & VHF_SHIELDREGEN)
-               vehicles_regen(vehic, vehic.dmg_time, vehicle_shield, autocvar_g_vehicle_racer_shield, autocvar_g_vehicle_racer_shield_regen_pause, autocvar_g_vehicle_racer_shield_regen, frametime, true);
+               vehicles_regen(vehic, vehic.dmg_time, vehicle_shield, autocvar_g_vehicle_racer_shield, autocvar_g_vehicle_racer_shield_regen_pause, autocvar_g_vehicle_racer_shield_regen, dt, true);
 
        if(vehic.vehicle_flags  & VHF_HEALTHREGEN)
-               vehicles_regen(vehic, vehic.dmg_time, vehicle_health, autocvar_g_vehicle_racer_health, autocvar_g_vehicle_racer_health_regen_pause, autocvar_g_vehicle_racer_health_regen, frametime, false);
+               vehicles_regen(vehic, vehic.dmg_time, vehicle_health, autocvar_g_vehicle_racer_health, autocvar_g_vehicle_racer_health_regen_pause, autocvar_g_vehicle_racer_health_regen, dt, false);
 
        if(vehic.vehicle_flags  & VHF_ENERGYREGEN)
-               vehicles_regen(vehic, vehic.wait, vehicle_energy, autocvar_g_vehicle_racer_energy, autocvar_g_vehicle_racer_energy_regen_pause, autocvar_g_vehicle_racer_energy_regen, frametime, false);
+               vehicles_regen(vehic, vehic.wait, vehicle_energy, autocvar_g_vehicle_racer_energy, autocvar_g_vehicle_racer_energy_regen_pause, autocvar_g_vehicle_racer_energy_regen, dt, false);
 
        VEHICLE_UPDATE_PLAYER(this, vehic, health, racer);
        VEHICLE_UPDATE_PLAYER(this, vehic, energy, racer);
@@ -521,8 +521,8 @@ void racer_deadtouch(entity this, entity toucher)
 
 spawnfunc(vehicle_racer)
 {
-       if(!autocvar_g_vehicle_racer) { remove(this); return; }
-       if(!vehicle_initialize(this, VEH_RACER, false)) { remove(this); return; }
+       if(!autocvar_g_vehicle_racer) { delete(this); return; }
+       if(!vehicle_initialize(this, VEH_RACER, false)) { delete(this); return; }
 }
 
 #endif // SVQC
@@ -545,7 +545,7 @@ METHOD(Racer, vr_enter, void(Racer thisveh, entity instance))
     if(instance.owner.flagcarried)
        setorigin(instance.owner.flagcarried, '-190 0 96');
 #elif defined(CSQC)
-    instance.move_movetype = MOVETYPE_BOUNCE;
+    set_movetype(instance, MOVETYPE_BOUNCE);
 #endif
 }
 
index 1af09990bc5aca8ec8582ce313785a6a24e7cb99..d20210c6118434d1c83dffc44729c65080bf4a4e 100644 (file)
@@ -16,7 +16,7 @@ METHOD(RacerAttack, wr_think, void(entity thiswep, entity actor, .entity weapone
             veh.vehicle_energy -= autocvar_g_vehicle_racer_cannon_cost;
             veh.wait = time;
         }
-        if (isPlayer) W_SetupShot_Dir(player, v_forward, false, 0, SND_Null, CH_WEAPON_B, 0);
+        if (isPlayer) W_SetupShot_Dir(player, weaponentity, v_forward, false, 0, SND_Null, CH_WEAPON_B, 0);
         vector org = w_shotorg;
         vector dir = w_shotdir;
         entity bolt = vehicles_projectile(veh, EFFECT_RACER_MUZZLEFLASH.eent_eff_name, SND_LASERGUN_FIRE,
@@ -28,7 +28,7 @@ METHOD(RacerAttack, wr_think, void(entity thiswep, entity actor, .entity weapone
     }
     if (fire & 2)
     if (!isPlayer || weapon_prepareattack(thiswep, actor, weaponentity, false, 0.2)) {
-        if (isPlayer) W_SetupShot_Dir(actor, v_forward, false, 0, SND_Null, CH_WEAPON_B, 0);
+        if (isPlayer) W_SetupShot_Dir(actor, weaponentity, v_forward, false, 0, SND_Null, CH_WEAPON_B, 0);
         racer_fire_rocket(player, w_shotorg, w_shotdir, NULL);
         weapon_thinkf(actor, weaponentity, WFRAME_FIRE2, 0, w_ready);
     }
index d938c4ad396cd6f760d78ad22a0a9857a4706b87..510f63ba1fdb2ff9c7020c5b7daac7e19efb2bdc 100644 (file)
@@ -84,7 +84,7 @@ void raptor_land(entity this)
        float hgt;
 
        hgt = vehicle_altitude(this, 512);
-       this.velocity = (this.velocity * 0.9) + ('0 0 -1800' * (hgt / 256) * sys_frametime);
+       this.velocity = (this.velocity * 0.9) + ('0 0 -1800' * (hgt / 256) * PHYS_INPUT_FRAMETIME);
        this.angles_x *= 0.95;
        this.angles_z *= 0.95;
 
@@ -153,7 +153,7 @@ void raptor_exit(entity this, int eject)
        this.owner = NULL;
 }
 
-bool raptor_frame(entity this)
+bool raptor_frame(entity this, float dt)
 {
        entity vehic = this.vehicle;
        return = true;
@@ -273,7 +273,7 @@ bool raptor_frame(entity this)
        else if (PHYS_INPUT_BUTTON_JUMP(this))
                df +=  v_up * autocvar_g_vehicle_raptor_speed_up;
 
-       vehic.velocity  += df * frametime;
+       vehic.velocity  += df * dt;
        this.velocity = this.movement  = vehic.velocity;
        setorigin(this, vehic.origin + '0 0 32');
 
@@ -331,8 +331,8 @@ bool raptor_frame(entity this)
        else if(autocvar_g_vehicle_raptor_cannon_locktarget == 1)
        {
 
-               vehicles_locktarget(vehic, (1 / autocvar_g_vehicle_raptor_cannon_locking_time) * frametime,
-                                                        (1 / autocvar_g_vehicle_raptor_cannon_locking_releasetime) * frametime,
+               vehicles_locktarget(vehic, (1 / autocvar_g_vehicle_raptor_cannon_locking_time) * dt,
+                                                        (1 / autocvar_g_vehicle_raptor_cannon_locking_releasetime) * dt,
                                                         autocvar_g_vehicle_raptor_cannon_locked_time);
 
                if(vehic.lock_target != NULL)
@@ -389,13 +389,13 @@ bool raptor_frame(entity this)
        }
 
        if(vehic.vehicle_flags  & VHF_SHIELDREGEN)
-               vehicles_regen(vehic, vehic.dmg_time, vehicle_shield, autocvar_g_vehicle_raptor_shield, autocvar_g_vehicle_raptor_shield_regen_pause, autocvar_g_vehicle_raptor_shield_regen, frametime, true);
+               vehicles_regen(vehic, vehic.dmg_time, vehicle_shield, autocvar_g_vehicle_raptor_shield, autocvar_g_vehicle_raptor_shield_regen_pause, autocvar_g_vehicle_raptor_shield_regen, dt, true);
 
        if(vehic.vehicle_flags  & VHF_HEALTHREGEN)
-               vehicles_regen(vehic, vehic.dmg_time, vehicle_health, autocvar_g_vehicle_raptor_health, autocvar_g_vehicle_raptor_health_regen_pause, autocvar_g_vehicle_raptor_health_regen, frametime, false);
+               vehicles_regen(vehic, vehic.dmg_time, vehicle_health, autocvar_g_vehicle_raptor_health, autocvar_g_vehicle_raptor_health_regen_pause, autocvar_g_vehicle_raptor_health_regen, dt, false);
 
        if(vehic.vehicle_flags  & VHF_ENERGYREGEN)
-               vehicles_regen(vehic, vehic.cnt, vehicle_energy, autocvar_g_vehicle_raptor_energy, autocvar_g_vehicle_raptor_energy_regen_pause, autocvar_g_vehicle_raptor_energy_regen, frametime, false);
+               vehicles_regen(vehic, vehic.cnt, vehicle_energy, autocvar_g_vehicle_raptor_energy, autocvar_g_vehicle_raptor_energy_regen_pause, autocvar_g_vehicle_raptor_energy_regen, dt, false);
 
        Weapon wep2a = WEP_RAPTOR_BOMB;
        if(!forbidWeaponUse(this))
@@ -430,9 +430,8 @@ bool raptor_frame(entity this)
        if(vehic.bomb1.cnt < time)
        {
                bool incoming = false;
-               FOREACH_ENTITY_ENT(enemy, vehic,
+               IL_EACH(g_projectiles, it.enemy == vehic,
                {
-                       if(it.flags & FL_PROJECTILE)
                        if(MISSILE_IS_TRACKING(it))
                        if(vdist(vehic.origin - it.origin, <, 2 * autocvar_g_vehicle_raptor_flare_range))
                        {
@@ -459,7 +458,7 @@ bool raptor_frame(entity this)
        PHYS_INPUT_BUTTON_ATCK(this) = PHYS_INPUT_BUTTON_ATCK2(this) = PHYS_INPUT_BUTTON_CROUCH(this) = false;
 }
 
-bool raptor_takeoff(entity this)
+bool raptor_takeoff(entity this, float dt)
 {
        entity vehic = this.vehicle;
        return = true;
@@ -477,7 +476,7 @@ bool raptor_takeoff(entity this)
        // Takeoff sequense
        if(vehic.frame < 25)
        {
-               vehic.frame += 25 / (autocvar_g_vehicle_raptor_takeofftime / sys_frametime);
+               vehic.frame += 25 / (autocvar_g_vehicle_raptor_takeofftime / PHYS_INPUT_FRAMETIME);
                vehic.velocity_z = min(vehic.velocity_z * 1.5, 256);
                vehic.bomb1.gun1.avelocity_y = 90 + ((vehic.frame / 25) * 25000);
                vehic.bomb1.gun2.avelocity_y = -vehic.bomb1.gun1.avelocity_y;
@@ -489,13 +488,13 @@ bool raptor_takeoff(entity this)
                this.PlayerPhysplug = raptor_frame;
 
        if(vehic.vehicle_flags  & VHF_SHIELDREGEN)
-               vehicles_regen(vehic, vehic.dmg_time, vehicle_shield, autocvar_g_vehicle_raptor_shield, autocvar_g_vehicle_raptor_shield_regen_pause, autocvar_g_vehicle_raptor_shield_regen, frametime, true);
+               vehicles_regen(vehic, vehic.dmg_time, vehicle_shield, autocvar_g_vehicle_raptor_shield, autocvar_g_vehicle_raptor_shield_regen_pause, autocvar_g_vehicle_raptor_shield_regen, dt, true);
 
        if(vehic.vehicle_flags  & VHF_HEALTHREGEN)
-               vehicles_regen(vehic, vehic.dmg_time, vehicle_health, autocvar_g_vehicle_raptor_health, autocvar_g_vehicle_raptor_health_regen_pause, autocvar_g_vehicle_raptor_health_regen, frametime, false);
+               vehicles_regen(vehic, vehic.dmg_time, vehicle_health, autocvar_g_vehicle_raptor_health, autocvar_g_vehicle_raptor_health_regen_pause, autocvar_g_vehicle_raptor_health_regen, dt, false);
 
        if(vehic.vehicle_flags  & VHF_ENERGYREGEN)
-               vehicles_regen(vehic, vehic.cnt, vehicle_energy, autocvar_g_vehicle_raptor_energy, autocvar_g_vehicle_raptor_energy_regen_pause, autocvar_g_vehicle_raptor_energy_regen, frametime, false);
+               vehicles_regen(vehic, vehic.cnt, vehicle_energy, autocvar_g_vehicle_raptor_energy, autocvar_g_vehicle_raptor_energy_regen_pause, autocvar_g_vehicle_raptor_energy_regen, dt, false);
 
 
        vehic.bomb1.alpha = vehic.bomb2.alpha = (time - vehic.lip) / (vehic.delay - vehic.lip);
@@ -600,8 +599,8 @@ bool raptor_impulse(entity this, int _imp)
 
 spawnfunc(vehicle_raptor)
 {
-       if(!autocvar_g_vehicle_raptor) { remove(this); return; }
-       if(!vehicle_initialize(this, VEH_RAPTOR, false)) { remove(this); return; }
+       if(!autocvar_g_vehicle_raptor) { delete(this); return; }
+       if(!vehicle_initialize(this, VEH_RAPTOR, false)) { delete(this); return; }
 }
 
 METHOD(Raptor, vr_impact, void(Raptor thisveh, entity instance))
index f24939ba9d21a2f697c41b6592e9ca970e598aad..fd9a7de790b8f49287d0092eafe1663ec0130da2 100644 (file)
@@ -1,9 +1,6 @@
-#ifndef RAPTOR_H
-#define RAPTOR_H
+#pragma once
 
 const int RSM_FIRST = 1;
 const int RSM_BOMB = 1;
 const int RSM_FLARE = 2;
 const int RSM_LAST = 2;
-
-#endif
index 86f4b22b8b6735dcc7c69a2f28bc97754008bc31..502ef80e2cd88af31f94979549c4b6820cb11d0b 100644 (file)
@@ -12,7 +12,7 @@ METHOD(RaptorCannon, wr_think, void(entity thiswep, entity actor, .entity weapon
     float t = autocvar_g_vehicle_raptor_cannon_refire * (1 + veh.misc_bulletcounter == 4);
     if (fire & 1)
     if (weapon_prepareattack(thiswep, player, weaponentity, false, t)) {
-        if (isPlayer) W_SetupShot_Dir(player, v_forward, false, 0, SND_Null, CH_WEAPON_B, 0);
+        if (isPlayer) W_SetupShot_Dir(player, weaponentity, v_forward, false, 0, SND_Null, CH_WEAPON_B, 0);
         vector org = w_shotorg;
         vector dir = w_shotdir;
         if (veh) {
@@ -91,7 +91,7 @@ void raptor_bomblet_boom(entity this)
                                     autocvar_g_vehicle_raptor_bomblet_edgedamage,
                                     autocvar_g_vehicle_raptor_bomblet_radius, NULL, NULL,
                                     autocvar_g_vehicle_raptor_bomblet_force, DEATH_VH_RAPT_BOMB.m_id, NULL);
-    remove(this);
+    delete(this);
 }
 
 void raptor_bomblet_touch(entity this, entity toucher)
@@ -140,7 +140,7 @@ void raptor_bomb_burst(entity this)
         CSQCProjectile(bomblet, true, PROJECTILE_RAPTORBOMBLET, true);
     }
 
-    remove(this);
+    delete(this);
 }
 
 void raptor_bomb_touch(entity this, entity toucher)
@@ -188,14 +188,14 @@ void raptor_bombdrop(entity this)
 
 void raptor_flare_touch(entity this, entity toucher)
 {
-    remove(this);
+    delete(this);
 }
 
 void raptor_flare_damage(entity this, entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
 {
     this.health -= damage;
     if(this.health <= 0)
-        remove(this);
+        delete(this);
 }
 
 void raptor_flare_think(entity this)
@@ -210,7 +210,7 @@ void raptor_flare_think(entity this)
     });
 
     if(this.tur_impacttime < time)
-        remove(this);
+        delete(this);
 }
 
 #endif
@@ -230,7 +230,7 @@ void RaptorCBShellfragDraw(entity this)
         this.alpha = bound(0, this.nextthink - time, 1);
 
     if(this.alpha < ALPHA_MIN_VISIBLE)
-        remove(this);
+        delete(this);
 }
 
 void RaptorCBShellfragToss(vector _org, vector _vel, vector _ang)
index 8140de8646d6b85b366c1b277029ada2ff4f7d36..3365266f80fbd33ee9c49683da03e1d590d0a53a 100644 (file)
@@ -68,7 +68,7 @@ float autocvar_g_vehicle_spiderbot_shield_regen_pause = 0.35;
 vector autocvar_g_vehicle_spiderbot_bouncepain = '0 0 0';
 
 .float jump_delay;
-bool spiderbot_frame(entity this)
+bool spiderbot_frame(entity this, float dt)
 {
        entity vehic = this.vehicle;
        return = true;
@@ -116,7 +116,7 @@ bool spiderbot_frame(entity this)
        //UpdateAuxiliaryXhair(this, trace_endpos, ('1 0 0' * this.vehicle_reload2) + ('0 1 0' * (1 - this.vehicle_reload2)), 2);
 
        // Rotate head
-       float ftmp = autocvar_g_vehicle_spiderbot_head_turnspeed * sys_frametime;
+       float ftmp = autocvar_g_vehicle_spiderbot_head_turnspeed * PHYS_INPUT_FRAMETIME;
        ad_y = bound(-ftmp, ad_y, ftmp);
        vehic.tur_head.angles_y = bound(autocvar_g_vehicle_spiderbot_head_turnlimit * -1, vehic.tur_head.angles_y + ad_y, autocvar_g_vehicle_spiderbot_head_turnlimit);
 
@@ -193,9 +193,9 @@ bool spiderbot_frame(entity this)
                        {
                                // Turn Body
                                if(this.movement_x == 0 && this.movement_y != 0)
-                                       ftmp = autocvar_g_vehicle_spiderbot_turnspeed_strafe * sys_frametime;
+                                       ftmp = autocvar_g_vehicle_spiderbot_turnspeed_strafe * PHYS_INPUT_FRAMETIME;
                                else
-                                       ftmp = autocvar_g_vehicle_spiderbot_turnspeed * sys_frametime;
+                                       ftmp = autocvar_g_vehicle_spiderbot_turnspeed * PHYS_INPUT_FRAMETIME;
 
                                ftmp = bound(-ftmp, vehic.tur_head.angles_y, ftmp);
                                vehic.angles_y = anglemods(vehic.angles_y + ftmp);
@@ -221,7 +221,7 @@ bool spiderbot_frame(entity this)
                                        vehic.velocity_z = oldvelz;
                                        float g = ((autocvar_sv_gameplayfix_gravityunaffectedbyticrate) ? 0.5 : 1);
                                        if(vehic.velocity_z <= 20) // not while jumping
-                                               vehic.velocity_z -= g * sys_frametime * autocvar_sv_gravity;
+                                               vehic.velocity_z -= g * PHYS_INPUT_FRAMETIME * autocvar_sv_gravity;
                                        if(IS_ONGROUND(vehic))
                                        if(vehic.sound_nexttime < time || vehic.delay != 1)
                                        {
@@ -251,7 +251,7 @@ bool spiderbot_frame(entity this)
                                        vehic.velocity_z = oldvelz;
                                        float g = ((autocvar_sv_gameplayfix_gravityunaffectedbyticrate) ? 0.5 : 1);
                                        if(vehic.velocity_z <= 20) // not while jumping
-                                               vehic.velocity_z -= g * sys_frametime * autocvar_sv_gravity;
+                                               vehic.velocity_z -= g * PHYS_INPUT_FRAMETIME * autocvar_sv_gravity;
                                        if(IS_ONGROUND(vehic))
                                        if(vehic.sound_nexttime < time || vehic.delay != 2)
                                        {
@@ -306,16 +306,16 @@ bool spiderbot_frame(entity this)
        else
                vehicles_regen(vehic, vehic.cnt, vehicle_ammo1, autocvar_g_vehicle_spiderbot_minigun_ammo_max,
                                                                                   autocvar_g_vehicle_spiderbot_minigun_ammo_regen_pause,
-                                                                                  autocvar_g_vehicle_spiderbot_minigun_ammo_regen, frametime, false);
+                                                                                  autocvar_g_vehicle_spiderbot_minigun_ammo_regen, dt, false);
 
 
        spiderbot_rocket_do(vehic);
 
        if(vehic.vehicle_flags  & VHF_SHIELDREGEN)
-               vehicles_regen(vehic, vehic.dmg_time, vehicle_shield, autocvar_g_vehicle_spiderbot_shield, autocvar_g_vehicle_spiderbot_shield_regen_pause, autocvar_g_vehicle_spiderbot_shield_regen, frametime, true);
+               vehicles_regen(vehic, vehic.dmg_time, vehicle_shield, autocvar_g_vehicle_spiderbot_shield, autocvar_g_vehicle_spiderbot_shield_regen_pause, autocvar_g_vehicle_spiderbot_shield_regen, dt, true);
 
        if(vehic.vehicle_flags  & VHF_HEALTHREGEN)
-               vehicles_regen(vehic, vehic.dmg_time, vehicle_health, autocvar_g_vehicle_spiderbot_health, autocvar_g_vehicle_spiderbot_health_regen_pause, autocvar_g_vehicle_spiderbot_health_regen, frametime, false);
+               vehicles_regen(vehic, vehic.dmg_time, vehicle_health, autocvar_g_vehicle_spiderbot_health, autocvar_g_vehicle_spiderbot_health_regen_pause, autocvar_g_vehicle_spiderbot_health_regen, dt, false);
 
        PHYS_INPUT_BUTTON_ATCK(this) = PHYS_INPUT_BUTTON_ATCK2(this) = false;
        //this.vehicle_ammo2 = vehic.tur_head.frame;
@@ -400,7 +400,7 @@ void spiderbot_headfade(entity this)
                        sound (this, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM);
                        Send_Effect(EFFECT_EXPLOSION_BIG, this.origin + '0 0 100', '0 0 0', 1);
                }
-               remove(this);
+               delete(this);
        }
 }
 
@@ -531,8 +531,8 @@ bool spiderbot_impulse(entity this, int _imp)
 
 spawnfunc(vehicle_spiderbot)
 {
-       if(!autocvar_g_vehicle_spiderbot) { remove(this); return; }
-       if(!vehicle_initialize(this, VEH_SPIDERBOT, false)) { remove(this); return; }
+       if(!autocvar_g_vehicle_spiderbot) { delete(this); return; }
+       if(!vehicle_initialize(this, VEH_SPIDERBOT, false)) { delete(this); return; }
 }
 
 METHOD(Spiderbot, vr_impact, void(Spiderbot thisveh, entity instance))
index 23b30792229f7e1e02f2720461e6fabb2720e644..4b6a6997a4c86a800b5c9a3692d7193a8375ec7e 100644 (file)
@@ -136,9 +136,9 @@ void viewloc_SetViewLocation()
                }
 
 #if 0
-               LOG_TRACE(vtos(camera_position), "\n");
-               LOG_TRACE(vtos(old_camera_angle), "\n");
-               LOG_TRACE(vtos(camera_angle), "\n");
+               LOG_TRACE(vtos(camera_position));
+               LOG_TRACE(vtos(old_camera_angle));
+               LOG_TRACE(vtos(camera_angle));
 #endif
 
                freeze_org = getpropertyvec(VF_ORIGIN);
index 4c4d05f92653d6d76deb44fde08bc2cb48721f44..7725d2d8fd040ab506048fb91ce787e0a0cbc676 100644 (file)
@@ -1,5 +1,4 @@
-#ifndef VIEWLOC_H
-#define VIEWLOC_H
+#pragma once
 
 .entity viewloc;
 
@@ -11,5 +10,3 @@ void viewloc_SetViewLocation();
 void viewloc_SetTags(entity this);
 
 #endif
-
-#endif
index 897e2caef2f5975e3627458dd0d6894d7da9a3d8..2b75ec0313f9aa015b916b0d7479c44b12a11be8 100644 (file)
@@ -392,7 +392,7 @@ void CL_WeaponEntity_SetModel(entity this, string name, bool _anim)
        if (name == "")
        {
                this.model = "";
-               if (this.weaponchild) remove(this.weaponchild);
+               if (this.weaponchild) delete(this.weaponchild);
                this.weaponchild = NULL;
                this.movedir = '0 0 0';
                this.spawnorigin = '0 0 0';
@@ -436,7 +436,7 @@ void CL_WeaponEntity_SetModel(entity this, string name, bool _anim)
                }
                else
                {
-                       if (this.weaponchild) remove(this.weaponchild);
+                       if (this.weaponchild) delete(this.weaponchild);
                        this.weaponchild = NULL;
                }
 
@@ -462,7 +462,7 @@ void CL_WeaponEntity_SetModel(entity this, string name, bool _anim)
                        }
                        else
                        {
-                               LOG_WARNINGF("weapon model %s does not support the 'shot' tag, will display shots TOTALLY wrong\n",
+                               LOG_WARNF("weapon model %s does not support the 'shot' tag, will display shots TOTALLY wrong",
                                        this.model);
                                this.movedir = '0 0 0';
                        }
@@ -481,7 +481,7 @@ void CL_WeaponEntity_SetModel(entity this, string name, bool _anim)
                        }
                        else
                        {
-                               LOG_WARNINGF("weapon model %s does not support the 'shell' tag, will display casings wrong\n",
+                               LOG_WARNF("weapon model %s does not support the 'shell' tag, will display casings wrong",
                                        this.model);
                                this.spawnorigin = this.movedir;
                        }
@@ -503,7 +503,7 @@ void CL_WeaponEntity_SetModel(entity this, string name, bool _anim)
                        }
                        else
                        {
-                               LOG_WARNINGF(
+                               LOG_WARNF(
                                        "weapon model %s does not support the 'handle' tag "
                                        "and neither does the v_ model support the 'shot' tag, "
                                        "will display muzzle flashes TOTALLY wrong\n",
index fa9d64ab8d238666270e193eb967bd4230c19e0a..a3f7eb4d0fa0bb26312e8bc708b2cdf3b9ea90ca 100644 (file)
@@ -1,5 +1,4 @@
-#ifndef WEAPONS_ALL_H
-#define WEAPONS_ALL_H
+#pragma once
 
 #include <common/command/all.qh>
 #include <common/stats.qh>
@@ -26,15 +25,15 @@ WepSet ReadWepSet();
 
 #include <common/util.qh>
 
-#ifdef SVQC
-#include <server/bot/aim.qh>
-#endif
-
 REGISTRY(Weapons, 72) // Increase as needed. Can be up to 72.
 #define Weapons_from(i) _Weapons_from(i, WEP_Null)
 REGISTER_REGISTRY(Weapons)
 STATIC_INIT(WeaponPickup) { FOREACH(Weapons, true, it.m_pickup = NEW(WeaponPickup, it)); }
 
+#ifdef SVQC
+#include <server/bot/api.qh>
+#endif
+
 .WepSet m_wepset;
 #define WEPSET(id) (WEP_##id.m_wepset)
 #define WepSet_FromWeapon(it) ((it).m_wepset)
@@ -312,7 +311,7 @@ STATIC_INIT(register_weapons_done)
         else
                inaccessible = strcat(inaccessible, "\n", it.netname);
     });
-    if (inaccessible) LOG_TRACEF("Impulse limit exceeded, weapon(s) will not be directly accessible: %s\n", inaccessible);
+    if (inaccessible) LOG_TRACEF("Impulse limit exceeded, weapon(s) will not be directly accessible: %s", inaccessible);
     #ifdef CSQC
     FOREACH(Weapons, true, it.wr_init(it));
     #endif
@@ -360,5 +359,3 @@ ENUMCLASS_END(WFRAME)
 vector shotorg_adjust_values(vector vecs, bool y_is_right, bool visual, int algn);
 void CL_WeaponEntity_SetModel(entity this, string name, bool _anim);
 #endif
-
-#endif
index e8307f39d20068151236b4e26d9155c820d61d2f..73d9b938efac9bdcc4917352b3833665a1dae105 100644 (file)
@@ -256,7 +256,7 @@ vector W_CalculateSpread(vector forward, float spread, float spreadfactor, float
                default:
                        error("g_projectiles_spread_style must be 0 (sphere), 1 (flattened sphere), 2 (circle), 3 (gauss 3D), 4 (gauss plane), 5 (linear falloff), 6 (quadratic falloff), 7 (stronger falloff)!");
        }
-               
+
        return '0 0 0';
        /*
         * how to derive falloff functions:
index 4feed9fc549e16a48d44c204435f4a83e21672d7..05eb9d9baf299ff4455f06eabed1adea87294587 100644 (file)
@@ -1,6 +1,5 @@
-#ifndef CALCULATIONS_H
-#define CALCULATIONS_H
+#pragma once
+
 vector damage_explosion_calcpush(vector explosion_f, vector target_v, float speedfactor);
 vector W_CalculateSpread(vector forward, float spread, float spreadfactor, float spreadstyle);
 int W_GetGunAlignment(entity player);
-#endif
index d88e18194bf7c37af8991483eb4448f7448e8a50..753147307b3a253e9fb86b5b056bcbdab222c096 100644 (file)
@@ -1,5 +1,4 @@
-#ifndef WEAPONS_CONFIG_H
-#define WEAPONS_CONFIG_H
+#pragma once
 
 #ifdef SVQC
 // ==========================
@@ -37,4 +36,3 @@ string wep_config_queue[MAX_WEP_CONFIG];
                cvar(sprintf("g_balance_%s_%s", #wepname, #name)))) }
 
 #endif
-#endif
index 8b844f13e08e39d8b0585ac94122733b3597e6ee..a08be2e61d5391c406668e6f5039146ba4748518 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef WEAPON_H
-#define WEAPON_H
+#pragma once
+
 #include <common/items/item/pickup.qh>
 #include <common/stats.qh>
 
@@ -54,7 +54,7 @@ const int WS_READY  = 4;
 
 /** fields which are explicitly/manually set are marked with "M", fields set automatically are marked with "A" */
 CLASS(Weapon, Object)
-       ATTRIB(Weapon, m_id, int, 0)
+       ATTRIB(Weapon, m_id, int, 0);
     /** A: WEPSET_id : WEPSET_... */
     ATTRIB(Weapon, weapons, WepSet, '0 0 0');
     /** M: ammotype  : main ammo field */
@@ -70,7 +70,7 @@ CLASS(Weapon, Object)
     /** M: modelname : name of model (without g_ v_ or h_ prefixes) */
     ATTRIB(Weapon, mdl, string, "");
     /** M: model MDL_id_ITEM */
-    ATTRIB(Weapon, m_model, entity, NULL);
+    ATTRIB(Weapon, m_model, entity);
     /** M: crosshair : per-weapon crosshair: "CrosshairImage Size" */
     ATTRIB(Weapon, w_crosshair, string, "gfx/crosshair1");
     /** A: crosshair : per-weapon crosshair size (argument two of "crosshair" field) */
@@ -82,7 +82,7 @@ CLASS(Weapon, Object)
     /** M: wepname   : human readable name */
     ATTRIB(Weapon, m_name, string, "AOL CD Thrower");
 
-    ATTRIB(Weapon, m_pickup, entity, NULL);
+    ATTRIB(Weapon, m_pickup, entity);
 
     /** (SERVER) setup weapon data */
     METHOD(Weapon, wr_setup, void(Weapon this, entity actor)) {}
@@ -107,9 +107,9 @@ CLASS(Weapon, Object)
     /** (CLIENT) impact effect for weapon explosion */
     METHOD(Weapon, wr_impacteffect, void(Weapon this, entity actor)) {}
     /** (SERVER) called whenever a player dies */
-    METHOD(Weapon, wr_playerdeath, void(Weapon this, entity actor)) {}
+    METHOD(Weapon, wr_playerdeath, void(Weapon this, entity actor, .entity weaponentity)) {}
     /** (SERVER) logic to run when weapon is lost */
-    METHOD(Weapon, wr_gonethink, void(Weapon this, entity actor)) {}
+    METHOD(Weapon, wr_gonethink, void(Weapon this, entity actor, .entity weaponentity)) {}
     /** (ALL)    dump weapon cvars to config in data directory (see: sv_cmd dumpweapons) */
     METHOD(Weapon, wr_config, void(Weapon this)) {}
     /** (CLIENT) weapon specific zoom reticle */
@@ -132,15 +132,15 @@ ENDCLASS(Weapon)
 
 #include <common/items/all.qh>
 CLASS(WeaponPickup, Pickup)
-    ATTRIB(WeaponPickup, m_weapon, Weapon, NULL)
-    ATTRIB(WeaponPickup, m_name, string, string_null)
+    ATTRIB(WeaponPickup, m_weapon, Weapon);
+    ATTRIB(WeaponPickup, m_name, string);
 #ifndef MENUQC
-    ATTRIB(WeaponPickup, m_sound, Sound, SND_WEAPONPICKUP)
+    ATTRIB(WeaponPickup, m_sound, Sound, SND_WEAPONPICKUP);
 #endif
 #ifdef SVQC
-    ATTRIB(WeaponPickup, m_itemflags, int, FL_WEAPON)
+    ATTRIB(WeaponPickup, m_itemflags, int, FL_WEAPON);
     float weapon_pickupevalfunc(entity player, entity item);
-    ATTRIB(WeaponPickup, m_pickupevalfunc, float(entity player, entity item), weapon_pickupevalfunc)
+    ATTRIB(WeaponPickup, m_pickupevalfunc, float(entity player, entity item), weapon_pickupevalfunc);
 #endif
     CONSTRUCTOR(WeaponPickup, Weapon w) {
         CONSTRUCT(WeaponPickup);
@@ -158,7 +158,7 @@ CLASS(WeaponPickup, Pickup)
     {
         bool b = Item_GiveTo(item, player);
         if (b) {
-            LOG_TRACEF("entity %i picked up %s\n", player, this.m_name);
+            LOG_TRACEF("entity %i picked up %s", player, this.m_name);
         }
         return b;
     }
@@ -216,5 +216,3 @@ int GetAmmoStat(.int ammotype);
 
 string W_Sound(string w_snd);
 string W_Model(string w_mdl);
-
-#endif
index 3e3af5e0f1e0f18f89d1b2a25ab044693b07c7d9..c0d85831ae730be7dc9c9981d9f8b86150286bc5 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef IMPLEMENTATION
 CLASS(Arc, Weapon)
-/* ammotype  */ ATTRIB(Arc, ammo_field, .int, ammo_cells)
-/* impulse   */ ATTRIB(Arc, impulse, int, 3)
+/* ammotype  */ ATTRIB(Arc, ammo_field, .int, ammo_cells);
+/* impulse   */ ATTRIB(Arc, impulse, int, 3);
 /* flags     */ ATTRIB(Arc, spawnflags, int, WEP_FLAG_NORMAL);
 /* rating    */ ATTRIB(Arc, bot_pickupbasevalue, float, BOT_PICKUP_RATING_HIGH);
 /* color     */ ATTRIB(Arc, wpcolor, vector, '1 1 1');
@@ -101,7 +101,7 @@ const int ARC_SF_LOCALMASK =   ARC_SF_START | ARC_SF_WANTDIR | ARC_SF_BEAMDIR;
 #endif
 #ifdef SVQC
 .entity arc_beam;
-.bool arc_BUTTON_ATCK_prev; // for better animation control
+.bool arc_BUTTON_ATCK_prev[MAX_WEAPONSLOTS]; // for better animation control
 .float beam_prev;
 .float beam_initialized;
 .float beam_bursting;
@@ -199,14 +199,17 @@ bool W_Arc_Beam_Send(entity this, entity to, int sf)
 
 void Reset_ArcBeam(entity player, vector forward)
 {
-       if (!player.arc_beam) {
-               return;
+       for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+       {
+               .entity weaponentity = weaponentities[slot];
+               if(!player.(weaponentity).arc_beam)
+                       continue;
+               player.(weaponentity).arc_beam.beam_dir = forward;
+               player.(weaponentity).arc_beam.beam_teleporttime = time;
        }
-       player.arc_beam.beam_dir = forward;
-       player.arc_beam.beam_teleporttime = time;
 }
 
-float Arc_GetHeat_Percent(entity player)
+float Arc_GetHeat_Percent(entity player, .entity weaponentity)
 {
        if ( WEP_CVAR(arc, overheat_max) <= 0 ||  WEP_CVAR(arc, overheat_max) <= 0 )
        {
@@ -214,8 +217,8 @@ float Arc_GetHeat_Percent(entity player)
                return 0;
        }
 
-       if ( player.arc_beam )
-               return player.arc_beam.beam_heat/WEP_CVAR(arc, overheat_max);
+       if ( player.(weaponentity).arc_beam )
+               return player.(weaponentity).arc_beam.beam_heat/WEP_CVAR(arc, overheat_max);
 
        if ( player.arc_overheat > time )
        {
@@ -225,9 +228,9 @@ float Arc_GetHeat_Percent(entity player)
 
        return 0;
 }
-void Arc_Player_SetHeat(entity player)
+void Arc_Player_SetHeat(entity player, .entity weaponentity)
 {
-       player.arc_heat_percent = Arc_GetHeat_Percent(player);
+       player.arc_heat_percent = Arc_GetHeat_Percent(player, weaponentity);
        //dprint("Heat: ",ftos(player.arc_heat_percent*100),"%\n");
 }
 
@@ -236,7 +239,7 @@ void W_Arc_Bolt_Explode(entity this, entity directhitentity)
        this.event_damage = func_null;
        RadiusDamage(this, this.realowner, WEP_CVAR(arc, bolt_damage), WEP_CVAR(arc, bolt_edgedamage), WEP_CVAR(arc, bolt_radius), NULL, NULL, WEP_CVAR(arc, bolt_force), this.projectiledeathtype, directhitentity);
 
-       remove(this);
+       delete(this);
 }
 
 void W_Arc_Bolt_Explode_use(entity this, entity actor, entity trigger)
@@ -265,13 +268,13 @@ void W_Arc_Bolt_Touch(entity this, entity toucher)
        this.use(this, NULL, toucher);
 }
 
-void W_Arc_Attack_Bolt(Weapon thiswep, entity actor)
+void W_Arc_Attack_Bolt(Weapon thiswep, entity actor, .entity weaponentity)
 {
        entity missile;
 
        W_DecreaseAmmo(thiswep, actor, WEP_CVAR(arc, bolt_ammo));
 
-       W_SetupShot(actor, false, 2, SND_LASERGUN_FIRE, CH_WEAPON_A, WEP_CVAR(arc, bolt_damage));
+       W_SetupShot(actor, weaponentity, false, 2, SND_LASERGUN_FIRE, CH_WEAPON_A, WEP_CVAR(arc, bolt_damage));
 
        Send_Effect(EFFECT_ARC_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
 
@@ -309,13 +312,13 @@ void W_Arc_Attack_Bolt(Weapon thiswep, entity actor)
 
 void W_Arc_Beam_Think(entity this)
 {
-       if(this != this.owner.arc_beam)
+       .entity weaponentity = this.weaponentity_fld;
+       if(this != this.owner.(weaponentity).arc_beam)
        {
-               remove(this);
+               delete(this);
                return;
        }
 
-
        float burst = 0;
        if( (PHYS_INPUT_BUTTON_ATCK2(this.owner) && !WEP_CVAR(arc, bolt)) || this.beam_bursting)
        {
@@ -369,7 +372,7 @@ void W_Arc_Beam_Think(entity this)
                        }
                }
 
-               if(this == this.owner.arc_beam) { this.owner.arc_beam = NULL; }
+               if(this == this.owner.(weaponentity).arc_beam) { this.owner.(weaponentity).arc_beam = NULL; }
                entity own = this.owner;
                Weapon w = WEP_ARC;
                if(!w.wr_checkammo1(w, own) && !w.wr_checkammo2(w, own))
@@ -378,7 +381,7 @@ void W_Arc_Beam_Think(entity this)
                        // note: this doesn't force the switch
                        W_SwitchToOtherWeapon(own);
                }
-               remove(this);
+               delete(this);
                return;
        }
 
@@ -405,6 +408,7 @@ void W_Arc_Beam_Think(entity this)
 
        W_SetupShot_Range(
                this.owner,
+               weaponentity, // TODO
                true,
                0,
                SND_Null,
@@ -672,14 +676,15 @@ void W_Arc_Beam_Think(entity this)
        this.nextthink = time;
 }
 
-void W_Arc_Beam(float burst, entity actor)
+void W_Arc_Beam(float burst, entity actor, .entity weaponentity)
 {
 
        // only play fire sound if 1 sec has passed since player let go the fire button
        if(time - actor.beam_prev > 1)
                sound(actor, CH_WEAPON_A, SND_ARC_FIRE, VOL_BASE, ATTN_NORM);
 
-       entity beam = actor.arc_beam = new(W_Arc_Beam);
+       entity beam = actor.(weaponentity).arc_beam = new(W_Arc_Beam);
+       beam.weaponentity_fld = weaponentity;
        beam.solid = SOLID_NOT;
        setthink(beam, W_Arc_Beam_Think);
        beam.owner = actor;
@@ -691,10 +696,10 @@ void W_Arc_Beam(float burst, entity actor)
 
        getthink(beam)(beam);
 }
-void Arc_Smoke(entity actor)
+void Arc_Smoke(entity actor, .entity weaponentity)
 {
        makevectors(actor.v_angle);
-       W_SetupShot_Range(actor,true,0,SND_Null,0,0,0);
+       W_SetupShot_Range(actor,weaponentity,true,0,SND_Null,0,0,0);
 
        vector smoke_origin = w_shotorg + actor.velocity*frametime;
        if ( actor.arc_overheat > time )
@@ -711,10 +716,10 @@ void Arc_Smoke(entity actor)
                        }
                }
        }
-       else if ( actor.arc_beam && WEP_CVAR(arc, overheat_max) > 0 &&
-                       actor.arc_beam.beam_heat > WEP_CVAR(arc, overheat_min) )
+       else if ( actor.(weaponentity).arc_beam && WEP_CVAR(arc, overheat_max) > 0 &&
+                       actor.(weaponentity).arc_beam.beam_heat > WEP_CVAR(arc, overheat_min) )
        {
-               if ( random() < (actor.arc_beam.beam_heat-WEP_CVAR(arc, overheat_min)) /
+               if ( random() < (actor.(weaponentity).arc_beam.beam_heat-WEP_CVAR(arc, overheat_min)) /
                                ( WEP_CVAR(arc, overheat_max)-WEP_CVAR(arc, overheat_min) ) )
                        Send_Effect(EFFECT_ARC_SMOKE, smoke_origin, '0 0 0', 1 );
        }
@@ -752,16 +757,17 @@ METHOD(Arc, wr_aim, void(entity thiswep, entity actor))
 }
 METHOD(Arc, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
 {
-    Arc_Player_SetHeat(actor);
-    Arc_Smoke(actor);
+    Arc_Player_SetHeat(actor, weaponentity);
+    Arc_Smoke(actor, weaponentity);
 
     bool beam_fire2 = ((fire & 2) && !WEP_CVAR(arc, bolt));
+    int slot = weaponslot(weaponentity);
 
     if (time >= actor.arc_overheat)
-    if ((fire & 1) || beam_fire2 || actor.arc_beam.beam_bursting)
+    if ((fire & 1) || beam_fire2 || actor.(weaponentity).arc_beam.beam_bursting)
     {
 
-        if(actor.arc_BUTTON_ATCK_prev)
+        if(actor.arc_BUTTON_ATCK_prev[slot])
         {
             #if 0
             if(actor.animstate_startframe == actor.anim_shoot.x && actor.animstate_numframes == actor.anim_shoot.y)
@@ -771,16 +777,16 @@ METHOD(Arc, wr_think, void(entity thiswep, entity actor, .entity weaponentity, i
                 weapon_thinkf(actor, weaponentity, WFRAME_DONTCHANGE, WEP_CVAR(arc, beam_animtime), w_ready);
         }
 
-        if((!actor.arc_beam) || wasfreed(actor.arc_beam))
+        if((!actor.(weaponentity).arc_beam) || wasfreed(actor.(weaponentity).arc_beam))
         {
             if(weapon_prepareattack(thiswep, actor, weaponentity, boolean(beam_fire2), 0))
             {
-                W_Arc_Beam(boolean(beam_fire2), actor);
+                W_Arc_Beam(boolean(beam_fire2), actor, weaponentity);
 
-                if(!actor.arc_BUTTON_ATCK_prev)
+                if(!actor.arc_BUTTON_ATCK_prev[slot])
                 {
                     weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR(arc, beam_animtime), w_ready);
-                    actor.arc_BUTTON_ATCK_prev = true;
+                    actor.arc_BUTTON_ATCK_prev[slot] = true;
                 }
             }
         }
@@ -791,19 +797,18 @@ METHOD(Arc, wr_think, void(entity thiswep, entity actor, .entity weaponentity, i
     {
         if(weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR(arc, bolt_refire)))
         {
-            W_Arc_Attack_Bolt(thiswep, actor);
+            W_Arc_Attack_Bolt(thiswep, actor, weaponentity);
             weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR(arc, bolt_refire), w_ready);
         }
     }
 
-    if(actor.arc_BUTTON_ATCK_prev)
+    if(actor.arc_BUTTON_ATCK_prev[slot])
     {
         sound(actor, CH_WEAPON_A, SND_ARC_STOP, VOL_BASE, ATTN_NORM);
         weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR(arc, beam_animtime), w_ready);
-        int slot = weaponslot(weaponentity);
         ATTACK_FINISHED(actor, slot) = time + WEP_CVAR(arc, beam_refire) * W_WeaponRateFactor(actor);
     }
-    actor.arc_BUTTON_ATCK_prev = false;
+    actor.arc_BUTTON_ATCK_prev[slot] = false;
 
     #if 0
     if(fire & 2)
@@ -855,7 +860,8 @@ METHOD(Arc, wr_drop, void(entity thiswep, entity actor))
     weapon_dropevent_item.arc_cooldown = actor.arc_cooldown;
     actor.arc_overheat = 0;
     actor.arc_cooldown = 0;
-    actor.arc_BUTTON_ATCK_prev = false;
+    for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+       actor.arc_BUTTON_ATCK_prev[slot] = false;
 }
 METHOD(Arc, wr_pickup, void(entity thiswep, entity actor))
 {
@@ -870,13 +876,15 @@ METHOD(Arc, wr_resetplayer, void(entity thiswep, entity actor))
 {
     actor.arc_overheat = 0;
     actor.arc_cooldown = 0;
-    actor.arc_BUTTON_ATCK_prev = false;
+    for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+       actor.arc_BUTTON_ATCK_prev[slot] = false;
 }
-METHOD(Arc, wr_playerdeath, void(entity thiswep, entity actor))
+METHOD(Arc, wr_playerdeath, void(entity thiswep, entity actor, .entity weaponentity))
 {
     actor.arc_overheat = 0;
     actor.arc_cooldown = 0;
-    actor.arc_BUTTON_ATCK_prev = false;
+    int slot = weaponslot(weaponentity);
+    actor.arc_BUTTON_ATCK_prev[slot] = false;
 }
 #endif
 #ifdef CSQC
@@ -1279,7 +1287,7 @@ void Draw_ArcBeam(entity this)
 
 void Remove_ArcBeam(entity this)
 {
-       remove(this.beam_muzzleentity);
+       delete(this.beam_muzzleentity);
        sound(this, CH_SHOTS_SINGLE, SND_Null, VOL_BASE, ATTEN_NORM);
 }
 
index 3a9bf365da35186132ee44561cdf13e6e39b2322..791b574817cfc1d6c8daa56c17889ac09057f33f 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef IMPLEMENTATION
 CLASS(Blaster, Weapon)
-/* ammotype  */ //ATTRIB(Blaster, ammo_field, .int, ammo_none)
-/* impulse   */ ATTRIB(Blaster, impulse, int, 1)
+/* ammotype  */ //ATTRIB(Blaster, ammo_field, .int, ammo_none);
+/* impulse   */ ATTRIB(Blaster, impulse, int, 1);
 /* flags     */ ATTRIB(Blaster, spawnflags, int, WEP_FLAG_NORMAL | WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH);
 /* rating    */ ATTRIB(Blaster, bot_pickupbasevalue, float, 0);
 /* color     */ ATTRIB(Blaster, wpcolor, vector, '1 0.5 0.5');
@@ -75,7 +75,7 @@ void W_Blaster_Touch(entity this, entity toucher)
                toucher
        );
 
-       remove(this);
+       delete(this);
 }
 
 void W_Blaster_Think(entity this)
@@ -88,6 +88,7 @@ void W_Blaster_Think(entity this)
 
 void W_Blaster_Attack(
        entity actor,
+       .entity weaponentity,
        float atk_deathtype,
        float atk_shotangle,
        float atk_damage,
@@ -101,7 +102,7 @@ void W_Blaster_Attack(
 {
        vector s_forward = v_forward * cos(atk_shotangle * DEG2RAD) + v_up * sin(atk_shotangle * DEG2RAD);
 
-       W_SetupShot_Dir(actor, s_forward, false, 3, SND_LASERGUN_FIRE, CH_WEAPON_B, atk_damage);
+       W_SetupShot_Dir(actor, weaponentity, s_forward, false, 3, SND_LASERGUN_FIRE, CH_WEAPON_B, atk_damage);
        Send_Effect(EFFECT_BLASTER_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
 
        entity missile = new(blasterbolt);
@@ -137,6 +138,7 @@ void W_Blaster_Attack(
 
        settouch(missile, W_Blaster_Touch);
        missile.flags = FL_PROJECTILE;
+       IL_PUSH(g_projectiles, missile);
        missile.missile_flags = MIF_SPLASH;
        missile.projectiledeathtype = atk_deathtype;
        setthink(missile, W_Blaster_Think);
@@ -171,6 +173,7 @@ METHOD(Blaster, wr_think, void(Blaster thiswep, entity actor, .entity weaponenti
         {
             W_Blaster_Attack(
                 actor,
+                weaponentity,
                 WEP_BLASTER.m_id,
                 WEP_CVAR_PRI(blaster, shotangle),
                 WEP_CVAR_PRI(blaster, damage),
@@ -202,6 +205,7 @@ METHOD(Blaster, wr_think, void(Blaster thiswep, entity actor, .entity weaponenti
                 {
                     W_Blaster_Attack(
                         actor,
+                        weaponentity,
                         WEP_BLASTER.m_id | HITTYPE_SECONDARY,
                         WEP_CVAR_SEC(blaster, shotangle),
                         WEP_CVAR_SEC(blaster, damage),
index 47fa8efcadaec3d884717b8f0bf710436656a5b8..8865dbd02f1c253f87c902dfec48922aa4611370 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef IMPLEMENTATION
 CLASS(Crylink, Weapon)
-/* ammotype  */ ATTRIB(Crylink, ammo_field, .int, ammo_cells)
-/* impulse   */ ATTRIB(Crylink, impulse, int, 6)
+/* ammotype  */ ATTRIB(Crylink, ammo_field, .int, ammo_cells);
+/* impulse   */ ATTRIB(Crylink, impulse, int, 6);
 /* flags     */ ATTRIB(Crylink, spawnflags, int, WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_TYPE_SPLASH);
 /* rating    */ ATTRIB(Crylink, bot_pickupbasevalue, float, BOT_PICKUP_RATING_MID);
 /* color     */ ATTRIB(Crylink, wpcolor, vector, '1 0.5 1');
@@ -114,7 +114,7 @@ void W_Crylink_Dequeue(entity e)
 void W_Crylink_Reset(entity this)
 {
        W_Crylink_Dequeue(this);
-       remove(this);
+       delete(this);
 }
 
 // force projectile to explode
@@ -132,13 +132,13 @@ void W_Crylink_LinkExplode(entity e, entity e2, entity directhitentity)
 
        float isprimary = !(e.projectiledeathtype & HITTYPE_SECONDARY);
 
-       RadiusDamage(e, e.realowner, WEP_CVAR_BOTH(crylink, isprimary, damage) * a, WEP_CVAR_BOTH(crylink, isprimary, edgedamage) * a, WEP_CVAR_BOTH(crylink, isprimary, radius), 
+       RadiusDamage(e, e.realowner, WEP_CVAR_BOTH(crylink, isprimary, damage) * a, WEP_CVAR_BOTH(crylink, isprimary, edgedamage) * a, WEP_CVAR_BOTH(crylink, isprimary, radius),
                                NULL, NULL, WEP_CVAR_BOTH(crylink, isprimary, force) * a, e.projectiledeathtype, directhitentity);
 
        W_Crylink_LinkExplode(e.queuenext, e2, directhitentity);
 
        e.classname = "spike_oktoremove";
-       remove(e);
+       delete(e);
 }
 
 // adjust towards center
@@ -268,7 +268,7 @@ void W_Crylink_LinkJoinEffect_Think(entity this)
                        }
                }
        }
-       remove(this);
+       delete(this);
 }
 
 float W_Crylink_Touch_WouldHitFriendly(entity projectile, float rad)
@@ -320,14 +320,14 @@ void W_Crylink_Touch(entity this, entity toucher)
                        this.realowner.crylink_lastgroup = NULL;
                W_Crylink_LinkExplode(this.queuenext, this, toucher);
                this.classname = "spike_oktoremove";
-               remove(this);
+               delete(this);
                return;
        }
        else if(finalhit)
        {
                // just unlink
                W_Crylink_Dequeue(this);
-               remove(this);
+               delete(this);
                return;
        }
        this.cnt = this.cnt - 1;
@@ -342,10 +342,10 @@ void W_Crylink_Touch(entity this, entity toucher)
 void W_Crylink_Fadethink(entity this)
 {
        W_Crylink_Dequeue(this);
-       remove(this);
+       delete(this);
 }
 
-void W_Crylink_Attack(Weapon thiswep, entity actor)
+void W_Crylink_Attack(Weapon thiswep, entity actor, .entity weaponentity)
 {
        float counter, shots;
        entity proj, prevproj, firstproj;
@@ -360,7 +360,7 @@ void W_Crylink_Attack(Weapon thiswep, entity actor)
        if(WEP_CVAR_PRI(crylink, joinexplode))
                maxdmg += WEP_CVAR_PRI(crylink, joinexplode_damage);
 
-       W_SetupShot(actor, false, 2, SND_CRYLINK_FIRE, CH_WEAPON_A, maxdmg);
+       W_SetupShot(actor, weaponentity, false, 2, SND_CRYLINK_FIRE, CH_WEAPON_A, maxdmg);
        forward = v_forward;
        right = v_right;
        up = v_up;
@@ -439,6 +439,7 @@ void W_Crylink_Attack(Weapon thiswep, entity actor)
                //proj.glow_size = 20;
 
                proj.flags = FL_PROJECTILE;
+               IL_PUSH(g_projectiles, proj);
                proj.missile_flags = MIF_SPLASH;
 
                CSQCProjectile(proj, true, (proj.cnt ? PROJECTILE_CRYLINK_BOUNCING : PROJECTILE_CRYLINK), true);
@@ -453,7 +454,7 @@ void W_Crylink_Attack(Weapon thiswep, entity actor)
        }
 }
 
-void W_Crylink_Attack2(Weapon thiswep, entity actor)
+void W_Crylink_Attack2(Weapon thiswep, entity actor, .entity weaponentity)
 {
        float counter, shots;
        entity proj, prevproj, firstproj;
@@ -468,7 +469,7 @@ void W_Crylink_Attack2(Weapon thiswep, entity actor)
        if(WEP_CVAR_SEC(crylink, joinexplode))
                maxdmg += WEP_CVAR_SEC(crylink, joinexplode_damage);
 
-       W_SetupShot(actor, false, 2, SND_CRYLINK_FIRE2, CH_WEAPON_A, maxdmg);
+       W_SetupShot(actor, weaponentity, false, 2, SND_CRYLINK_FIRE2, CH_WEAPON_A, maxdmg);
        forward = v_forward;
        right = v_right;
        up = v_up;
@@ -554,6 +555,7 @@ void W_Crylink_Attack2(Weapon thiswep, entity actor)
                //proj.glow_size = 20;
 
                proj.flags = FL_PROJECTILE;
+               IL_PUSH(g_projectiles, proj);
         proj.missile_flags = MIF_SPLASH;
 
                CSQCProjectile(proj, true, (proj.cnt ? PROJECTILE_CRYLINK_BOUNCING : PROJECTILE_CRYLINK), true);
@@ -586,7 +588,7 @@ METHOD(Crylink, wr_think, void(entity thiswep, entity actor, .entity weaponentit
         if(actor.crylink_waitrelease != 1)
         if(weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR_PRI(crylink, refire)))
         {
-            W_Crylink_Attack(thiswep, actor);
+            W_Crylink_Attack(thiswep, actor, weaponentity);
             weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_PRI(crylink, animtime), w_ready);
         }
     }
@@ -596,7 +598,7 @@ METHOD(Crylink, wr_think, void(entity thiswep, entity actor, .entity weaponentit
         if(actor.crylink_waitrelease != 2)
         if(weapon_prepareattack(thiswep, actor, weaponentity, true, WEP_CVAR_SEC(crylink, refire)))
         {
-            W_Crylink_Attack2(thiswep, actor);
+            W_Crylink_Attack2(thiswep, actor, weaponentity);
             weapon_thinkf(actor, weaponentity, WFRAME_FIRE2, WEP_CVAR_SEC(crylink, animtime), w_ready);
         }
     }
@@ -653,7 +655,7 @@ METHOD(Crylink, wr_checkammo2, bool(entity thiswep, entity actor))
 }
 METHOD(Crylink, wr_reload, void(entity thiswep, entity actor, .entity weaponentity))
 {
-    W_Reload(actor, min(WEP_CVAR_PRI(crylink, ammo), WEP_CVAR_SEC(crylink, ammo)), SND_RELOAD);
+    W_Reload(actor, weaponentity, min(WEP_CVAR_PRI(crylink, ammo), WEP_CVAR_SEC(crylink, ammo)), SND_RELOAD);
 }
 METHOD(Crylink, wr_suicidemessage, Notification(entity thiswep))
 {
index 3049225c4ffef66b20f13adfce03616ee2ac13e2..e02a474c2d43e817600595e22ae3725060020db6 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef IMPLEMENTATION
 CLASS(Devastator, Weapon)
-/* ammotype  */ ATTRIB(Devastator, ammo_field, .int, ammo_rockets)
-/* impulse   */ ATTRIB(Devastator, impulse, int, 9)
+/* ammotype  */ ATTRIB(Devastator, ammo_field, .int, ammo_rockets);
+/* impulse   */ ATTRIB(Devastator, impulse, int, 9);
 /* flags     */ ATTRIB(Devastator, spawnflags, int, WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH);
 /* rating    */ ATTRIB(Devastator, bot_pickupbasevalue, float, BOT_PICKUP_RATING_HIGH);
 /* color     */ ATTRIB(Devastator, wpcolor, vector, '1 1 0');
@@ -61,7 +61,7 @@ ENDCLASS(Devastator)
 REGISTER_WEAPON(DEVASTATOR, devastator, NEW(Devastator));
 
 #ifdef SVQC
-.float rl_release;
+.float rl_release[MAX_WEAPONSLOTS];
 .float rl_detonate_later;
 #endif
 #endif
@@ -76,7 +76,12 @@ void W_Devastator_Unregister(entity this)
 {
        if(this.realowner && this.realowner.lastrocket == this)
        {
-               this.realowner.lastrocket = NULL;
+               for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+               {
+                       .entity weaponentity = weaponentities[slot];
+                       if(this.realowner.(weaponentity).lastrocket == this)
+                               this.realowner.(weaponentity).lastrocket = NULL;
+               }
                // this.realowner.rl_release = 1;
        }
 }
@@ -120,7 +125,7 @@ void W_Devastator_Explode(entity this, entity directhitentity)
                        PS(this.realowner).m_switchweapon = w_getbestweapon(this.realowner);
                }
        }
-       remove(this);
+       delete(this);
 }
 
 void W_Devastator_Explode_think(entity this)
@@ -206,13 +211,13 @@ void W_Devastator_DoRemoteExplode(entity this, .entity weaponentity)
                        PS(this.realowner).m_switchweapon = w_getbestweapon(this.realowner);
                }
        }
-       remove(this);
+       delete(this);
 }
 
 void W_Devastator_RemoteExplode(entity this, .entity weaponentity)
 {
        if(!IS_DEAD(this.realowner))
-       if(this.realowner.lastrocket)
+       if(this.realowner.(weaponentity).lastrocket)
        {
                if((this.spawnshieldtime >= 0)
                        ? (time >= this.spawnshieldtime) // timer
@@ -278,8 +283,11 @@ void W_Devastator_Think(entity this)
        // laser guided, or remote detonation
        if(PS(this.realowner).m_weapon == WEP_DEVASTATOR)
        {
-               if(this == this.realowner.lastrocket)
-               if(!this.realowner.rl_release)
+               .entity weaponentity = this.weaponentity_fld;
+               int slot = weaponslot(weaponentity);
+
+               if(this == this.realowner.(weaponentity).lastrocket)
+               if(!this.realowner.rl_release[slot])
                if(!PHYS_INPUT_BUTTON_ATCK2(this))
                if(WEP_CVAR(devastator, guiderate))
                if(time > this.pushltime)
@@ -315,7 +323,6 @@ void W_Devastator_Think(entity this)
                        }
                }
 
-               .entity weaponentity = weaponentities[0]; // TODO: unhardcode
                if(this.rl_detonate_later)
                        W_Devastator_RemoteExplode(this, weaponentity);
        }
@@ -351,16 +358,17 @@ void W_Devastator_Damage(entity this, entity inflictor, entity attacker, float d
                W_PrepareExplosionByDamage(this, attacker, W_Devastator_Explode_think);
 }
 
-void W_Devastator_Attack(Weapon thiswep, entity actor)
+void W_Devastator_Attack(Weapon thiswep, entity actor, .entity weaponentity)
 {
        W_DecreaseAmmo(thiswep, actor, WEP_CVAR(devastator, ammo));
 
-       W_SetupShot_ProjectileSize(actor, '-3 -3 -3', '3 3 3', false, 5, SND_ROCKET_FIRE, CH_WEAPON_A, WEP_CVAR(devastator, damage));
+       W_SetupShot_ProjectileSize(actor, weaponentity, '-3 -3 -3', '3 3 3', false, 5, SND_ROCKET_FIRE, CH_WEAPON_A, WEP_CVAR(devastator, damage));
        Send_Effect(EFFECT_ROCKET_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
 
        entity missile = WarpZone_RefSys_SpawnSameRefSys(actor);
+       missile.weaponentity_fld = weaponentity;
        missile.owner = missile.realowner = actor;
-       actor.lastrocket = missile;
+       actor.(weaponentity).lastrocket = missile;
        if(WEP_CVAR(devastator, detonatedelay) >= 0)
                missile.spawnshieldtime = time + WEP_CVAR(devastator, detonatedelay);
        else
@@ -390,6 +398,7 @@ void W_Devastator_Attack(Weapon thiswep, entity actor)
        missile.nextthink = time;
        missile.cnt = time + WEP_CVAR(devastator, lifetime);
        missile.flags = FL_PROJECTILE;
+       IL_PUSH(g_projectiles, missile);
        missile.missile_flags = MIF_SPLASH;
 
        CSQCProjectile(missile, WEP_CVAR(devastator, guiderate) == 0 && WEP_CVAR(devastator, speedaccel) == 0, PROJECTILE_ROCKET, false); // because of fly sound
@@ -399,7 +408,7 @@ void W_Devastator_Attack(Weapon thiswep, entity actor)
        setmodel(flash, MDL_DEVASTATOR_MUZZLEFLASH); // precision set below
        SUB_SetFade(flash, time, 0.1);
        flash.effects = EF_ADDITIVE | EF_FULLBRIGHT | EF_LOWPRECISION;
-       W_AttachToShotorg(actor, flash, '5 0 0');
+       W_AttachToShotorg(actor, weaponentity, flash, '5 0 0');
 
        // common properties
        MUTATOR_CALLHOOK(EditProjectile, actor, missile);
@@ -522,18 +531,19 @@ METHOD(Devastator, wr_think, void(entity thiswep, entity actor, .entity weaponen
     if(WEP_CVAR(devastator, reload_ammo) && actor.clip_load < WEP_CVAR(devastator, ammo)) { // forced reload
         thiswep.wr_reload(thiswep, actor, weaponentity);
     } else {
+       int slot = weaponslot(weaponentity);
         if(fire & 1)
         {
-            if(actor.rl_release || WEP_CVAR(devastator, guidestop))
+            if(actor.rl_release[slot] || WEP_CVAR(devastator, guidestop))
             if(weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR(devastator, refire)))
             {
-                W_Devastator_Attack(thiswep, actor);
+                W_Devastator_Attack(thiswep, actor, weaponentity);
                 weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR(devastator, animtime), w_ready);
-                actor.rl_release = 0;
+                actor.rl_release[slot] = 0;
             }
         }
         else
-            actor.rl_release = 1;
+            actor.rl_release[slot] = 1;
 
         if(fire & 2)
         if(PS(actor).m_switchweapon == WEP_DEVASTATOR)
@@ -555,7 +565,8 @@ METHOD(Devastator, wr_think, void(entity thiswep, entity actor, .entity weaponen
 }
 METHOD(Devastator, wr_setup, void(entity thiswep, entity actor))
 {
-    actor.rl_release = 1;
+    for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+       actor.rl_release[slot] = 1;
 }
 METHOD(Devastator, wr_checkammo1, bool(entity thiswep, entity actor))
 {
@@ -599,12 +610,16 @@ METHOD(Devastator, wr_checkammo2, bool(entity thiswep, entity actor))
 }
 METHOD(Devastator, wr_resetplayer, void(entity thiswep, entity actor))
 {
-    actor.lastrocket = NULL; // stop rocket guiding, no revenge from the grave!
-    actor.rl_release = 0;
+    for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+    {
+       .entity weaponentity = weaponentities[slot];
+       actor.(weaponentity).lastrocket = NULL; // stop rocket guiding, no revenge from the grave!
+       actor.rl_release[slot] = 0;
+    }
 }
 METHOD(Devastator, wr_reload, void(entity thiswep, entity actor, .entity weaponentity))
 {
-    W_Reload(actor, WEP_CVAR(devastator, ammo), SND_RELOAD);
+    W_Reload(actor, weaponentity, WEP_CVAR(devastator, ammo), SND_RELOAD);
 }
 METHOD(Devastator, wr_suicidemessage, Notification(entity thiswep))
 {
index 2853625f2c343ef0829ab129ab635eeddd6ad6fe..2c74b3b451477c364232467a1792826c027cf994 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef IMPLEMENTATION
 CLASS(Electro, Weapon)
-/* ammotype  */ ATTRIB(Electro, ammo_field, .int, ammo_cells)
-/* impulse   */ ATTRIB(Electro, impulse, int, 5)
+/* ammotype  */ ATTRIB(Electro, ammo_field, .int, ammo_cells);
+/* impulse   */ ATTRIB(Electro, impulse, int, 5);
 /* flags     */ ATTRIB(Electro, spawnflags, int, WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH);
 /* rating    */ ATTRIB(Electro, bot_pickupbasevalue, float, BOT_PICKUP_RATING_MID);
 /* color     */ ATTRIB(Electro, wpcolor, vector, '0 0.5 1');
@@ -142,7 +142,7 @@ void W_Electro_ExplodeCombo(entity this)
                NULL
        );
 
-       remove(this);
+       delete(this);
 }
 
 void W_Electro_Explode(entity this, entity directhitentity)
@@ -189,7 +189,7 @@ void W_Electro_Explode(entity this, entity directhitentity)
                );
        }
 
-       remove(this);
+       delete(this);
 }
 
 void W_Electro_Explode_use(entity this, entity actor, entity trigger)
@@ -203,8 +203,12 @@ void W_Electro_TouchExplode(entity this, entity toucher)
        W_Electro_Explode(this, toucher);
 }
 
+
+void sys_phys_update_single(entity this);
+
 void W_Electro_Bolt_Think(entity this)
 {
+       // sys_phys_update_single(this);
        if(time >= this.ltime)
        {
                this.use(this, NULL, NULL);
@@ -253,9 +257,10 @@ void W_Electro_Bolt_Think(entity this)
                        { this.nextthink = min(time + WEP_CVAR_PRI(electro, midaircombo_interval), this.ltime); }
        }
        else { this.nextthink = this.ltime; }
+       // this.nextthink = time;
 }
 
-void W_Electro_Attack_Bolt(Weapon thiswep, entity actor)
+void W_Electro_Attack_Bolt(Weapon thiswep, entity actor, .entity weaponentity)
 {
        entity proj;
 
@@ -263,6 +268,7 @@ void W_Electro_Attack_Bolt(Weapon thiswep, entity actor)
 
        W_SetupShot_ProjectileSize(
                actor,
+               weaponentity,
                '0 0 -3',
                '0 0 -3',
                false,
@@ -286,17 +292,21 @@ void W_Electro_Attack_Bolt(Weapon thiswep, entity actor)
        proj.projectiledeathtype = WEP_ELECTRO.m_id;
        setorigin(proj, w_shotorg);
 
+       // if (IS_CSQC)
        set_movetype(proj, MOVETYPE_FLY);
        W_SetupProjVelocity_PRI(proj, electro);
        proj.angles = vectoangles(proj.velocity);
        settouch(proj, W_Electro_TouchExplode);
        setsize(proj, '0 0 -3', '0 0 -3');
        proj.flags = FL_PROJECTILE;
+       IL_PUSH(g_projectiles, proj);
        proj.missile_flags = MIF_SPLASH;
 
        CSQCProjectile(proj, true, PROJECTILE_ELECTRO_BEAM, true);
 
        MUTATOR_CALLHOOK(EditProjectile, actor, proj);
+       // proj.com_phys_pos = proj.origin;
+       // proj.com_phys_vel = proj.velocity;
 }
 
 void W_Electro_Orb_Stick(entity this, entity to)
@@ -330,7 +340,7 @@ void W_Electro_Orb_Stick(entity this, entity to)
        newproj.use = this.use;
        newproj.flags = this.flags;
 
-       remove(this);
+       delete(this);
 
        if(to)
                SetMovetypeFollow(this, to);
@@ -394,12 +404,13 @@ void W_Electro_Orb_Damage(entity this, entity inflictor, entity attacker, float
        }
 }
 
-void W_Electro_Attack_Orb(Weapon thiswep, entity actor)
+void W_Electro_Attack_Orb(Weapon thiswep, entity actor, .entity weaponentity)
 {
        W_DecreaseAmmo(thiswep, actor, WEP_CVAR_SEC(electro, ammo));
 
        W_SetupShot_ProjectileSize(
                actor,
+               weaponentity,
                '-4 -4 -4',
                '4 4 4',
                false,
@@ -435,6 +446,7 @@ void W_Electro_Attack_Orb(Weapon thiswep, entity actor)
        proj.health = WEP_CVAR_SEC(electro, health);
        proj.event_damage = W_Electro_Orb_Damage;
        proj.flags = FL_PROJECTILE;
+       IL_PUSH(g_projectiles, proj);
        proj.damagedbycontents = (WEP_CVAR_SEC(electro, damagedbycontents));
 
        proj.bouncefactor = WEP_CVAR_SEC(electro, bouncefactor);
@@ -460,7 +472,7 @@ void W_Electro_CheckAttack(Weapon thiswep, entity actor, .entity weaponentity, i
        if(PHYS_INPUT_BUTTON_ATCK2(actor))
        if(weapon_prepareattack(thiswep, actor, weaponentity, true, -1))
        {
-               W_Electro_Attack_Orb(WEP_ELECTRO, actor);
+               W_Electro_Attack_Orb(WEP_ELECTRO, actor, weaponentity);
                actor.electro_count -= 1;
                weapon_thinkf(actor, weaponentity, WFRAME_FIRE2, WEP_CVAR_SEC(electro, animtime), W_Electro_CheckAttack);
                return;
@@ -520,7 +532,7 @@ METHOD(Electro, wr_think, void(entity thiswep, entity actor, .entity weaponentit
     {
         if(weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR_PRI(electro, refire)))
         {
-                W_Electro_Attack_Bolt(thiswep, actor);
+                W_Electro_Attack_Bolt(thiswep, actor, weaponentity);
                 weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_PRI(electro, animtime), w_ready);
         }
     }
@@ -529,7 +541,7 @@ METHOD(Electro, wr_think, void(entity thiswep, entity actor, .entity weaponentit
         if(time >= actor.electro_secondarytime)
         if(weapon_prepareattack(thiswep, actor, weaponentity, true, WEP_CVAR_SEC(electro, refire)))
         {
-            W_Electro_Attack_Orb(thiswep, actor);
+            W_Electro_Attack_Orb(thiswep, actor, weaponentity);
             actor.electro_count = WEP_CVAR_SEC(electro, count);
             weapon_thinkf(actor, weaponentity, WFRAME_FIRE2, WEP_CVAR_SEC(electro, animtime), W_Electro_CheckAttack);
             actor.electro_secondarytime = time + WEP_CVAR_SEC(electro, refire2) * W_WeaponRateFactor(actor);
@@ -563,7 +575,7 @@ METHOD(Electro, wr_resetplayer, void(entity thiswep, entity actor))
 }
 METHOD(Electro, wr_reload, void(entity thiswep, entity actor, .entity weaponentity))
 {
-    W_Reload(actor, min(WEP_CVAR_PRI(electro, ammo), WEP_CVAR_SEC(electro, ammo)), SND_RELOAD);
+    W_Reload(actor, weaponentity, min(WEP_CVAR_PRI(electro, ammo), WEP_CVAR_SEC(electro, ammo)), SND_RELOAD);
 }
 METHOD(Electro, wr_suicidemessage, Notification(entity thiswep))
 {
index 69c2dc006f5d5c3eabe3e57b0c0b8c7e86263bdd..8d17a247d4c36c8408473c8c7b595e96c168ca7b 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef IMPLEMENTATION
 CLASS(Fireball, Weapon)
-/* ammotype  */ //ATTRIB(Fireball, ammo_field, .int, ammo_none)
-/* impulse   */ ATTRIB(Fireball, impulse, int, 9)
+/* ammotype  */ //ATTRIB(Fireball, ammo_field, .int, ammo_none);
+/* impulse   */ ATTRIB(Fireball, impulse, int, 9);
 /* flags     */ ATTRIB(Fireball, spawnflags, int, WEP_FLAG_SUPERWEAPON | WEP_TYPE_SPLASH);
 /* rating    */ ATTRIB(Fireball, bot_pickupbasevalue, float, BOT_PICKUP_RATING_MID);
 /* color     */ ATTRIB(Fireball, wpcolor, vector, '1 0.5 0');
@@ -55,7 +55,7 @@ REGISTER_WEAPON(FIREBALL, fireball, NEW(Fireball));
 #ifdef SVQC
 .float bot_primary_fireballmooth; // whatever a mooth is
 .vector fireball_impactvec;
-.float fireball_primarytime;
+.float fireball_primarytime[MAX_WEAPONSLOTS];
 #endif
 #endif
 #ifdef IMPLEMENTATION
@@ -109,7 +109,7 @@ void W_Fireball_Explode(entity this, entity directhitentity)
                }
        }
 
-       remove(this);
+       delete(this);
 }
 
 void W_Fireball_Explode_think(entity this)
@@ -193,15 +193,13 @@ void W_Fireball_Damage(entity this, entity inflictor, entity attacker, float dam
        }
 }
 
-void W_Fireball_Attack1(entity actor)
+void W_Fireball_Attack1(entity actor, .entity weaponentity)
 {
-       entity proj;
-
-       W_SetupShot_ProjectileSize(actor, '-16 -16 -16', '16 16 16', false, 2, SND_FIREBALL_FIRE2, CH_WEAPON_A, WEP_CVAR_PRI(fireball, damage) + WEP_CVAR_PRI(fireball, bfgdamage));
+       W_SetupShot_ProjectileSize(actor, weaponentity, '-16 -16 -16', '16 16 16', false, 2, SND_FIREBALL_FIRE2, CH_WEAPON_A, WEP_CVAR_PRI(fireball, damage) + WEP_CVAR_PRI(fireball, bfgdamage));
 
        Send_Effect(EFFECT_FIREBALL_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
 
-       proj = new(plasma_prim);
+       entity proj = new(plasma_prim);
        proj.owner = proj.realowner = actor;
        proj.bot_dodge = true;
        proj.bot_dodgerating = WEP_CVAR_PRI(fireball, damage);
@@ -224,6 +222,7 @@ void W_Fireball_Attack1(entity actor)
        settouch(proj, W_Fireball_TouchExplode);
        setsize(proj, '-16 -16 -16', '16 16 16');
        proj.flags = FL_PROJECTILE;
+       IL_PUSH(g_projectiles, proj);
     proj.missile_flags = MIF_SPLASH | MIF_PROXY;
 
        CSQCProjectile(proj, true, PROJECTILE_FIREBALL, true);
@@ -231,40 +230,40 @@ void W_Fireball_Attack1(entity actor)
        MUTATOR_CALLHOOK(EditProjectile, actor, proj);
 }
 
-void W_Fireball_AttackEffect(entity actor, float i, vector f_diff)
+void W_Fireball_AttackEffect(entity actor, .entity weaponentity, float i, vector f_diff)
 {
-       W_SetupShot_ProjectileSize(actor, '-16 -16 -16', '16 16 16', false, 0, SND_Null, 0, 0);
+       W_SetupShot_ProjectileSize(actor, weaponentity, '-16 -16 -16', '16 16 16', false, 0, SND_Null, 0, 0);
        w_shotorg += f_diff.x * v_up + f_diff.y * v_right;
        Send_Effect(EFFECT_FIREBALL_PRE_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
 }
 
 void W_Fireball_Attack1_Frame4(Weapon thiswep, entity actor, .entity weaponentity, int fire)
 {
-       W_Fireball_Attack1(actor);
+       W_Fireball_Attack1(actor, weaponentity);
        weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_PRI(fireball, animtime), w_ready);
 }
 
 void W_Fireball_Attack1_Frame3(Weapon thiswep, entity actor, .entity weaponentity, int fire)
 {
-       W_Fireball_AttackEffect(actor, 0, '+1.25 +3.75 0');
+       W_Fireball_AttackEffect(actor, weaponentity, 0, '+1.25 +3.75 0');
        weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_PRI(fireball, animtime), W_Fireball_Attack1_Frame4);
 }
 
 void W_Fireball_Attack1_Frame2(Weapon thiswep, entity actor, .entity weaponentity, int fire)
 {
-       W_Fireball_AttackEffect(actor, 0, '-1.25 +3.75 0');
+       W_Fireball_AttackEffect(actor, weaponentity, 0, '-1.25 +3.75 0');
        weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_PRI(fireball, animtime), W_Fireball_Attack1_Frame3);
 }
 
 void W_Fireball_Attack1_Frame1(Weapon thiswep, entity actor, .entity weaponentity, int fire)
 {
-       W_Fireball_AttackEffect(actor, 1, '+1.25 -3.75 0');
+       W_Fireball_AttackEffect(actor, weaponentity, 1, '+1.25 -3.75 0');
        weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_PRI(fireball, animtime), W_Fireball_Attack1_Frame2);
 }
 
 void W_Fireball_Attack1_Frame0(Weapon thiswep, entity actor, .entity weaponentity, int fire)
 {
-       W_Fireball_AttackEffect(actor, 0, '-1.25 -3.75 0');
+       W_Fireball_AttackEffect(actor, weaponentity, 0, '-1.25 -3.75 0');
        sound(actor, CH_WEAPON_SINGLE, SND_FIREBALL_PREFIRE2, VOL_BASE, ATTEN_NORM);
        weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_PRI(fireball, animtime), W_Fireball_Attack1_Frame1);
 }
@@ -273,7 +272,7 @@ void W_Fireball_Firemine_Think(entity this)
 {
        if(time > this.pushltime)
        {
-               remove(this);
+               delete(this);
                return;
        }
 
@@ -301,13 +300,13 @@ void W_Fireball_Firemine_Touch(entity this, entity toucher)
        if(toucher.takedamage == DAMAGE_AIM)
        if(Fire_AddDamage(toucher, this.realowner, WEP_CVAR_SEC(fireball, damage), WEP_CVAR_SEC(fireball, damagetime), this.projectiledeathtype) >= 0)
        {
-               remove(this);
+               delete(this);
                return;
        }
        this.projectiledeathtype |= HITTYPE_BOUNCE;
 }
 
-void W_Fireball_Attack2(entity actor)
+void W_Fireball_Attack2(entity actor, .entity weaponentity)
 {
        entity proj;
        vector f_diff;
@@ -330,7 +329,7 @@ void W_Fireball_Attack2(entity actor)
                        f_diff = '+1.25 +3.75 0';
                        break;
        }
-       W_SetupShot_ProjectileSize(actor, '-4 -4 -4', '4 4 4', false, 2, SND_FIREBALL_FIRE, CH_WEAPON_A, WEP_CVAR_SEC(fireball, damage));
+       W_SetupShot_ProjectileSize(actor, weaponentity, '-4 -4 -4', '4 4 4', false, 2, SND_FIREBALL_FIRE, CH_WEAPON_A, WEP_CVAR_SEC(fireball, damage));
        traceline(w_shotorg, w_shotorg + f_diff_x * v_up + f_diff_y * v_right, MOVE_NORMAL, actor);
        w_shotorg = trace_endpos;
 
@@ -354,6 +353,7 @@ void W_Fireball_Attack2(entity actor)
 
        proj.angles = vectoangles(proj.velocity);
        proj.flags = FL_PROJECTILE;
+       IL_PUSH(g_projectiles, proj);
     proj.missile_flags = MIF_SPLASH | MIF_PROXY | MIF_ARC;
 
        CSQCProjectile(proj, true, PROJECTILE_FIREMINE, true);
@@ -386,18 +386,19 @@ METHOD(Fireball, wr_think, void(entity thiswep, entity actor, .entity weaponenti
 {
     if(fire & 1)
     {
-        if(time >= actor.fireball_primarytime)
+       int slot = weaponslot(weaponentity);
+        if(time >= actor.fireball_primarytime[slot])
         if(weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR_PRI(fireball, refire)))
         {
             W_Fireball_Attack1_Frame0(thiswep, actor, weaponentity, fire);
-            actor.fireball_primarytime = time + WEP_CVAR_PRI(fireball, refire2) * W_WeaponRateFactor(actor);
+            actor.fireball_primarytime[slot] = time + WEP_CVAR_PRI(fireball, refire2) * W_WeaponRateFactor(actor);
         }
     }
     else if(fire & 2)
     {
         if(weapon_prepareattack(thiswep, actor, weaponentity, true, WEP_CVAR_SEC(fireball, refire)))
         {
-            W_Fireball_Attack2(actor);
+            W_Fireball_Attack2(actor, weaponentity);
             weapon_thinkf(actor, weaponentity, WFRAME_FIRE2, WEP_CVAR_SEC(fireball, animtime), w_ready);
         }
     }
@@ -416,7 +417,8 @@ METHOD(Fireball, wr_checkammo2, bool(entity thiswep, entity actor))
 }
 METHOD(Fireball, wr_resetplayer, void(entity thiswep, entity actor))
 {
-    actor.fireball_primarytime = time;
+       for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+       actor.fireball_primarytime[slot] = time;
 }
 METHOD(Fireball, wr_suicidemessage, Notification(entity thiswep))
 {
index 130c470636facc264f4b9759d187d87a52df3ecc..c83203272d8c935c1408dbeb087a2972b96c9f59 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef IMPLEMENTATION
 CLASS(Hagar, Weapon)
-/* ammotype  */ ATTRIB(Hagar, ammo_field, .int, ammo_rockets)
-/* impulse   */ ATTRIB(Hagar, impulse, int, 8)
+/* ammotype  */ ATTRIB(Hagar, ammo_field, .int, ammo_rockets);
+/* impulse   */ ATTRIB(Hagar, impulse, int, 8);
 /* flags     */ ATTRIB(Hagar, spawnflags, int, WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH);
 /* rating    */ ATTRIB(Hagar, bot_pickupbasevalue, float, BOT_PICKUP_RATING_MID);
 /* color     */ ATTRIB(Hagar, wpcolor, vector, '1 1 0.5');
@@ -68,7 +68,7 @@ void W_Hagar_Explode(entity this, entity directhitentity)
        this.event_damage = func_null;
        RadiusDamage(this, this.realowner, WEP_CVAR_PRI(hagar, damage), WEP_CVAR_PRI(hagar, edgedamage), WEP_CVAR_PRI(hagar, radius), NULL, NULL, WEP_CVAR_PRI(hagar, force), this.projectiledeathtype, directhitentity);
 
-       remove(this);
+       delete(this);
 }
 
 void W_Hagar_Explode_use(entity this, entity actor, entity trigger)
@@ -81,7 +81,7 @@ void W_Hagar_Explode2(entity this, entity directhitentity)
        this.event_damage = func_null;
        RadiusDamage(this, this.realowner, WEP_CVAR_SEC(hagar, damage), WEP_CVAR_SEC(hagar, edgedamage), WEP_CVAR_SEC(hagar, radius), NULL, NULL, WEP_CVAR_SEC(hagar, force), this.projectiledeathtype, directhitentity);
 
-       remove(this);
+       delete(this);
 }
 
 void W_Hagar_Explode2_use(entity this, entity actor, entity trigger)
@@ -134,13 +134,13 @@ void W_Hagar_Touch2(entity this, entity toucher)
        }
 }
 
-void W_Hagar_Attack(Weapon thiswep, entity actor)
+void W_Hagar_Attack(Weapon thiswep, entity actor, .entity weaponentity)
 {
        entity missile;
 
        W_DecreaseAmmo(thiswep, actor, WEP_CVAR_PRI(hagar, ammo));
 
-       W_SetupShot(actor, false, 2, SND_HAGAR_FIRE, CH_WEAPON_A, WEP_CVAR_PRI(hagar, damage));
+       W_SetupShot(actor, weaponentity, false, 2, SND_HAGAR_FIRE, CH_WEAPON_A, WEP_CVAR_PRI(hagar, damage));
 
        Send_Effect(EFFECT_HAGAR_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
 
@@ -169,6 +169,7 @@ void W_Hagar_Attack(Weapon thiswep, entity actor)
 
        missile.angles = vectoangles(missile.velocity);
        missile.flags = FL_PROJECTILE;
+       IL_PUSH(g_projectiles, missile);
        missile.missile_flags = MIF_SPLASH;
 
        CSQCProjectile(missile, true, PROJECTILE_HAGAR, true);
@@ -176,13 +177,13 @@ void W_Hagar_Attack(Weapon thiswep, entity actor)
        MUTATOR_CALLHOOK(EditProjectile, actor, missile);
 }
 
-void W_Hagar_Attack2(Weapon thiswep, entity actor)
+void W_Hagar_Attack2(Weapon thiswep, entity actor, .entity weaponentity)
 {
        entity missile;
 
        W_DecreaseAmmo(thiswep, actor, WEP_CVAR_SEC(hagar, ammo));
 
-       W_SetupShot(actor, false, 2, SND_HAGAR_FIRE, CH_WEAPON_A, WEP_CVAR_SEC(hagar, damage));
+       W_SetupShot(actor, weaponentity, false, 2, SND_HAGAR_FIRE, CH_WEAPON_A, WEP_CVAR_SEC(hagar, damage));
 
        Send_Effect(EFFECT_HAGAR_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
 
@@ -212,6 +213,7 @@ void W_Hagar_Attack2(Weapon thiswep, entity actor)
 
        missile.angles = vectoangles(missile.velocity);
        missile.flags = FL_PROJECTILE;
+       IL_PUSH(g_projectiles, missile);
        missile.missile_flags = MIF_SPLASH;
 
        CSQCProjectile(missile, true, PROJECTILE_HAGAR_BOUNCING, true);
@@ -234,7 +236,7 @@ void W_Hagar_Attack2_Load_Release(entity actor, .entity weaponentity)
 
        weapon_prepareattack_do(actor, weaponentity, true, WEP_CVAR_SEC(hagar, refire));
 
-       W_SetupShot(actor, false, 2, SND_HAGAR_FIRE, CH_WEAPON_A, WEP_CVAR_SEC(hagar, damage));
+       W_SetupShot(actor, weaponentity, false, 2, SND_HAGAR_FIRE, CH_WEAPON_A, WEP_CVAR_SEC(hagar, damage));
        Send_Effect(EFFECT_HAGAR_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
 
        forward = v_forward;
@@ -288,6 +290,7 @@ void W_Hagar_Attack2_Load_Release(entity actor, .entity weaponentity)
 
                missile.angles = vectoangles(missile.velocity);
                missile.flags = FL_PROJECTILE;
+               IL_PUSH(g_projectiles, missile);
 
                CSQCProjectile(missile, true, PROJECTILE_HAGAR, true);
 
@@ -423,7 +426,7 @@ void W_Hagar_Attack_Auto(Weapon thiswep, entity actor, .entity weaponentity, int
                return;
        }
 
-       W_Hagar_Attack(thiswep, actor);
+       W_Hagar_Attack(thiswep, actor, weaponentity);
 
        int slot = weaponslot(weaponentity);
        ATTACK_FINISHED(actor, slot) = time + WEP_CVAR_PRI(hagar, refire) * W_WeaponRateFactor(actor);
@@ -463,19 +466,18 @@ METHOD(Hagar, wr_think, void(entity thiswep, entity actor, .entity weaponentity,
     {
         if(weapon_prepareattack(thiswep, actor, weaponentity, true, WEP_CVAR_SEC(hagar, refire)))
         {
-            W_Hagar_Attack2(thiswep, actor);
+            W_Hagar_Attack2(thiswep, actor, weaponentity);
             weapon_thinkf(actor, weaponentity, WFRAME_FIRE2, WEP_CVAR_SEC(hagar, refire), w_ready);
         }
     }
 }
-METHOD(Hagar, wr_gonethink, void(entity thiswep, entity actor))
+METHOD(Hagar, wr_gonethink, void(entity thiswep, entity actor, .entity weaponentity))
 {
     // we lost the weapon and want to prepare switching away
     if(actor.hagar_load)
     {
-        .entity weaponentity = weaponentities[0]; // TODO: unhardcode
-        actor.(weaponentity).state = WS_READY;
-        W_Hagar_Attack2_Load_Release(actor, weaponentity);
+       actor.(weaponentity).state = WS_READY;
+       W_Hagar_Attack2_Load_Release(actor, weaponentity);
     }
 }
 METHOD(Hagar, wr_setup, void(entity thiswep, entity actor))
@@ -504,17 +506,16 @@ METHOD(Hagar, wr_resetplayer, void(entity thiswep, entity actor))
 {
     actor.hagar_load = 0;
 }
-METHOD(Hagar, wr_playerdeath, void(entity thiswep, entity actor))
+METHOD(Hagar, wr_playerdeath, void(entity thiswep, entity actor, .entity weaponentity))
 {
-    .entity weaponentity = weaponentities[0]; // TODO: unhardcode
     // if we have any rockets loaded when we die, release them
     if(actor.hagar_load && WEP_CVAR_SEC(hagar, load_releasedeath))
-        W_Hagar_Attack2_Load_Release(actor, weaponentity);
+       W_Hagar_Attack2_Load_Release(actor, weaponentity);
 }
 METHOD(Hagar, wr_reload, void(entity thiswep, entity actor, .entity weaponentity))
 {
     if(!actor.hagar_load) // require releasing loaded rockets first
-        W_Reload(actor, min(WEP_CVAR_PRI(hagar, ammo), WEP_CVAR_SEC(hagar, ammo)), SND_RELOAD);
+        W_Reload(actor, weaponentity, min(WEP_CVAR_PRI(hagar, ammo), WEP_CVAR_SEC(hagar, ammo)), SND_RELOAD);
 }
 METHOD(Hagar, wr_suicidemessage, Notification(entity thiswep))
 {
index ab4e2f7a0803780bb57960396ca058a4944a0a94..b545f6ce1ea7d4a1cf52d9d8c55d7ce62d6995cd 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef IMPLEMENTATION
 CLASS(HLAC, Weapon)
-/* ammotype  */ ATTRIB(HLAC, ammo_field, .int, ammo_cells)
-/* impulse   */ ATTRIB(HLAC, impulse, int, 6)
+/* ammotype  */ ATTRIB(HLAC, ammo_field, .int, ammo_cells);
+/* impulse   */ ATTRIB(HLAC, impulse, int, 6);
 /* flags     */ ATTRIB(HLAC, spawnflags, int, WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_RELOADABLE | WEP_TYPE_SPLASH);
 /* rating    */ ATTRIB(HLAC, bot_pickupbasevalue, float, BOT_PICKUP_RATING_MID);
 /* color     */ ATTRIB(HLAC, wpcolor, vector, '0 1 0');
@@ -66,10 +66,10 @@ void W_HLAC_Touch(entity this, entity toucher)
 
        RadiusDamage(this, this.realowner, WEP_CVAR_BOTH(hlac, isprimary, damage), WEP_CVAR_BOTH(hlac, isprimary, edgedamage), WEP_CVAR_BOTH(hlac, isprimary, radius), NULL, NULL, WEP_CVAR_BOTH(hlac, isprimary, force), this.projectiledeathtype, toucher);
 
-       remove(this);
+       delete(this);
 }
 
-void W_HLAC_Attack(Weapon thiswep, entity actor)
+void W_HLAC_Attack(Weapon thiswep, entity actor, .entity weaponentity)
 {
        entity missile;
     float spread;
@@ -81,7 +81,7 @@ void W_HLAC_Attack(Weapon thiswep, entity actor)
     if(actor.crouch)
         spread = spread * WEP_CVAR_PRI(hlac, spread_crouchmod);
 
-       W_SetupShot(actor, false, 3, SND_LASERGUN_FIRE, CH_WEAPON_A, WEP_CVAR_PRI(hlac, damage));
+       W_SetupShot(actor, weaponentity, false, 3, SND_LASERGUN_FIRE, CH_WEAPON_A, WEP_CVAR_PRI(hlac, damage));
        Send_Effect(EFFECT_BLASTER_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
        if(!autocvar_g_norecoil)
        {
@@ -110,6 +110,7 @@ void W_HLAC_Attack(Weapon thiswep, entity actor)
     missile.nextthink = time + WEP_CVAR_PRI(hlac, lifetime);
 
        missile.flags = FL_PROJECTILE;
+       IL_PUSH(g_projectiles, missile);
        missile.projectiledeathtype = WEP_HLAC.m_id;
 
        CSQCProjectile(missile, true, PROJECTILE_HLAC, true);
@@ -117,7 +118,7 @@ void W_HLAC_Attack(Weapon thiswep, entity actor)
        MUTATOR_CALLHOOK(EditProjectile, actor, missile);
 }
 
-void W_HLAC_Attack2(entity actor)
+void W_HLAC_Attack2(entity actor, .entity weaponentity)
 {
        entity missile;
     float spread;
@@ -128,7 +129,7 @@ void W_HLAC_Attack2(entity actor)
     if(actor.crouch)
         spread = spread * WEP_CVAR_SEC(hlac, spread_crouchmod);
 
-       W_SetupShot(actor, false, 3, SND_LASERGUN_FIRE, CH_WEAPON_A, WEP_CVAR_SEC(hlac, damage));
+       W_SetupShot(actor, weaponentity, false, 3, SND_LASERGUN_FIRE, CH_WEAPON_A, WEP_CVAR_SEC(hlac, damage));
        Send_Effect(EFFECT_BLASTER_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
 
        missile = new(hlacbolt);
@@ -152,6 +153,7 @@ void W_HLAC_Attack2(entity actor)
     missile.nextthink = time + WEP_CVAR_SEC(hlac, lifetime);
 
        missile.flags = FL_PROJECTILE;
+       IL_PUSH(g_projectiles, missile);
        missile.missile_flags = MIF_SPLASH;
        missile.projectiledeathtype = WEP_HLAC.m_id | HITTYPE_SECONDARY;
 
@@ -181,7 +183,7 @@ void W_HLAC_Attack_Frame(Weapon thiswep, entity actor, .entity weaponentity, int
 
                int slot = weaponslot(weaponentity);
                ATTACK_FINISHED(actor, slot) = time + WEP_CVAR_PRI(hlac, refire) * W_WeaponRateFactor(actor);
-               W_HLAC_Attack(WEP_HLAC, actor);
+               W_HLAC_Attack(WEP_HLAC, actor, weaponentity);
                actor.misc_bulletcounter = actor.misc_bulletcounter + 1;
         weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_PRI(hlac, refire), W_HLAC_Attack_Frame);
        }
@@ -191,14 +193,14 @@ void W_HLAC_Attack_Frame(Weapon thiswep, entity actor, .entity weaponentity, int
        }
 }
 
-void W_HLAC_Attack2_Frame(Weapon thiswep, entity actor)
+void W_HLAC_Attack2_Frame(Weapon thiswep, entity actor, .entity weaponentity)
 {
     float i;
 
        W_DecreaseAmmo(thiswep, actor, WEP_CVAR_SEC(hlac, ammo));
 
     for(i=WEP_CVAR_SEC(hlac, shots);i>0;--i)
-        W_HLAC_Attack2(actor);
+        W_HLAC_Attack2(actor, weaponentity);
 
        if(!autocvar_g_norecoil)
        {
@@ -220,7 +222,7 @@ METHOD(HLAC, wr_think, void(entity thiswep, entity actor, .entity weaponentity,
         if(weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR_PRI(hlac, refire)))
         {
             actor.misc_bulletcounter = 0;
-            W_HLAC_Attack(thiswep, actor);
+            W_HLAC_Attack(thiswep, actor, weaponentity);
             weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_PRI(hlac, refire), W_HLAC_Attack_Frame);
         }
     }
@@ -229,7 +231,7 @@ METHOD(HLAC, wr_think, void(entity thiswep, entity actor, .entity weaponentity,
     {
         if(weapon_prepareattack(thiswep, actor, weaponentity, true, WEP_CVAR_SEC(hlac, refire)))
         {
-            W_HLAC_Attack2_Frame(thiswep, actor);
+            W_HLAC_Attack2_Frame(thiswep, actor, weaponentity);
             weapon_thinkf(actor, weaponentity, WFRAME_FIRE2, WEP_CVAR_SEC(hlac, animtime), w_ready);
         }
     }
@@ -248,7 +250,7 @@ METHOD(HLAC, wr_checkammo2, bool(entity thiswep, entity actor))
 }
 METHOD(HLAC, wr_reload, void(entity thiswep, entity actor, .entity weaponentity))
 {
-    W_Reload(actor, min(WEP_CVAR_PRI(hlac, ammo), WEP_CVAR_SEC(hlac, ammo)), SND_RELOAD);
+    W_Reload(actor, weaponentity, min(WEP_CVAR_PRI(hlac, ammo), WEP_CVAR_SEC(hlac, ammo)), SND_RELOAD);
 }
 METHOD(HLAC, wr_suicidemessage, Notification(entity thiswep))
 {
index 01a3497d06f83497c934117fdba52966e3a66bf9..5e8119e6a6a5bc74d2497fb019b9ac129d9c604f 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef IMPLEMENTATION
 CLASS(Hook, Weapon)
-/* ammotype  */ ATTRIB(Hook, ammo_field, .int, ammo_fuel)
-/* impulse   */ ATTRIB(Hook, impulse, int, 0)
+/* ammotype  */ ATTRIB(Hook, ammo_field, .int, ammo_fuel);
+/* impulse   */ ATTRIB(Hook, impulse, int, 0);
 /* flags     */ ATTRIB(Hook, spawnflags, int, WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH);
 /* rating    */ ATTRIB(Hook, bot_pickupbasevalue, float, 0);
 /* color     */ ATTRIB(Hook, wpcolor, vector, '0 0.5 0');
@@ -14,7 +14,7 @@ CLASS(Hook, Weapon)
 /* wepimg    */ ATTRIB(Hook, model2, string, "weaponhook");
 /* refname   */ ATTRIB(Hook, netname, string, "hook");
 /* wepname   */ ATTRIB(Hook, m_name, string, _("Grappling Hook"));
-       ATTRIB(Hook, ammo_factor, float, 1)
+       ATTRIB(Hook, ammo_factor, float, 1);
 
 #define X(BEGIN, P, END, class, prefix) \
        BEGIN(class) \
@@ -96,7 +96,7 @@ void W_Hook_ExplodeThink(entity this)
        if(dt < this.dmg_duration)
                this.nextthink = time + 0.05; // soon
        else
-               remove(this);
+               delete(this);
 }
 
 void W_Hook_Explode2(entity this)
@@ -143,10 +143,10 @@ void W_Hook_Touch2(entity this, entity toucher)
        this.use(this, NULL, NULL);
 }
 
-void W_Hook_Attack2(Weapon thiswep, entity actor)
+void W_Hook_Attack2(Weapon thiswep, entity actor, .entity weaponentity)
 {
        //W_DecreaseAmmo(thiswep, actor, WEP_CVAR_SEC(hook, ammo)); // WEAPONTODO: Figure out how to handle ammo with hook secondary (gravitybomb)
-       W_SetupShot(actor, false, 4, SND_HOOKBOMB_FIRE, CH_WEAPON_A, WEP_CVAR_SEC(hook, damage));
+       W_SetupShot(actor, weaponentity, false, 4, SND_HOOKBOMB_FIRE, CH_WEAPON_A, WEP_CVAR_SEC(hook, damage));
 
        entity gren = new(hookbomb);
        gren.owner = gren.realowner = actor;
@@ -179,6 +179,7 @@ void W_Hook_Attack2(Weapon thiswep, entity actor)
 
        gren.angles = '0 0 0';
        gren.flags = FL_PROJECTILE;
+       IL_PUSH(g_projectiles, gren);
 
        CSQCProjectile(gren, true, PROJECTILE_HOOKBOMB, true);
 
@@ -207,7 +208,7 @@ METHOD(Hook, wr_think, void(entity thiswep, entity actor, .entity weaponentity,
     {
         if(weapon_prepareattack(thiswep, actor, weaponentity, true, WEP_CVAR_SEC(hook, refire)))
         {
-            W_Hook_Attack2(thiswep, actor);
+            W_Hook_Attack2(thiswep, actor, weaponentity);
             weapon_thinkf(actor, weaponentity, WFRAME_FIRE2, WEP_CVAR_SEC(hook, animtime), w_ready);
         }
     }
index 59dfc10e20ecfbb9f31b856d47a058ea432ab27e..e3d1da2fea86db9d6ad4cff51cbe881a45e5273e 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef IMPLEMENTATION
 CLASS(MachineGun, Weapon)
-/* ammotype  */ ATTRIB(MachineGun, ammo_field, .int, ammo_nails)
-/* impulse   */ ATTRIB(MachineGun, impulse, int, 3)
+/* ammotype  */ ATTRIB(MachineGun, ammo_field, .int, ammo_nails);
+/* impulse   */ ATTRIB(MachineGun, impulse, int, 3);
 /* flags     */ ATTRIB(MachineGun, spawnflags, int, WEP_FLAG_RELOADABLE | WEP_TYPE_HITSCAN);
 /* rating    */ ATTRIB(MachineGun, bot_pickupbasevalue, float, BOT_PICKUP_RATING_MID);
 /* color     */ ATTRIB(MachineGun, wpcolor, vector, '1 1 0');
@@ -88,27 +88,29 @@ void W_MachineGun_MuzzleFlash_Think(entity this)
 
 }
 
-void W_MachineGun_MuzzleFlash(entity actor)
+void W_MachineGun_MuzzleFlash(entity actor, .entity weaponentity)
 {
-       if(actor.muzzle_flash == NULL)
-               actor.muzzle_flash = spawn();
+       entity wepent = actor.(weaponentity);
+
+       if(wepent.muzzle_flash == NULL)
+               wepent.muzzle_flash = spawn();
 
        // muzzle flash for 1st person view
-       setmodel(actor.muzzle_flash, MDL_MACHINEGUN_MUZZLEFLASH); // precision set below
-
-       actor.muzzle_flash.scale = 0.75;
-       setthink(actor.muzzle_flash, W_MachineGun_MuzzleFlash_Think);
-       actor.muzzle_flash.nextthink = time + 0.02;
-       actor.muzzle_flash.frame = 2;
-       actor.muzzle_flash.alpha = 0.75;
-       actor.muzzle_flash.angles_z = random() * 180;
-       actor.muzzle_flash.effects = EF_ADDITIVE | EF_FULLBRIGHT | EF_LOWPRECISION;
-       actor.muzzle_flash.owner = actor.muzzle_flash.realowner = actor;
+       setmodel(wepent.muzzle_flash, MDL_MACHINEGUN_MUZZLEFLASH); // precision set below
+
+       wepent.muzzle_flash.scale = 0.75;
+       setthink(wepent.muzzle_flash, W_MachineGun_MuzzleFlash_Think);
+       wepent.muzzle_flash.nextthink = time + 0.02;
+       wepent.muzzle_flash.frame = 2;
+       wepent.muzzle_flash.alpha = 0.75;
+       wepent.muzzle_flash.angles_z = random() * 180;
+       wepent.muzzle_flash.effects = EF_ADDITIVE | EF_FULLBRIGHT | EF_LOWPRECISION;
+       wepent.muzzle_flash.owner = wepent.muzzle_flash.realowner = wepent;
 }
 
 void W_MachineGun_Attack(Weapon thiswep, int deathtype, entity actor, .entity weaponentity)
 {
-       W_SetupShot(actor, true, 0, SND_UZI_FIRE, CH_WEAPON_A, ((actor.misc_bulletcounter == 1) ? WEP_CVAR(machinegun, first_damage) : WEP_CVAR(machinegun, sustained_damage)));
+       W_SetupShot(actor, weaponentity, true, 0, SND_UZI_FIRE, CH_WEAPON_A, ((actor.misc_bulletcounter == 1) ? WEP_CVAR(machinegun, first_damage) : WEP_CVAR(machinegun, sustained_damage)));
        if(!autocvar_g_norecoil)
        {
                actor.punchangle_x = random() - 0.5;
@@ -125,14 +127,14 @@ void W_MachineGun_Attack(Weapon thiswep, int deathtype, entity actor, .entity we
 
        Send_Effect(EFFECT_MACHINEGUN_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
 
-       W_MachineGun_MuzzleFlash(actor);
-       W_AttachToShotorg(actor, actor.muzzle_flash, '5 0 0');
+       W_MachineGun_MuzzleFlash(actor, weaponentity);
+       W_AttachToShotorg(actor, weaponentity, actor.(weaponentity).muzzle_flash, '5 0 0');
 
        // casing code
        if(autocvar_g_casings >= 2)
        {
                makevectors(actor.v_angle); // for some reason, this is lost
-               SpawnCasing(((random() * 50 + 50) * v_right) - (v_forward * (random() * 25 + 25)) - ((random() * 5 - 70) * v_up), 2, vectoangles(v_forward),'0 250 0', 100, 3, actor);
+               SpawnCasing(((random() * 50 + 50) * v_right) - (v_forward * (random() * 25 + 25)) - ((random() * 5 - 70) * v_up), 2, vectoangles(v_forward),'0 250 0', 100, 3, actor, weaponentity);
        }
 
        if(actor.misc_bulletcounter == 1)
@@ -187,7 +189,7 @@ void W_MachineGun_Attack_Auto(Weapon thiswep, entity actor, .entity weaponentity
 
        W_DecreaseAmmo(WEP_MACHINEGUN, actor, WEP_CVAR(machinegun, sustained_ammo));
 
-       W_SetupShot(actor, true, 0, SND_UZI_FIRE, CH_WEAPON_A, WEP_CVAR(machinegun, sustained_damage));
+       W_SetupShot(actor, weaponentity, true, 0, SND_UZI_FIRE, CH_WEAPON_A, WEP_CVAR(machinegun, sustained_damage));
        if(!autocvar_g_norecoil)
        {
                actor.punchangle_x = random() - 0.5;
@@ -201,13 +203,13 @@ void W_MachineGun_Attack_Auto(Weapon thiswep, entity actor, .entity weaponentity
 
        Send_Effect(EFFECT_MACHINEGUN_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
 
-       W_MachineGun_MuzzleFlash(actor);
-       W_AttachToShotorg(actor, actor.muzzle_flash, '5 0 0');
+       W_MachineGun_MuzzleFlash(actor, weaponentity);
+       W_AttachToShotorg(actor, weaponentity, actor.(weaponentity).muzzle_flash, '5 0 0');
 
        if(autocvar_g_casings >= 2) // casing code
        {
                makevectors(actor.v_angle); // for some reason, this is lost
-               SpawnCasing(((random() * 50 + 50) * v_right) - (v_forward * (random() * 25 + 25)) - ((random() * 5 - 70) * v_up), 2, vectoangles(v_forward),'0 250 0', 100, 3, actor);
+               SpawnCasing(((random() * 50 + 50) * v_right) - (v_forward * (random() * 25 + 25)) - ((random() * 5 - 70) * v_up), 2, vectoangles(v_forward),'0 250 0', 100, 3, actor, weaponentity);
        }
 
        int slot = weaponslot(weaponentity);
@@ -217,7 +219,7 @@ void W_MachineGun_Attack_Auto(Weapon thiswep, entity actor, .entity weaponentity
 
 void W_MachineGun_Attack_Burst(Weapon thiswep, entity actor, .entity weaponentity, int fire)
 {
-       W_SetupShot(actor, true, 0, SND_UZI_FIRE, CH_WEAPON_A, WEP_CVAR(machinegun, sustained_damage));
+       W_SetupShot(actor, weaponentity, true, 0, SND_UZI_FIRE, CH_WEAPON_A, WEP_CVAR(machinegun, sustained_damage));
        if(!autocvar_g_norecoil)
        {
                actor.punchangle_x = random() - 0.5;
@@ -228,13 +230,13 @@ void W_MachineGun_Attack_Burst(Weapon thiswep, entity actor, .entity weaponentit
 
        Send_Effect(EFFECT_MACHINEGUN_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
 
-       W_MachineGun_MuzzleFlash(actor);
-       W_AttachToShotorg(actor, actor.muzzle_flash, '5 0 0');
+       W_MachineGun_MuzzleFlash(actor, weaponentity);
+       W_AttachToShotorg(actor, weaponentity, actor.(weaponentity).muzzle_flash, '5 0 0');
 
        if(autocvar_g_casings >= 2) // casing code
        {
                makevectors(actor.v_angle); // for some reason, this is lost
-               SpawnCasing(((random() * 50 + 50) * v_right) - (v_forward * (random() * 25 + 25)) - ((random() * 5 - 70) * v_up), 2, vectoangles(v_forward),'0 250 0', 100, 3, actor);
+               SpawnCasing(((random() * 50 + 50) * v_right) - (v_forward * (random() * 25 + 25)) - ((random() * 5 - 70) * v_up), 2, vectoangles(v_forward),'0 250 0', 100, 3, actor, weaponentity);
        }
 
        actor.misc_bulletcounter = actor.misc_bulletcounter + 1;
@@ -345,7 +347,7 @@ METHOD(MachineGun, wr_checkammo2, bool(entity thiswep, entity actor))
 }
 METHOD(MachineGun, wr_reload, void(entity thiswep, entity actor, .entity weaponentity))
 {
-    W_Reload(actor, min(max(WEP_CVAR(machinegun, sustained_ammo), WEP_CVAR(machinegun, first_ammo)), WEP_CVAR(machinegun, burst_ammo)), SND_RELOAD);
+    W_Reload(actor, weaponentity, min(max(WEP_CVAR(machinegun, sustained_ammo), WEP_CVAR(machinegun, first_ammo)), WEP_CVAR(machinegun, burst_ammo)), SND_RELOAD);
 }
 METHOD(MachineGun, wr_suicidemessage, Notification(entity thiswep))
 {
index 8b1e0cd2e12bbc268551ee8a62e117483b621639..3021f47454500838ebcdded983139fdeaea55f85 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef IMPLEMENTATION
 CLASS(MineLayer, Weapon)
-/* ammotype  */ ATTRIB(MineLayer, ammo_field, .int, ammo_rockets)
-/* impulse   */ ATTRIB(MineLayer, impulse, int, 4)
+/* ammotype  */ ATTRIB(MineLayer, ammo_field, .int, ammo_rockets);
+/* impulse   */ ATTRIB(MineLayer, impulse, int, 4);
 /* flags     */ ATTRIB(MineLayer, spawnflags, int, WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_RELOADABLE | WEP_TYPE_SPLASH);
 /* rating    */ ATTRIB(MineLayer, bot_pickupbasevalue, float, BOT_PICKUP_RATING_HIGH);
 /* color     */ ATTRIB(MineLayer, wpcolor, vector, '0.75 1 0');
@@ -70,6 +70,7 @@ void W_MineLayer_Stick(entity this, entity to)
        // in order for mines to face properly when sticking to the ground, they must be a server side entity rather than a csqc projectile
 
        entity newmine = spawn();
+       IL_PUSH(g_mines, newmine);
        newmine.classname = this.classname;
 
        newmine.bot_dodge = this.bot_dodge;
@@ -101,8 +102,9 @@ void W_MineLayer_Stick(entity this, entity to)
        newmine.nextthink = time;
        newmine.cnt = this.cnt;
        newmine.flags = this.flags;
+       IL_PUSH(g_projectiles, newmine);
 
-       remove(this);
+       delete(this);
 
        if(to)
                SetMovetypeFollow(newmine, to);
@@ -129,13 +131,14 @@ void W_MineLayer_Explode(entity this, entity directhitentity)
                if(!w.wr_checkammo1(w, own))
                {
                        own.cnt = WEP_MINE_LAYER.m_id;
-                       int slot = 0; // TODO: unhardcode
+                       .entity weaponentity = this.weaponentity_fld;
+                       int slot = weaponslot(weaponentity);
                        ATTACK_FINISHED(own, slot) = time;
                        PS(own).m_switchweapon = w_getbestweapon(own);
                }
        }
        this.realowner.minelayer_mines -= 1;
-       remove(this);
+       delete(this);
 }
 
 void W_MineLayer_Explode_think(entity this)
@@ -160,13 +163,14 @@ void W_MineLayer_DoRemoteExplode(entity this)
                if(!w.wr_checkammo1(w, own))
                {
                        own.cnt = WEP_MINE_LAYER.m_id;
-                       int slot = 0; // TODO: unhardcode
+                       .entity weaponentity = this.weaponentity_fld;
+                       int slot = weaponslot(weaponentity);
                        ATTACK_FINISHED(own, slot) = time;
                        PS(own).m_switchweapon = w_getbestweapon(own);
                }
        }
        this.realowner.minelayer_mines -= 1;
-       remove(this);
+       delete(this);
 }
 
 void W_MineLayer_RemoteExplode(entity this)
@@ -203,9 +207,10 @@ void W_MineLayer_ProximityExplode(entity this)
 int W_MineLayer_Count(entity e)
 {
        int minecount = 0;
-       entity mine;
-       for(mine = NULL; (mine = find(mine, classname, "mine")); ) if(mine.realowner == e)
+       IL_EACH(g_mines, it.realowner == e,
+       {
                minecount += 1;
+       });
 
        return minecount;
 }
@@ -312,7 +317,7 @@ void W_MineLayer_Damage(entity this, entity inflictor, entity attacker, float da
                W_PrepareExplosionByDamage(this, attacker, W_MineLayer_Explode_think);
 }
 
-void W_MineLayer_Attack(Weapon thiswep, entity actor)
+void W_MineLayer_Attack(Weapon thiswep, entity actor, .entity weaponentity)
 {
        entity mine;
        entity flash;
@@ -331,10 +336,12 @@ void W_MineLayer_Attack(Weapon thiswep, entity actor)
 
        W_DecreaseAmmo(thiswep, actor, WEP_CVAR(minelayer, ammo));
 
-       W_SetupShot_ProjectileSize(actor, '-4 -4 -4', '4 4 4', false, 5, SND_MINE_FIRE, CH_WEAPON_A, WEP_CVAR(minelayer, damage));
+       W_SetupShot_ProjectileSize(actor, weaponentity, '-4 -4 -4', '4 4 4', false, 5, SND_MINE_FIRE, CH_WEAPON_A, WEP_CVAR(minelayer, damage));
        Send_Effect(EFFECT_ROCKET_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
 
        mine = WarpZone_RefSys_SpawnSameRefSys(actor);
+       mine.weaponentity_fld = weaponentity;
+       IL_PUSH(g_mines, mine);
        mine.owner = mine.realowner = actor;
        if(WEP_CVAR(minelayer, detonatedelay) >= 0)
                mine.spawnshieldtime = time + WEP_CVAR(minelayer, detonatedelay);
@@ -364,6 +371,7 @@ void W_MineLayer_Attack(Weapon thiswep, entity actor)
        mine.nextthink = time;
        mine.cnt = (WEP_CVAR(minelayer, lifetime) - WEP_CVAR(minelayer, lifetime_countdown));
        mine.flags = FL_PROJECTILE;
+       IL_PUSH(g_projectiles, mine);
        mine.missile_flags = MIF_SPLASH | MIF_ARC | MIF_PROXY;
 
        if(mine.cnt > 0) { mine.cnt += time; }
@@ -375,7 +383,7 @@ void W_MineLayer_Attack(Weapon thiswep, entity actor)
        setmodel(flash, MDL_MINELAYER_MUZZLEFLASH); // precision set below
        SUB_SetFade(flash, time, 0.1);
        flash.effects = EF_ADDITIVE | EF_FULLBRIGHT | EF_LOWPRECISION;
-       W_AttachToShotorg(actor, flash, '5 0 0');
+       W_AttachToShotorg(actor, weaponentity, flash, '5 0 0');
 
        // common properties
 
@@ -384,24 +392,23 @@ void W_MineLayer_Attack(Weapon thiswep, entity actor)
        actor.minelayer_mines = W_MineLayer_Count(actor);
 }
 
-float W_MineLayer_PlacedMines(entity this, float detonate)
+bool W_MineLayer_PlacedMines(entity this, bool detonate)
 {
-       entity mine;
-       float minfound = 0;
+       bool minfound = false;
 
-       for(mine = NULL; (mine = find(mine, classname, "mine")); ) if(mine.realowner == this)
+       IL_EACH(g_mines, it.realowner == this,
        {
                if(detonate)
                {
-                       if(!mine.minelayer_detonate)
+                       if(!it.minelayer_detonate)
                        {
-                               mine.minelayer_detonate = true;
-                               minfound = 1;
+                               it.minelayer_detonate = true;
+                               minfound = true;
                        }
                }
                else
-                       minfound = 1;
-       }
+                       minfound = true;
+       });
        return minfound;
 }
 
@@ -425,10 +432,8 @@ METHOD(MineLayer, wr_aim, void(entity thiswep, entity actor))
         teamdamage = 0;
         enemydamage = 0;
 
-        FOREACH_ENTITY_ENT(realowner, actor,
+        IL_EACH(g_mines, it.realowner == actor,
         {
-               if(it.classname != "mine") continue;
-
                entity mine = it;
                FOREACH_ENTITY_FLOAT(bot_attack, true,
                {
@@ -452,10 +457,8 @@ METHOD(MineLayer, wr_aim, void(entity thiswep, entity actor))
             desirabledamage = desirabledamage - teamdamage;
 
         makevectors(actor.v_angle);
-        FOREACH_ENTITY_ENT(realowner, actor,
+        IL_EACH(g_mines, it.realowner == actor,
         {
-            if(it.classname != "mine") continue;
-
             if(skill > 9) // normal players only do this for the target they are tracking
             {
                    entity mine = it;
@@ -506,7 +509,7 @@ METHOD(MineLayer, wr_think, void(entity thiswep, entity actor, .entity weaponent
     {
         if(weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR(minelayer, refire)))
         {
-            W_MineLayer_Attack(thiswep, actor);
+            W_MineLayer_Attack(thiswep, actor, weaponentity);
             weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR(minelayer, animtime), w_ready);
         }
     }
@@ -542,7 +545,7 @@ METHOD(MineLayer, wr_resetplayer, void(entity thiswep, entity actor))
 }
 METHOD(MineLayer, wr_reload, void(entity thiswep, entity actor, .entity weaponentity))
 {
-    W_Reload(actor, WEP_CVAR(minelayer, ammo), SND_RELOAD);
+    W_Reload(actor, weaponentity, WEP_CVAR(minelayer, ammo), SND_RELOAD);
 }
 METHOD(MineLayer, wr_suicidemessage, Notification(entity thiswep))
 {
index 748c2347f71ebda4805493d839f17612f1892802..0a457f1a6be1730bfdef5642c529097d9cf16901 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef IMPLEMENTATION
 CLASS(Mortar, Weapon)
-/* ammotype  */ ATTRIB(Mortar, ammo_field, .int, ammo_rockets)
-/* impulse   */ ATTRIB(Mortar, impulse, int, 4)
+/* ammotype  */ ATTRIB(Mortar, ammo_field, .int, ammo_rockets);
+/* impulse   */ ATTRIB(Mortar, impulse, int, 4);
 /* flags     */ ATTRIB(Mortar, spawnflags, int, WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH);
 /* rating    */ ATTRIB(Mortar, bot_pickupbasevalue, float, BOT_PICKUP_RATING_MID);
 /* color     */ ATTRIB(Mortar, wpcolor, vector, '1 0 0');
@@ -81,7 +81,7 @@ void W_Mortar_Grenade_Explode(entity this, entity directhitentity)
 
        RadiusDamage(this, this.realowner, WEP_CVAR_PRI(mortar, damage), WEP_CVAR_PRI(mortar, edgedamage), WEP_CVAR_PRI(mortar, radius), NULL, NULL, WEP_CVAR_PRI(mortar, force), this.projectiledeathtype, directhitentity);
 
-       remove(this);
+       delete(this);
 }
 
 void W_Mortar_Grenade_Explode_use(entity this, entity actor, entity trigger)
@@ -106,7 +106,7 @@ void W_Mortar_Grenade_Explode2(entity this, entity directhitentity)
 
        RadiusDamage(this, this.realowner, WEP_CVAR_SEC(mortar, damage), WEP_CVAR_SEC(mortar, edgedamage), WEP_CVAR_SEC(mortar, radius), NULL, NULL, WEP_CVAR_SEC(mortar, force), this.projectiledeathtype, directhitentity);
 
-       remove(this);
+       delete(this);
 }
 
 void W_Mortar_Grenade_Explode2_use(entity this, entity actor, entity trigger)
@@ -209,18 +209,16 @@ void W_Mortar_Grenade_Touch2(entity this, entity toucher)
        }
 }
 
-void W_Mortar_Attack(Weapon thiswep, entity actor)
+void W_Mortar_Attack(Weapon thiswep, entity actor, .entity weaponentity)
 {
-       entity gren;
-
        W_DecreaseAmmo(thiswep, actor, WEP_CVAR_PRI(mortar, ammo));
 
-       W_SetupShot_ProjectileSize(actor, '-3 -3 -3', '3 3 3', false, 4, SND_GRENADE_FIRE, CH_WEAPON_A, WEP_CVAR_PRI(mortar, damage));
+       W_SetupShot_ProjectileSize(actor, weaponentity, '-3 -3 -3', '3 3 3', false, 4, SND_GRENADE_FIRE, CH_WEAPON_A, WEP_CVAR_PRI(mortar, damage));
        w_shotdir = v_forward; // no TrueAim for grenades please
 
        Send_Effect(EFFECT_GRENADE_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
 
-       gren = new(grenade);
+       entity gren = new(grenade);
        gren.owner = gren.realowner = actor;
        gren.bot_dodge = true;
        gren.bot_dodgerating = WEP_CVAR_PRI(mortar, damage);
@@ -248,6 +246,7 @@ void W_Mortar_Attack(Weapon thiswep, entity actor)
 
        gren.angles = vectoangles(gren.velocity);
        gren.flags = FL_PROJECTILE;
+       IL_PUSH(g_projectiles, gren);
 
        if(WEP_CVAR_PRI(mortar, type) == 0 || WEP_CVAR_PRI(mortar, type) == 2)
                CSQCProjectile(gren, true, PROJECTILE_GRENADE, true);
@@ -257,13 +256,13 @@ void W_Mortar_Attack(Weapon thiswep, entity actor)
        MUTATOR_CALLHOOK(EditProjectile, actor, gren);
 }
 
-void W_Mortar_Attack2(Weapon thiswep, entity actor)
+void W_Mortar_Attack2(Weapon thiswep, entity actor, .entity weaponentity)
 {
        entity gren;
 
        W_DecreaseAmmo(thiswep, actor, WEP_CVAR_SEC(mortar, ammo));
 
-       W_SetupShot_ProjectileSize(actor, '-3 -3 -3', '3 3 3', false, 4, SND_GRENADE_FIRE, CH_WEAPON_A, WEP_CVAR_SEC(mortar, damage));
+       W_SetupShot_ProjectileSize(actor, weaponentity, '-3 -3 -3', '3 3 3', false, 4, SND_GRENADE_FIRE, CH_WEAPON_A, WEP_CVAR_SEC(mortar, damage));
        w_shotdir = v_forward; // no TrueAim for grenades please
 
        Send_Effect(EFFECT_GRENADE_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
@@ -295,6 +294,7 @@ void W_Mortar_Attack2(Weapon thiswep, entity actor)
 
        gren.angles = vectoangles(gren.velocity);
        gren.flags = FL_PROJECTILE;
+       IL_PUSH(g_projectiles, gren);
 
        if(WEP_CVAR_SEC(mortar, type) == 0 || WEP_CVAR_SEC(mortar, type) == 2)
                CSQCProjectile(gren, true, PROJECTILE_GRENADE, true);
@@ -351,7 +351,7 @@ METHOD(Mortar, wr_think, void(entity thiswep, entity actor, .entity weaponentity
     {
         if(weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR_PRI(mortar, refire)))
         {
-            W_Mortar_Attack(thiswep, actor);
+            W_Mortar_Attack(thiswep, actor, weaponentity);
             weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_PRI(mortar, animtime), w_ready);
         }
     }
@@ -374,7 +374,7 @@ METHOD(Mortar, wr_think, void(entity thiswep, entity actor, .entity weaponentity
         }
         else if(weapon_prepareattack(thiswep, actor, weaponentity, true, WEP_CVAR_SEC(mortar, refire)))
         {
-            W_Mortar_Attack2(thiswep, actor);
+            W_Mortar_Attack2(thiswep, actor, weaponentity);
             weapon_thinkf(actor, weaponentity, WFRAME_FIRE2, WEP_CVAR_SEC(mortar, animtime), w_ready);
         }
     }
@@ -393,7 +393,7 @@ METHOD(Mortar, wr_checkammo2, bool(entity thiswep, entity actor))
 }
 METHOD(Mortar, wr_reload, void(entity thiswep, entity actor, .entity weaponentity))
 {
-    W_Reload(actor, min(WEP_CVAR_PRI(mortar, ammo), WEP_CVAR_SEC(mortar, ammo)), SND_RELOAD); // WEAPONTODO
+    W_Reload(actor, weaponentity, min(WEP_CVAR_PRI(mortar, ammo), WEP_CVAR_SEC(mortar, ammo)), SND_RELOAD); // WEAPONTODO
 }
 METHOD(Mortar, wr_suicidemessage, Notification(entity thiswep))
 {
index f17a2ac505f178514b6ee04b433bb9948441b477..b5bc00353e025e75f765023654ab13266ff55e5b 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef IMPLEMENTATION
 CLASS(PortoLaunch, Weapon)
-/* ammotype  */ ATTRIB(PortoLaunch, ammo_field, .int, ammo_none)
-/* impulse   */ ATTRIB(PortoLaunch, impulse, int, 0)
+/* ammotype  */ ATTRIB(PortoLaunch, ammo_field, .int, ammo_none);
+/* impulse   */ ATTRIB(PortoLaunch, impulse, int, 0);
 /* flags     */ ATTRIB(PortoLaunch, spawnflags, int, WEP_TYPE_OTHER | WEP_FLAG_SUPERWEAPON);
 /* rating    */ ATTRIB(PortoLaunch, bot_pickupbasevalue, float, 0);
 /* color     */ ATTRIB(PortoLaunch, wpcolor, vector, '0.5 0.5 0.5');
@@ -62,7 +62,7 @@ void W_Porto_Success(entity this)
        }
 
        this.realowner.porto_current = NULL;
-       remove(this);
+       delete(this);
 }
 
 string W_ThrowNewWeapon(entity own, float wpn, float doreduce, vector org, vector velo);
@@ -98,7 +98,7 @@ void W_Porto_Fail(entity this, float failhard)
                        }
                }
        }
-       remove(this);
+       delete(this);
 }
 
 void W_Porto_Remove(entity p)
@@ -113,7 +113,7 @@ void W_Porto_Think(entity this)
 {
        trace_plane_normal = '0 0 0';
        if(this.realowner.playerid != this.playerid)
-               remove(this);
+               delete(this);
        else
                W_Porto_Fail(this, 0);
 }
@@ -143,7 +143,7 @@ void W_Porto_Touch(entity this, entity toucher)
        if(this.realowner.playerid != this.playerid)
        {
                sound(this, CH_SHOTS, SND_PORTO_UNSUPPORTED, VOL_BASE, ATTEN_NORM);
-               remove(this);
+               delete(this);
        }
        else if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_SLICK || trace_dphitcontents & DPCONTENTS_PLAYERCLIP)
        {
@@ -240,11 +240,11 @@ void W_Porto_Touch(entity this, entity toucher)
        }
 }
 
-void W_Porto_Attack(entity actor, float type)
+void W_Porto_Attack(entity actor, .entity weaponentity, float type)
 {
        entity gren;
 
-       W_SetupShot(actor, false, 4, SND_PORTO_FIRE, CH_WEAPON_A, 0);
+       W_SetupShot(actor, weaponentity, false, 4, SND_PORTO_FIRE, CH_WEAPON_A, 0);
        // always shoot from the eye
        w_shotdir = v_forward;
        w_shotorg = actor.origin + actor.view_ofs + ((w_shotorg - actor.origin - actor.view_ofs) * v_forward) * v_forward;
@@ -275,6 +275,7 @@ void W_Porto_Attack(entity actor, float type)
 
        gren.angles = vectoangles(gren.velocity);
        gren.flags = FL_PROJECTILE;
+       IL_PUSH(g_projectiles, gren);
 
        gren.portal_id = time;
        actor.porto_current = gren;
@@ -309,7 +310,7 @@ METHOD(PortoLaunch, wr_think, void(entity thiswep, entity actor, .entity weapone
         if(!actor.porto_forbidden)
         if(weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR_PRI(porto, refire)))
         {
-            W_Porto_Attack(actor, 0);
+            W_Porto_Attack(actor, weaponentity, 0);
             weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_PRI(porto, animtime), w_ready);
         }
 
@@ -318,7 +319,7 @@ METHOD(PortoLaunch, wr_think, void(entity thiswep, entity actor, .entity weapone
         if(!actor.porto_forbidden)
         if(weapon_prepareattack(thiswep, actor, weaponentity, true, WEP_CVAR_SEC(porto, refire)))
         {
-            W_Porto_Attack(actor, 1);
+            W_Porto_Attack(actor, weaponentity, 1);
             weapon_thinkf(actor, weaponentity, WFRAME_FIRE2, WEP_CVAR_SEC(porto, animtime), w_ready);
         }
     }
@@ -351,7 +352,7 @@ METHOD(PortoLaunch, wr_think, void(entity thiswep, entity actor, .entity weapone
         if(!actor.porto_forbidden)
         if(weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR_PRI(porto, refire)))
         {
-            W_Porto_Attack(actor, -1);
+            W_Porto_Attack(actor, weaponentity, -1);
             weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_PRI(porto, animtime), w_ready);
         }
     }
@@ -377,7 +378,7 @@ METHOD(PortoLaunch, wr_resetplayer, void(entity thiswep, entity actor))
 #endif
 #ifdef CSQC
 METHOD(PortoLaunch, wr_impacteffect, void(entity this, entity actor)) {
-    LOG_WARNING("Since when does Porto send DamageInfo?\n");
+    LOG_WARN("Since when does Porto send DamageInfo?");
 }
 #endif
 #endif
index c46b8f2b2cc8cd859add380552083e8839a7c879..1b6faee7860ca6a4f0296ae7481af98db06ae3a7 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef IMPLEMENTATION
 CLASS(Rifle, Weapon)
-/* ammotype  */ ATTRIB(Rifle, ammo_field, .int, ammo_nails)
-/* impulse   */ ATTRIB(Rifle, impulse, int, 7)
+/* ammotype  */ ATTRIB(Rifle, ammo_field, .int, ammo_nails);
+/* impulse   */ ATTRIB(Rifle, impulse, int, 7);
 /* flags     */ ATTRIB(Rifle, spawnflags, int, WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_RELOADABLE | WEP_TYPE_HITSCAN);
 /* rating    */ ATTRIB(Rifle, bot_pickupbasevalue, float, BOT_PICKUP_RATING_MID);
 /* color     */ ATTRIB(Rifle, wpcolor, vector, '0.5 1 0');
@@ -56,13 +56,13 @@ spawnfunc(weapon_rifle) { weapon_defaultspawnfunc(this, WEP_RIFLE); }
 spawnfunc(weapon_campingrifle) { spawnfunc_weapon_rifle(this); }
 spawnfunc(weapon_sniperrifle) { spawnfunc_weapon_rifle(this); }
 
-void W_Rifle_FireBullet(Weapon thiswep, float pSpread, float pDamage, float pForce, float pSolidPenetration, float pAmmo, int deathtype, float pTracer, float pShots, Sound pSound, entity actor)
+void W_Rifle_FireBullet(Weapon thiswep, .entity weaponentity, float pSpread, float pDamage, float pForce, float pSolidPenetration, float pAmmo, int deathtype, float pTracer, float pShots, Sound pSound, entity actor)
 {
        float i;
 
        W_DecreaseAmmo(thiswep, actor, pAmmo);
 
-       W_SetupShot(actor, true, 2, pSound, CH_WEAPON_A, pDamage * pShots);
+       W_SetupShot(actor, weaponentity, true, 2, pSound, CH_WEAPON_A, pDamage * pShots);
 
        Send_Effect(EFFECT_RIFLE_MUZZLEFLASH, w_shotorg, w_shotdir * 2000, 1);
 
@@ -78,21 +78,21 @@ void W_Rifle_FireBullet(Weapon thiswep, float pSpread, float pDamage, float pFor
        if(autocvar_g_casings >= 2)
     {
         makevectors(actor.v_angle); // for some reason, this is lost
-               SpawnCasing(((random() * 50 + 50) * v_right) - (v_forward * (random() * 25 + 25)) - ((random() * 5 - 70) * v_up), 2, vectoangles(v_forward),'0 250 0', 100, 3, actor);
+               SpawnCasing(((random() * 50 + 50) * v_right) - (v_forward * (random() * 25 + 25)) - ((random() * 5 - 70) * v_up), 2, vectoangles(v_forward),'0 250 0', 100, 3, actor, weaponentity);
     }
 }
 
-void W_Rifle_Attack(entity actor)
+void W_Rifle_Attack(entity actor, .entity weaponentity)
 {
-       W_Rifle_FireBullet(WEP_RIFLE, WEP_CVAR_PRI(rifle, spread), WEP_CVAR_PRI(rifle, damage), WEP_CVAR_PRI(rifle, force), WEP_CVAR_PRI(rifle, solidpenetration), WEP_CVAR_PRI(rifle, ammo), WEP_RIFLE.m_id, WEP_CVAR_PRI(rifle, tracer), WEP_CVAR_PRI(rifle, shots), SND_CAMPINGRIFLE_FIRE, actor);
+       W_Rifle_FireBullet(WEP_RIFLE, weaponentity, WEP_CVAR_PRI(rifle, spread), WEP_CVAR_PRI(rifle, damage), WEP_CVAR_PRI(rifle, force), WEP_CVAR_PRI(rifle, solidpenetration), WEP_CVAR_PRI(rifle, ammo), WEP_RIFLE.m_id, WEP_CVAR_PRI(rifle, tracer), WEP_CVAR_PRI(rifle, shots), SND_CAMPINGRIFLE_FIRE, actor);
 }
 
-void W_Rifle_Attack2(entity actor)
+void W_Rifle_Attack2(entity actor, .entity weaponentity)
 {
-       W_Rifle_FireBullet(WEP_RIFLE, WEP_CVAR_SEC(rifle, spread), WEP_CVAR_SEC(rifle, damage), WEP_CVAR_SEC(rifle, force), WEP_CVAR_SEC(rifle, solidpenetration), WEP_CVAR_SEC(rifle, ammo), WEP_RIFLE.m_id | HITTYPE_SECONDARY, WEP_CVAR_SEC(rifle, tracer), WEP_CVAR_SEC(rifle, shots), SND_CAMPINGRIFLE_FIRE2, actor);
+       W_Rifle_FireBullet(WEP_RIFLE, weaponentity, WEP_CVAR_SEC(rifle, spread), WEP_CVAR_SEC(rifle, damage), WEP_CVAR_SEC(rifle, force), WEP_CVAR_SEC(rifle, solidpenetration), WEP_CVAR_SEC(rifle, ammo), WEP_RIFLE.m_id | HITTYPE_SECONDARY, WEP_CVAR_SEC(rifle, tracer), WEP_CVAR_SEC(rifle, shots), SND_CAMPINGRIFLE_FIRE2, actor);
 }
 
-.void(entity actor) rifle_bullethail_attackfunc;
+.void(entity actor, .entity weaponentity) rifle_bullethail_attackfunc;
 .WFRAME rifle_bullethail_frame;
 .float rifle_bullethail_animtime;
 .float rifle_bullethail_refire;
@@ -110,7 +110,7 @@ void W_Rifle_BulletHail_Continue(Weapon thiswep, entity actor, .entity weaponent
                PS(actor).m_switchweapon = sw;
        if(r)
        {
-               actor.rifle_bullethail_attackfunc(actor);
+               actor.rifle_bullethail_attackfunc(actor, weaponentity);
                weapon_thinkf(actor, weaponentity, actor.rifle_bullethail_frame, actor.rifle_bullethail_animtime, W_Rifle_BulletHail_Continue);
        }
        else
@@ -119,10 +119,10 @@ void W_Rifle_BulletHail_Continue(Weapon thiswep, entity actor, .entity weaponent
        }
 }
 
-void W_Rifle_BulletHail(entity actor, .entity weaponentity, float mode, void(entity actor) AttackFunc, WFRAME fr, float animtime, float refire)
+void W_Rifle_BulletHail(entity actor, .entity weaponentity, float mode, void(entity actor, .entity weaponentity) AttackFunc, WFRAME fr, float animtime, float refire)
 {
        // if we get here, we have at least one bullet to fire
-       AttackFunc(actor);
+       AttackFunc(actor, weaponentity);
        if(mode)
        {
                // continue hail
@@ -217,7 +217,7 @@ METHOD(Rifle, wr_resetplayer, void(entity thiswep, entity actor))
 }
 METHOD(Rifle, wr_reload, void(entity thiswep, entity actor, .entity weaponentity))
 {
-    W_Reload(actor, min(WEP_CVAR_PRI(rifle, ammo), WEP_CVAR_SEC(rifle, ammo)), SND_RELOAD);
+    W_Reload(actor, weaponentity, min(WEP_CVAR_PRI(rifle, ammo), WEP_CVAR_SEC(rifle, ammo)), SND_RELOAD);
 }
 METHOD(Rifle, wr_suicidemessage, Notification(entity thiswep))
 {
index 00e481ba26584ddc0cf4383b10e4646cffb93e7c..9f0a326ff2d53da99691044fb3bd42f273ed3430 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef IMPLEMENTATION
 CLASS(Seeker, Weapon)
-/* ammotype  */ ATTRIB(Seeker, ammo_field, .int, ammo_rockets)
-/* impulse   */ ATTRIB(Seeker, impulse, int, 8)
+/* ammotype  */ ATTRIB(Seeker, ammo_field, .int, ammo_rockets);
+/* impulse   */ ATTRIB(Seeker, impulse, int, 8);
 /* flags     */ ATTRIB(Seeker, spawnflags, int, WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_RELOADABLE | WEP_TYPE_SPLASH);
 /* rating    */ ATTRIB(Seeker, bot_pickupbasevalue, float, BOT_PICKUP_RATING_HIGH);
 /* color     */ ATTRIB(Seeker, wpcolor, vector, '0.5 1 0');
@@ -99,7 +99,7 @@ void W_Seeker_Missile_Explode(entity this, entity directhitentity)
        this.event_damage = func_null;
        RadiusDamage(this, this.realowner, WEP_CVAR(seeker, missile_damage), WEP_CVAR(seeker, missile_edgedamage), WEP_CVAR(seeker, missile_radius), NULL, NULL, WEP_CVAR(seeker, missile_force), this.projectiledeathtype, directhitentity);
 
-       remove(this);
+       delete(this);
 }
 
 void W_Seeker_Missile_Explode_think(entity this)
@@ -253,20 +253,18 @@ void W_Seeker_Missile_Animate(entity this)
 }
 */
 
-void W_Seeker_Fire_Missile(Weapon thiswep, entity actor, vector f_diff, entity m_target)
+void W_Seeker_Fire_Missile(Weapon thiswep, entity actor, .entity weaponentity, vector f_diff, entity m_target)
 {
-       entity missile;
-
        W_DecreaseAmmo(thiswep, actor, WEP_CVAR(seeker, missile_ammo));
 
        makevectors(actor.v_angle);
-       W_SetupShot_ProjectileSize(actor, '-2 -2 -2', '2 2 2', false, 2, SND_SEEKER_FIRE, CH_WEAPON_A, 0);
+       W_SetupShot_ProjectileSize(actor, weaponentity, '-2 -2 -2', '2 2 2', false, 2, SND_SEEKER_FIRE, CH_WEAPON_A, 0);
        w_shotorg += f_diff;
        Send_Effect(EFFECT_SEEKER_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
 
        //actor.detornator         = false;
 
-       missile                 = new(seeker_missile);
+       entity missile                 = new(seeker_missile);
        missile.owner           = missile.realowner = actor;
        missile.bot_dodge       = true;
        missile.bot_dodgerating = WEP_CVAR(seeker, missile_damage);
@@ -294,7 +292,8 @@ void W_Seeker_Fire_Missile(Weapon thiswep, entity actor, vector f_diff, entity m
        setorigin(missile, w_shotorg);
        setsize(missile, '-4 -4 -4', '4 4 4');
        set_movetype(missile, MOVETYPE_FLYMISSILE);
-       missile.flags       = FL_PROJECTILE;
+       missile.flags = FL_PROJECTILE;
+       IL_PUSH(g_projectiles, missile);
        missile.missile_flags = MIF_SPLASH | MIF_GUIDED_TAG;
 
        W_SetupProjVelocity_UP_PRE(missile, seeker, missile_);
@@ -315,7 +314,7 @@ void W_Seeker_Flac_Explode(entity this, entity directhitentity)
 
        RadiusDamage(this, this.realowner, WEP_CVAR(seeker, flac_damage), WEP_CVAR(seeker, flac_edgedamage), WEP_CVAR(seeker, flac_radius), NULL, NULL, WEP_CVAR(seeker, flac_force), this.projectiledeathtype, directhitentity);
 
-       remove(this);
+       delete(this);
 }
 
 void W_Seeker_Flac_Touch(entity this, entity toucher)
@@ -328,7 +327,7 @@ void W_Seeker_Flac_Explode_use(entity this, entity actor, entity trigger)
        W_Seeker_Flac_Explode(this, trigger);
 }
 
-void W_Seeker_Fire_Flac(Weapon thiswep, entity actor)
+void W_Seeker_Fire_Flac(Weapon thiswep, entity actor, .entity weaponentity)
 {
        entity missile;
        vector f_diff;
@@ -353,7 +352,7 @@ void W_Seeker_Fire_Flac(Weapon thiswep, entity actor)
                        f_diff = '+1.25 +3.75 0';
                        break;
        }
-       W_SetupShot_ProjectileSize(actor, '-2 -2 -2', '2 2 2', false, 2, SND_FLAC_FIRE, CH_WEAPON_A, WEP_CVAR(seeker, flac_damage));
+       W_SetupShot_ProjectileSize(actor, weaponentity, '-2 -2 -2', '2 2 2', false, 2, SND_FLAC_FIRE, CH_WEAPON_A, WEP_CVAR(seeker, flac_damage));
        w_shotorg += f_diff;
 
        Send_Effect(EFFECT_HAGAR_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
@@ -370,7 +369,8 @@ void W_Seeker_Fire_Flac(Weapon thiswep, entity actor)
        set_movetype(missile, MOVETYPE_FLY);
        missile.projectiledeathtype = WEP_SEEKER.m_id;
        missile.projectiledeathtype = WEP_SEEKER.m_id | HITTYPE_SECONDARY;
-       missile.flags                           = FL_PROJECTILE;
+       missile.flags = FL_PROJECTILE;
+       IL_PUSH(g_projectiles, missile);
        missile.missile_flags       = MIF_SPLASH;
 
        // csqc projectiles
@@ -399,7 +399,7 @@ entity W_Seeker_Tagged_Info(entity isowner, entity istarget)
        return NULL;
 }
 
-void W_Seeker_Attack(entity actor)
+void W_Seeker_Attack(entity actor, .entity weaponentity)
 {
        entity tracker, closest_target;
 
@@ -419,7 +419,7 @@ void W_Seeker_Attack(entity actor)
        if((!closest_target) || ((trace_fraction < 1) && (trace_ent != closest_target)))
                closest_target = NULL;
 
-       W_Seeker_Fire_Missile(WEP_SEEKER, actor, '0 0 0', closest_target);
+       W_Seeker_Fire_Missile(WEP_SEEKER, actor, weaponentity, '0 0 0', closest_target);
 }
 
 void W_Seeker_Vollycontroller_Think(entity this) // TODO: Merge this with W_Seeker_Attack
@@ -431,7 +431,7 @@ void W_Seeker_Vollycontroller_Think(entity this) // TODO: Merge this with W_Seek
        Weapon thiswep = WEP_SEEKER;
        if((!(this.realowner.items & IT_UNLIMITED_AMMO) && this.realowner.(thiswep.ammo_field) < WEP_CVAR(seeker, missile_ammo)) || (this.cnt <= -1) || (IS_DEAD(this.realowner)) || (PS(this.realowner).m_switchweapon != WEP_SEEKER))
        {
-               remove(this);
+               delete(this);
                return;
        }
 
@@ -441,22 +441,23 @@ void W_Seeker_Vollycontroller_Think(entity this) // TODO: Merge this with W_Seek
 
        oldenemy = own.enemy;
        own.enemy = this.enemy;
+       .entity weaponentity = this.weaponentity_fld;
 
        c = own.cnt % 4;
        switch(c)
        {
                case 0:
-                       W_Seeker_Fire_Missile(WEP_SEEKER, own, '-1.25 -3.75 0', own.enemy);
+                       W_Seeker_Fire_Missile(WEP_SEEKER, own, weaponentity, '-1.25 -3.75 0', own.enemy); // TODO
                        break;
                case 1:
-                       W_Seeker_Fire_Missile(WEP_SEEKER, own, '+1.25 -3.75 0', own.enemy);
+                       W_Seeker_Fire_Missile(WEP_SEEKER, own, weaponentity, '+1.25 -3.75 0', own.enemy); // TODO
                        break;
                case 2:
-                       W_Seeker_Fire_Missile(WEP_SEEKER, own, '-1.25 +3.75 0', own.enemy);
+                       W_Seeker_Fire_Missile(WEP_SEEKER, own, weaponentity, '-1.25 +3.75 0', own.enemy); // TODO
                        break;
                case 3:
                default:
-                       W_Seeker_Fire_Missile(WEP_SEEKER, own, '+1.25 +3.75 0', own.enemy);
+                       W_Seeker_Fire_Missile(WEP_SEEKER, own, weaponentity, '+1.25 +3.75 0', own.enemy); // TODO
                        break;
        }
 
@@ -472,7 +473,7 @@ void W_Seeker_Tracker_Think(entity this)
                if(this)
                {
                        WaypointSprite_Kill(this.tag_target.wps_tag_tracker);
-                       remove(this);
+                       delete(this);
                }
                return;
        }
@@ -490,7 +491,7 @@ void W_Seeker_Tag_Explode(entity this)
        //    return;
        Damage_DamageInfo(this.origin, 0, 0, 0, this.velocity, WEP_SEEKER.m_id | HITTYPE_BOUNCE, 0, this);
 
-       remove(this);
+       delete(this);
 }
 
 void W_Seeker_Tag_Damage(entity this, entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
@@ -534,6 +535,7 @@ void W_Seeker_Tag_Touch(entity this, entity toucher)
                {
                        //sprint(this.realowner, strcat("You just tagged ^2", toucher.netname, "^7 with a tracking device!\n"));
                        e             = new(tag_tracker);
+                       e.weaponentity_fld = this.weaponentity_fld;
                        e.cnt         = WEP_CVAR(seeker, missile_count);
                        e.owner       = this.owner;
                        e.realowner   = this.realowner;
@@ -560,18 +562,18 @@ void W_Seeker_Tag_Touch(entity this, entity toucher)
                }
        }
 
-       remove(this);
+       delete(this);
        return;
 }
 
-void W_Seeker_Fire_Tag(Weapon thiswep, entity actor)
+void W_Seeker_Fire_Tag(Weapon thiswep, entity actor, .entity weaponentity)
 {
-       entity missile;
        W_DecreaseAmmo(thiswep, actor, WEP_CVAR(seeker, tag_ammo));
 
-       W_SetupShot_ProjectileSize(actor, '-2 -2 -2', '2 2 2', false, 2, SND_TAG_FIRE, CH_WEAPON_A, WEP_CVAR(seeker, missile_damage) * WEP_CVAR(seeker, missile_count));
+       W_SetupShot_ProjectileSize(actor, weaponentity, '-2 -2 -2', '2 2 2', false, 2, SND_TAG_FIRE, CH_WEAPON_A, WEP_CVAR(seeker, missile_damage) * WEP_CVAR(seeker, missile_count));
 
-       missile                 = new(seeker_tag);
+       entity missile          = new(seeker_tag);
+       missile.weaponentity_fld = weaponentity;
        missile.owner           = missile.realowner = actor;
        missile.bot_dodge       = true;
        missile.bot_dodgerating = 50;
@@ -589,7 +591,8 @@ void W_Seeker_Fire_Tag(Weapon thiswep, entity actor)
        setorigin(missile, w_shotorg);
        setsize(missile, '-2 -2 -2', '2 2 2');
 
-       missile.flags       = FL_PROJECTILE;
+       missile.flags = FL_PROJECTILE;
+       IL_PUSH(g_projectiles, missile);
        //missile.missile_flags = MIF_..?;
 
        set_movetype(missile, MOVETYPE_FLY);
@@ -625,7 +628,7 @@ METHOD(Seeker, wr_think, void(entity thiswep, entity actor, .entity weaponentity
         {
             if(weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR(seeker, missile_refire)))
             {
-                W_Seeker_Attack(actor);
+                W_Seeker_Attack(actor, weaponentity);
                 weapon_thinkf(actor, weaponentity, WFRAME_FIRE2, WEP_CVAR(seeker, missile_animtime), w_ready);
             }
         }
@@ -633,7 +636,7 @@ METHOD(Seeker, wr_think, void(entity thiswep, entity actor, .entity weaponentity
         {
             if(weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR(seeker, tag_refire)))
             {
-                W_Seeker_Fire_Tag(thiswep, actor);
+                W_Seeker_Fire_Tag(thiswep, actor, weaponentity);
                 weapon_thinkf(actor, weaponentity, WFRAME_FIRE2, WEP_CVAR(seeker, tag_animtime), w_ready);
             }
         }
@@ -645,7 +648,7 @@ METHOD(Seeker, wr_think, void(entity thiswep, entity actor, .entity weaponentity
         {
             if(weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR(seeker, tag_refire)))
             {
-                W_Seeker_Fire_Tag(thiswep, actor);
+                W_Seeker_Fire_Tag(thiswep, actor, weaponentity);
                 weapon_thinkf(actor, weaponentity, WFRAME_FIRE2, WEP_CVAR(seeker, tag_animtime), w_ready);
             }
         }
@@ -653,7 +656,7 @@ METHOD(Seeker, wr_think, void(entity thiswep, entity actor, .entity weaponentity
         {
             if(weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR(seeker, flac_refire)))
             {
-                W_Seeker_Fire_Flac(thiswep, actor);
+                W_Seeker_Fire_Flac(thiswep, actor, weaponentity);
                 weapon_thinkf(actor, weaponentity, WFRAME_FIRE2, WEP_CVAR(seeker, flac_animtime), w_ready);
             }
         }
@@ -691,7 +694,7 @@ METHOD(Seeker, wr_checkammo2, bool(entity thiswep, entity actor))
 }
 METHOD(Seeker, wr_reload, void(entity thiswep, entity actor, .entity weaponentity))
 {
-    W_Reload(actor, min(WEP_CVAR(seeker, missile_ammo), WEP_CVAR(seeker, tag_ammo)), SND_RELOAD);
+    W_Reload(actor, weaponentity, min(WEP_CVAR(seeker, missile_ammo), WEP_CVAR(seeker, tag_ammo)), SND_RELOAD);
 }
 METHOD(Seeker, wr_suicidemessage, Notification(entity thiswep))
 {
index 539ccfdb72c444d8686be62258616cd9008155db..de7726f24f225b1d22d9586bf4b695d92bfa6093 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef IMPLEMENTATION
 CLASS(Shockwave, Weapon)
-/* ammotype  */ //ATTRIB(Shockwave, ammo_field, .int, ammo_none)
-/* impulse   */ ATTRIB(Shockwave, impulse, int, 2)
-/* flags     */ ATTRIB(Shockwave, spawnflags, int, WEP_FLAG_NORMAL | WEP_TYPE_HITSCAN | WEP_FLAG_CANCLIMB | WEP_TYPE_MELEE_SEC);
+/* ammotype  */ //ATTRIB(Shockwave, ammo_field, .int, ammo_none);
+/* impulse   */ ATTRIB(Shockwave, impulse, int, 2);
+/* flags     */ ATTRIB(Shockwave, spawnflags, int, WEP_TYPE_HITSCAN | WEP_FLAG_CANCLIMB | WEP_TYPE_MELEE_SEC);
 /* rating    */ ATTRIB(Shockwave, bot_pickupbasevalue, float, BOT_PICKUP_RATING_LOW);
 /* color     */ ATTRIB(Shockwave, wpcolor, vector, '0.5 0.25 0');
 /* modelname */ ATTRIB(Shockwave, mdl, string, "shotgun");
@@ -122,7 +122,7 @@ void W_Shockwave_Melee_Think(entity this)
        // check to see if we can still continue, otherwise give up now
        if(IS_DEAD(this.realowner) && WEP_CVAR(shockwave, melee_no_doubleslap))
        {
-               remove(this);
+               delete(this);
                return;
        }
 
@@ -214,7 +214,7 @@ void W_Shockwave_Melee_Think(entity this)
                        }
                        else
                        {
-                               remove(this);
+                               delete(this);
                                return;
                        }
                }
@@ -223,7 +223,7 @@ void W_Shockwave_Melee_Think(entity this)
        if(time >= this.cnt + meleetime)
        {
                // melee is finished
-               remove(this);
+               delete(this);
                return;
        }
        else
@@ -243,7 +243,7 @@ void W_Shockwave_Melee(Weapon thiswep, entity actor, .entity weaponentity, int f
        meleetemp.owner = meleetemp.realowner = actor;
        setthink(meleetemp, W_Shockwave_Melee_Think);
        meleetemp.nextthink = time + WEP_CVAR(shockwave, melee_delay) * W_WeaponRateFactor(actor);
-       W_SetupShot_Range(actor, true, 0, SND_Null, 0, WEP_CVAR(shockwave, melee_damage), WEP_CVAR(shockwave, melee_range));
+       W_SetupShot_Range(actor, weaponentity, true, 0, SND_Null, 0, WEP_CVAR(shockwave, melee_damage), WEP_CVAR(shockwave, melee_range));
 }
 
 // SHOCKWAVE ATTACK MODE
@@ -355,7 +355,7 @@ void W_Shockwave_Send(entity actor)
        WriteByte(MSG_BROADCAST, etof(actor));
 }
 
-void W_Shockwave_Attack(entity actor)
+void W_Shockwave_Attack(entity actor, .entity weaponentity)
 {
        // declarations
        float multiplier, multiplier_from_accuracy, multiplier_from_distance;
@@ -366,7 +366,7 @@ void W_Shockwave_Attack(entity actor)
        float i, queue = 0;
 
        // set up the shot direction
-       W_SetupShot(actor, true, 3, SND_LASERGUN_FIRE, CH_WEAPON_B, WEP_CVAR(shockwave, blast_damage));
+       W_SetupShot(actor, weaponentity, true, 3, SND_LASERGUN_FIRE, CH_WEAPON_B, WEP_CVAR(shockwave, blast_damage));
        vector attack_endpos = (w_shotorg + (w_shotdir * WEP_CVAR(shockwave, blast_distance)));
        WarpZone_TraceLine(w_shotorg, attack_endpos, MOVE_NOMONSTERS, actor);
        vector attack_hitpos = trace_endpos;
@@ -709,7 +709,7 @@ METHOD(Shockwave, wr_think, void(entity thiswep, entity actor, .entity weaponent
         {
             if(weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR(shockwave, blast_animtime)))
             {
-                W_Shockwave_Attack(actor);
+                W_Shockwave_Attack(actor, weaponentity);
                 actor.shockwave_blasttime = time + WEP_CVAR(shockwave, blast_refire) * W_WeaponRateFactor(actor);
                 weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR(shockwave, blast_animtime), w_ready);
             }
@@ -718,7 +718,6 @@ METHOD(Shockwave, wr_think, void(entity thiswep, entity actor, .entity weaponent
     else if(fire & 2)
     {
         //if(actor.clip_load >= 0) // we are not currently reloading
-        if(!actor.crouch) // no crouchmelee please
         if(weapon_prepareattack(thiswep, actor, weaponentity, true, WEP_CVAR(shockwave, melee_refire)))
         {
             // attempt forcing playback of the anim by switching to another anim (that we never play) here...
@@ -757,7 +756,7 @@ void Draw_Shockwave(entity this)
 {
        // fading/removal control
        float a = bound(0, (SW_MAXALPHA - ((time - this.sw_time) / SW_FADETIME)), SW_MAXALPHA);
-       if(a < ALPHA_MIN_VISIBLE) { remove(this); }
+       if(a < ALPHA_MIN_VISIBLE) { delete(this); }
 
        // WEAPONTODO: save this only once when creating the entity
        vector sw_color = entcs_GetColor(this.sv_entnum - 1); // GetTeamRGB(entcs_GetTeam(this.sv_entnum));
index f89ef6872b1db46ce3706b4a0799e2dc00ecb3b7..9c7aff3acab2af395a02bbb10313b025628d6ec3 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef IMPLEMENTATION
 CLASS(Shotgun, Weapon)
-/* ammotype  */ ATTRIB(Shotgun, ammo_field, .int, ammo_shells)
-/* impulse   */ ATTRIB(Shotgun, impulse, int, 2)
+/* ammotype  */ ATTRIB(Shotgun, ammo_field, .int, ammo_shells);
+/* impulse   */ ATTRIB(Shotgun, impulse, int, 2);
 /* flags     */ ATTRIB(Shotgun, spawnflags, int, WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_TYPE_HITSCAN | WEP_TYPE_MELEE_SEC);
 /* rating    */ ATTRIB(Shotgun, bot_pickupbasevalue, float, BOT_PICKUP_RATING_LOW);
 /* color     */ ATTRIB(Shotgun, wpcolor, vector, '0.5 0.25 0');
@@ -58,15 +58,12 @@ REGISTER_WEAPON(SHOTGUN, shotgun, NEW(Shotgun));
 #ifdef SVQC
 spawnfunc(weapon_shotgun) { weapon_defaultspawnfunc(this, WEP_SHOTGUN); }
 
-void W_Shotgun_Attack(Weapon thiswep, entity actor, float isprimary)
+void W_Shotgun_Attack(Weapon thiswep, entity actor, .entity weaponentity, float isprimary)
 {
-       float   sc;
-       entity flash;
-
        W_DecreaseAmmo(thiswep, actor, WEP_CVAR_PRI(shotgun, ammo));
 
-       W_SetupShot(actor, true, 5, SND_SHOTGUN_FIRE, ((isprimary) ? CH_WEAPON_A : CH_WEAPON_SINGLE), WEP_CVAR_PRI(shotgun, damage) * WEP_CVAR_PRI(shotgun, bullets));
-       for(sc = 0;sc < WEP_CVAR_PRI(shotgun, bullets);sc = sc + 1)
+       W_SetupShot(actor, weaponentity, true, 5, SND_SHOTGUN_FIRE, ((isprimary) ? CH_WEAPON_A : CH_WEAPON_SINGLE), WEP_CVAR_PRI(shotgun, damage) * WEP_CVAR_PRI(shotgun, bullets));
+       for(int sc = 0;sc < WEP_CVAR_PRI(shotgun, bullets);sc = sc + 1)
                fireBullet(actor, w_shotorg, w_shotdir, WEP_CVAR_PRI(shotgun, spread), WEP_CVAR_PRI(shotgun, solidpenetration), WEP_CVAR_PRI(shotgun, damage), WEP_CVAR_PRI(shotgun, force), WEP_SHOTGUN.m_id, 0);
 
        Send_Effect(EFFECT_SHOTGUN_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, WEP_CVAR_PRI(shotgun, ammo));
@@ -75,17 +72,17 @@ void W_Shotgun_Attack(Weapon thiswep, entity actor, float isprimary)
        if(autocvar_g_casings >= 1)
        {
                makevectors(actor.v_angle); // for some reason, this is lost
-               for(sc = 0;sc < WEP_CVAR_PRI(shotgun, ammo);sc = sc + 1)
-                       SpawnCasing(((random() * 50 + 50) * v_right) - (v_forward * (random() * 25 + 25)) - ((random() * 5 - 30) * v_up), 2, vectoangles(v_forward),'0 250 0', 100, 1, actor);
+               //for(int sc = 0;sc < WEP_CVAR_PRI(shotgun, ammo);sc = sc + 1)
+                       SpawnCasing(((random() * 50 + 50) * v_right) - (v_forward * (random() * 25 + 25)) - ((random() * 5 - 30) * v_up), 2, vectoangles(v_forward),'0 250 0', 100, 1, actor, weaponentity);
        }
 
        // muzzle flash for 1st person view
-       flash = spawn();
+       entity flash = spawn();
        setmodel(flash, MDL_SHOTGUN_MUZZLEFLASH); // precision set below
        setthink(flash, SUB_Remove);
        flash.nextthink = time + 0.06;
        flash.effects = EF_ADDITIVE | EF_FULLBRIGHT | EF_LOWPRECISION;
-       W_AttachToShotorg(actor, flash, '5 0 0');
+       W_AttachToShotorg(actor, weaponentity, flash, '5 0 0');
 }
 
 .float swing_prev;
@@ -113,7 +110,7 @@ void W_Shotgun_Melee_Think(entity this)
        // check to see if we can still continue, otherwise give up now
        if(IS_DEAD(this.realowner) && WEP_CVAR_SEC(shotgun, melee_no_doubleslap))
        {
-               remove(this);
+               delete(this);
                return;
        }
 
@@ -166,7 +163,7 @@ void W_Shotgun_Melee_Think(entity this)
                        }
                        else
                        {
-                               remove(this);
+                               delete(this);
                                return;
                        }
                }
@@ -175,7 +172,7 @@ void W_Shotgun_Melee_Think(entity this)
        if(time >= this.cnt + meleetime)
        {
                // melee is finished
-               remove(this);
+               delete(this);
                return;
        }
        else
@@ -195,7 +192,7 @@ void W_Shotgun_Attack2(Weapon thiswep, entity actor, .entity weaponentity, int f
        meleetemp.realowner = actor;
        setthink(meleetemp, W_Shotgun_Melee_Think);
        meleetemp.nextthink = time + WEP_CVAR_SEC(shotgun, melee_delay) * W_WeaponRateFactor(actor);
-       W_SetupShot_Range(actor, true, 0, SND_Null, 0, WEP_CVAR_SEC(shotgun, damage), WEP_CVAR_SEC(shotgun, melee_range));
+       W_SetupShot_Range(actor, weaponentity, true, 0, SND_Null, 0, WEP_CVAR_SEC(shotgun, damage), WEP_CVAR_SEC(shotgun, melee_range));
 }
 
 // alternate secondary weapon frames
@@ -210,7 +207,7 @@ void W_Shotgun_Attack3_Frame2(Weapon thiswep, entity actor, .entity weaponentity
        }
 
        sound(actor, CH_WEAPON_SINGLE, SND_Null, VOL_BASE, ATTN_NORM); // kill previous sound
-       W_Shotgun_Attack(WEP_SHOTGUN, actor, true); // actually is secondary, but we trick the last shot into playing full reload sound
+       W_Shotgun_Attack(WEP_SHOTGUN, actor, weaponentity, true); // actually is secondary, but we trick the last shot into playing full reload sound
        weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_SEC(shotgun, alt_animtime), w_ready);
 }
 void W_Shotgun_Attack3_Frame1(Weapon thiswep, entity actor, .entity weaponentity, int fire)
@@ -223,11 +220,11 @@ void W_Shotgun_Attack3_Frame1(Weapon thiswep, entity actor, .entity weaponentity
                return;
        }
 
-       W_Shotgun_Attack(WEP_SHOTGUN, actor, false);
+       W_Shotgun_Attack(WEP_SHOTGUN, actor, weaponentity, false);
        weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_SEC(shotgun, alt_animtime), W_Shotgun_Attack3_Frame2);
 }
 
-.float shotgun_primarytime;
+.float shotgun_primarytime[MAX_WEAPONSLOTS];
 
 METHOD(Shotgun, wr_aim, void(entity thiswep, entity actor))
 {
@@ -249,31 +246,32 @@ METHOD(Shotgun, wr_think, void(entity thiswep, entity actor, .entity weaponentit
     {
         if(fire & 1)
         {
-            if(time >= actor.shotgun_primarytime) // handle refire separately so the secondary can be fired straight after a primary
+               int slot = weaponslot(weaponentity);
+            if(time >= actor.shotgun_primarytime[slot]) // handle refire separately so the secondary can be fired straight after a primary
             {
                 if(weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR_PRI(shotgun, animtime)))
                 {
-                    W_Shotgun_Attack(thiswep, actor, true);
-                    actor.shotgun_primarytime = time + WEP_CVAR_PRI(shotgun, refire) * W_WeaponRateFactor(actor);
+                    W_Shotgun_Attack(thiswep, actor, weaponentity, true);
+                    actor.shotgun_primarytime[slot] = time + WEP_CVAR_PRI(shotgun, refire) * W_WeaponRateFactor(actor);
                     weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_PRI(shotgun, animtime), w_ready);
                 }
             }
         }
         else if((fire & 2) && WEP_CVAR(shotgun, secondary) == 2)
         {
-            if(time >= actor.shotgun_primarytime) // handle refire separately so the secondary can be fired straight after a primary
+               int slot = weaponslot(weaponentity);
+            if(time >= actor.shotgun_primarytime[slot]) // handle refire separately so the secondary can be fired straight after a primary
             {
                 if(weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR_SEC(shotgun, alt_animtime)))
                 {
-                    W_Shotgun_Attack(thiswep, actor, false);
-                    actor.shotgun_primarytime = time + WEP_CVAR_SEC(shotgun, alt_refire) * W_WeaponRateFactor(actor);
+                    W_Shotgun_Attack(thiswep, actor, weaponentity, false);
+                    actor.shotgun_primarytime[slot] = time + WEP_CVAR_SEC(shotgun, alt_refire) * W_WeaponRateFactor(actor);
                     weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_SEC(shotgun, alt_animtime), W_Shotgun_Attack3_Frame1);
                 }
             }
         }
     }
     if(actor.clip_load >= 0) // we are not currently reloading
-    if(!actor.crouch) // no crouchmelee please
     if(WEP_CVAR(shotgun, secondary) == 1)
     if(((fire & 1) && actor.(thiswep.ammo_field) <= 0 && !(actor.items & IT_UNLIMITED_WEAPON_AMMO)) || (fire & 2))
     if(weapon_prepareattack(thiswep, actor, weaponentity, true, WEP_CVAR_SEC(shotgun, refire)))
@@ -311,7 +309,7 @@ METHOD(Shotgun, wr_checkammo2, bool(entity thiswep, entity actor))
 }
 METHOD(Shotgun, wr_reload, void(entity thiswep, entity actor, .entity weaponentity))
 {
-    W_Reload(actor, WEP_CVAR_PRI(shotgun, ammo), SND_RELOAD); // WEAPONTODO
+    W_Reload(actor, weaponentity, WEP_CVAR_PRI(shotgun, ammo), SND_RELOAD); // WEAPONTODO
 }
 METHOD(Shotgun, wr_suicidemessage, Notification(entity thiswep))
 {
index c0e0ac89ba89814e3fd8fab83b8e0f8e30a00a41..31d2bf7a6299fcf735df432d93fa931ee31caf0d 100644 (file)
@@ -1,6 +1,6 @@
 #ifndef IMPLEMENTATION
 CLASS(Tuba, Weapon)
-/* impulse   */ ATTRIB(Tuba, impulse, int, 1)
+/* impulse   */ ATTRIB(Tuba, impulse, int, 1);
 /* flags     */ ATTRIB(Tuba, spawnflags, int, WEP_FLAG_HIDDEN | WEP_TYPE_SPLASH);
 /* rating    */ ATTRIB(Tuba, bot_pickupbasevalue, float, BOT_PICKUP_RATING_MID);
 /* color     */ ATTRIB(Tuba, wpcolor, vector, '0 1 0');
@@ -179,7 +179,7 @@ void W_Tuba_NoteOff(entity this)
                        }
                }
        }
-       remove(this);
+       delete(this);
 }
 
 int W_Tuba_GetNote(entity pl, int hittype)
@@ -309,12 +309,12 @@ void W_Tuba_NoteThink(entity this)
        });
 }
 
-void W_Tuba_NoteOn(entity actor, float hittype)
+void W_Tuba_NoteOn(entity actor, .entity weaponentity, float hittype)
 {
        vector o;
        float n;
 
-       W_SetupShot(actor, false, 2, SND_Null, 0, WEP_CVAR(tuba, damage));
+       W_SetupShot(actor, weaponentity, false, 2, SND_Null, 0, WEP_CVAR(tuba, damage));
 
        n = W_Tuba_GetNote(actor, hittype);
 
@@ -377,13 +377,13 @@ METHOD(Tuba, wr_think, void(Tuba this, entity actor, .entity weaponentity, int f
        if (fire & 1)
        if (weapon_prepareattack(this, actor, weaponentity, false, WEP_CVAR(tuba, refire)))
        {
-               W_Tuba_NoteOn(actor, 0);
+               W_Tuba_NoteOn(actor, weaponentity, 0);
                weapon_thinkf(actor, weaponentity, WFRAME_IDLE, WEP_CVAR(tuba, animtime), w_ready);
        }
        if (fire & 2)
        if (weapon_prepareattack(this, actor, weaponentity, true, WEP_CVAR(tuba, refire)))
        {
-               W_Tuba_NoteOn(actor, HITTYPE_SECONDARY);
+               W_Tuba_NoteOn(actor, weaponentity, HITTYPE_SECONDARY);
                weapon_thinkf(actor, weaponentity, WFRAME_IDLE, WEP_CVAR(tuba, animtime), w_ready);
        }
        if (actor.tuba_note)
@@ -448,7 +448,7 @@ METHOD(Tuba, wr_reload, void(Tuba this, entity actor, .entity weaponentity))
                                break;
                }
                tuba_instrument_send(actor, actor.tuba_instrument);
-               W_SetupShot(actor, false, 0, SND_Null, 0, 0);
+               W_SetupShot(actor, weaponentity, false, 0, SND_Null, 0, 0);
                Send_Effect(EFFECT_TELEPORT, w_shotorg, '0 0 0', 1);
                actor.(weaponentity).state = WS_INUSE;
                weapon_thinkf(actor, weaponentity, WFRAME_RELOAD, 0.5, w_ready);
@@ -563,9 +563,9 @@ void Ent_TubaNote_Think(entity this)
                sound(this, CH_TUBA_SINGLE, SND_Null, 0, 0);
                if (this.enemy) {
                        sound(this.enemy, CH_TUBA_SINGLE, SND_Null, 0, 0);
-                       remove(this.enemy);
+                       delete(this.enemy);
                }
-               remove(this);
+               delete(this);
        } else {
                tubasound(this, 0);
        }
@@ -643,7 +643,7 @@ PRECACHE(Tuba)
        Tuba_PitchStep = autocvar_g_balance_tuba_pitchstep;
        if (Tuba_PitchStep) {
                if (!checkextension("DP_SND_SOUND7_WIP2") && !checkextension("DP_SND_SOUND7")) {
-                       LOG_WARNING("requested pitch shifting, but not supported by this engine build");
+                       LOG_WARN("requested pitch shifting, but not supported by this engine build");
                        Tuba_PitchStep = 0;
                }
        }
index 8a8e858ecb5ce197e1ce6b1a55ade7e718c85cbc..8fa43c1d8c019e73f209a081a778f9c7950b0687 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef IMPLEMENTATION
 CLASS(Vaporizer, Weapon)
-/* ammotype  */ ATTRIB(Vaporizer, ammo_field, .int, ammo_cells)
-/* impulse   */ ATTRIB(Vaporizer, impulse, int, 7)
+/* ammotype  */ ATTRIB(Vaporizer, ammo_field, .int, ammo_cells);
+/* impulse   */ ATTRIB(Vaporizer, impulse, int, 7);
 /* flags     */ ATTRIB(Vaporizer, spawnflags, int, WEP_FLAG_RELOADABLE | WEP_FLAG_CANCLIMB | WEP_FLAG_SUPERWEAPON | WEP_TYPE_HITSCAN);
 /* rating    */ ATTRIB(Vaporizer, bot_pickupbasevalue, float, BOT_PICKUP_RATING_HIGH);
 /* color     */ ATTRIB(Vaporizer, wpcolor, vector, '0.5 1 1');
@@ -158,7 +158,7 @@ NET_HANDLE(TE_CSQC_VAPORBEAMPARTICLE, bool isNew)
                WarpZone_TrailParticles(NULL, particleeffectnum(((this.cnt) ? EFFECT_VAPORIZER_HIT(this.team) : EFFECT_VAPORIZER(this.team))), this.vorg1, this.vorg2);
                this.draw = func_null;
                this.drawmask = MASK_NORMAL;
-               remove(this);
+               delete(this);
        }
 
        return true;
@@ -177,15 +177,15 @@ void W_RocketMinsta_Explosion(entity actor, vector loc)
        dmgent.owner = dmgent.realowner = actor;
        setorigin(dmgent, loc);
        RadiusDamage (dmgent, actor, autocvar_g_rm_damage, autocvar_g_rm_edgedamage, autocvar_g_rm_radius, NULL, NULL, autocvar_g_rm_force, WEP_DEVASTATOR.m_id | HITTYPE_SPLASH, other);
-       remove(dmgent);
+       delete(dmgent);
 }
 
-void W_Vaporizer_Attack(Weapon thiswep, entity actor)
+void W_Vaporizer_Attack(Weapon thiswep, entity actor, .entity weaponentity)
 {
        bool flying = IsFlying(actor); // do this BEFORE to make the trace values from FireRailgunBullet last
        float vaporizer_damage = ((WEP_CVAR_PRI(vaporizer, damage) > 0) ? WEP_CVAR_PRI(vaporizer, damage) : 10000);
 
-       W_SetupShot(actor, true, 0, SND_Null, CH_WEAPON_A, vaporizer_damage);
+       W_SetupShot(actor, weaponentity, true, 0, SND_Null, CH_WEAPON_A, vaporizer_damage);
        // handle sound separately so we can change the volume
        // added bonus: no longer plays the strength sound (strength gives no bonus to instakill anyway)
        sound (actor, CH_WEAPON_A, SND_MINSTANEXFIRE, VOL_BASE * 0.8, ATTEN_NORM);
@@ -226,7 +226,7 @@ void W_RocketMinsta_Laser_Explode (entity this)
        this.event_damage = func_null;
        this.takedamage = DAMAGE_NO;
        RadiusDamage (this, this.realowner, this.rm_damage, this.rm_edmg, autocvar_g_rm_laser_radius, NULL, NULL, this.rm_force, this.projectiledeathtype, other);
-       remove(this);
+       delete(this);
 }
 
 void W_RocketMinsta_Laser_Explode_use(entity this, entity actor, entity trigger)
@@ -239,10 +239,10 @@ void W_RocketMinsta_Laser_Touch(entity this, entity toucher)
        PROJECTILE_TOUCH(this, toucher);
        //W_RocketMinsta_Laser_Explode ();
        RadiusDamage(this, this.realowner, this.rm_damage, this.rm_edmg, autocvar_g_rm_laser_radius, NULL, NULL, this.rm_force, this.projectiledeathtype, toucher);
-       remove(this);
+       delete(this);
 }
 
-void W_RocketMinsta_Attack2(entity actor)
+void W_RocketMinsta_Attack2(entity actor, .entity weaponentity)
 {
        makevectors(actor.v_angle);
 
@@ -254,7 +254,7 @@ void W_RocketMinsta_Attack2(entity actor)
 
        Weapon w = PS(actor).m_weapon;
        PS(actor).m_weapon = WEP_ELECTRO;
-       W_SetupShot_ProjectileSize (actor, '0 0 -3', '0 0 -3', false, 2, SND_CRYLINK_FIRE, CH_WEAPON_A, autocvar_g_rm_laser_damage);
+       W_SetupShot_ProjectileSize (actor, weaponentity, '0 0 -3', '0 0 -3', false, 2, SND_CRYLINK_FIRE, CH_WEAPON_A, autocvar_g_rm_laser_damage);
        PS(actor).m_weapon = w;
 
        Send_Effect(EFFECT_ELECTRO_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
@@ -287,6 +287,7 @@ void W_RocketMinsta_Attack2(entity actor)
         settouch(proj, W_RocketMinsta_Laser_Touch);
         setsize(proj, '0 0 -3', '0 0 -3');
         proj.flags = FL_PROJECTILE;
+        IL_PUSH(g_projectiles, proj);
         proj.missile_flags = MIF_SPLASH;
 
         CSQCProjectile(proj, true, PROJECTILE_ROCKETMINSTA_LASER, true);
@@ -296,7 +297,7 @@ void W_RocketMinsta_Attack2(entity actor)
     }
 }
 
-void W_RocketMinsta_Attack3 (entity actor)
+void W_RocketMinsta_Attack3 (entity actor, .entity weaponentity)
 {
        makevectors(actor.v_angle);
 
@@ -306,7 +307,7 @@ void W_RocketMinsta_Attack3 (entity actor)
 
        Weapon w = PS(actor).m_weapon;
        PS(actor).m_weapon = WEP_ELECTRO;
-       W_SetupShot_ProjectileSize (actor, '0 0 -3', '0 0 -3', false, 2, SND_ELECTRO_FIRE2, CH_WEAPON_A, autocvar_g_rm_laser_damage);
+       W_SetupShot_ProjectileSize (actor, weaponentity, '0 0 -3', '0 0 -3', false, 2, SND_ELECTRO_FIRE2, CH_WEAPON_A, autocvar_g_rm_laser_damage);
        PS(actor).m_weapon = w;
 
        Send_Effect(EFFECT_ELECTRO_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
@@ -337,6 +338,7 @@ void W_RocketMinsta_Attack3 (entity actor)
         settouch(proj, W_RocketMinsta_Laser_Touch);
         setsize(proj, '0 0 -3', '0 0 -3');
         proj.flags = FL_PROJECTILE;
+        IL_PUSH(g_projectiles, proj);
         proj.missile_flags = MIF_SPLASH;
 
         CSQCProjectile(proj, true, PROJECTILE_ROCKETMINSTA_LASER, true);
@@ -366,7 +368,7 @@ METHOD(Vaporizer, wr_think, void(entity thiswep, entity actor, .entity weaponent
     {
         if(weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR_PRI(vaporizer, refire)))
         {
-            W_Vaporizer_Attack(thiswep, actor);
+            W_Vaporizer_Attack(thiswep, actor, weaponentity);
             weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_PRI(vaporizer, animtime), w_ready);
         }
     }
@@ -382,13 +384,13 @@ METHOD(Vaporizer, wr_think, void(entity thiswep, entity actor, .entity weaponent
                 actor.jump_interval = time + autocvar_g_rm_laser_refire;
                 actor.jump_interval2 = time + autocvar_g_rm_laser_rapid_delay;
                 damage_goodhits = 0;
-                W_RocketMinsta_Attack2(actor);
+                W_RocketMinsta_Attack2(actor, weaponentity);
             }
             else if(rapid && actor.jump_interval2 <= time && actor.held_down)
             {
                 actor.jump_interval2 = time + autocvar_g_rm_laser_rapid_refire;
                 damage_goodhits = 0;
-                W_RocketMinsta_Attack3(actor);
+                W_RocketMinsta_Attack3(actor, weaponentity);
                 //weapon_thinkf(actor, WFRAME_FIRE2, autocvar_g_rm_laser_rapid_animtime, w_ready);
             }
         }
@@ -407,6 +409,7 @@ METHOD(Vaporizer, wr_think, void(entity thiswep, entity actor, .entity weaponent
             PS(actor).m_weapon = WEP_BLASTER;
             W_Blaster_Attack(
                 actor,
+                weaponentity,
                 WEP_BLASTER.m_id | HITTYPE_SECONDARY,
                 WEP_CVAR_SEC(vaporizer, shotangle),
                 WEP_CVAR_SEC(vaporizer, damage),
@@ -460,7 +463,7 @@ METHOD(Vaporizer, wr_reload, void(entity thiswep, entity actor, .entity weaponen
     else
         used_ammo = vaporizer_ammo;
 
-    W_Reload(actor, used_ammo, SND_RELOAD);
+    W_Reload(actor, weaponentity, used_ammo, SND_RELOAD);
 }
 METHOD(Vaporizer, wr_suicidemessage, Notification(entity thiswep))
 {
index 640cd2c402f325769a8cfb86c16f14b4e8a75429..0ca635b3ee32f1e21b8d996117c19bac39858ab8 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef IMPLEMENTATION
 CLASS(Vortex, Weapon)
-/* ammotype  */ ATTRIB(Vortex, ammo_field, .int, ammo_cells)
-/* impulse   */ ATTRIB(Vortex, impulse, int, 7)
+/* ammotype  */ ATTRIB(Vortex, ammo_field, .int, ammo_cells);
+/* impulse   */ ATTRIB(Vortex, impulse, int, 7);
 /* flags     */ ATTRIB(Vortex, spawnflags, int, WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_TYPE_HITSCAN);
 /* rating    */ ATTRIB(Vortex, bot_pickupbasevalue, float, BOT_PICKUP_RATING_HIGH);
 /* color     */ ATTRIB(Vortex, wpcolor, vector, '0.5 1 1');
@@ -157,7 +157,7 @@ MUTATOR_HOOKFUNCTION(vortex_charge, GetPressedKeys)
        }
 }
 
-void W_Vortex_Attack(Weapon thiswep, entity actor, float issecondary)
+void W_Vortex_Attack(Weapon thiswep, entity actor, .entity weaponentity, float issecondary)
 {
        float mydmg, myforce, mymindist, mymaxdist, myhalflife, myforcehalflife, myammo, charge;
 
@@ -184,7 +184,7 @@ void W_Vortex_Attack(Weapon thiswep, entity actor, float issecondary)
        mydmg *= charge;
        myforce *= charge;
 
-       W_SetupShot(actor, true, 5, SND_NEXFIRE, CH_WEAPON_A, mydmg);
+       W_SetupShot(actor, weaponentity, true, 5, SND_NEXFIRE, CH_WEAPON_A, mydmg);
        if(charge > WEP_CVAR(vortex, charge_animlimit) && WEP_CVAR(vortex, charge_animlimit)) // if the Vortex is overcharged, we play an extra sound
        {
                sound(actor, CH_WEAPON_B, SND_NEXCHARGE, VOL_BASE * (charge - 0.5 * WEP_CVAR(vortex, charge_animlimit)) / (1 - 0.5 * WEP_CVAR(vortex, charge_animlimit)), ATTN_NORM);
@@ -243,7 +243,7 @@ METHOD(Vortex, wr_think, void(entity thiswep, entity actor, .entity weaponentity
         {
             if(weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR_PRI(vortex, refire)))
             {
-                W_Vortex_Attack(thiswep, actor, 0);
+                W_Vortex_Attack(thiswep, actor, weaponentity, 0);
                 weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_PRI(vortex, animtime), w_ready);
             }
         }
@@ -315,7 +315,7 @@ METHOD(Vortex, wr_think, void(entity thiswep, entity actor, .entity weaponentity
             {
                 if(weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR_SEC(vortex, refire)))
                 {
-                    W_Vortex_Attack(thiswep, actor, 1);
+                    W_Vortex_Attack(thiswep, actor, weaponentity, 1);
                     weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_SEC(vortex, animtime), w_ready);
                 }
             }
@@ -358,7 +358,7 @@ METHOD(Vortex, wr_resetplayer, void(entity thiswep, entity actor))
 }
 METHOD(Vortex, wr_reload, void(entity thiswep, entity actor, .entity weaponentity))
 {
-    W_Reload(actor, min(WEP_CVAR_PRI(vortex, ammo), WEP_CVAR_SEC(vortex, ammo)), SND_RELOAD);
+    W_Reload(actor, weaponentity, min(WEP_CVAR_PRI(vortex, ammo), WEP_CVAR_SEC(vortex, ammo)), SND_RELOAD);
 }
 METHOD(Vortex, wr_suicidemessage, Notification(entity thiswep))
 {
index f424d1a5de4dcfec5323851cabb41a712eed6adb..29d797585efbe10117995db27925b739109abae6 100644 (file)
@@ -1,5 +1,4 @@
-#ifndef CSPROGSDEFS_H
-#define CSPROGSDEFS_H
+#pragma once
 
 #pragma noref 1
 
@@ -44,5 +43,3 @@
 #define use use1
 .void(entity this, entity actor, entity trigger) use;
 #define touch move_touch
-
-#endif
index 240eec0c1cf5d7fd1f8a79e170eb407917347e06..b49bb6f57ad72e7ab0ff6bed1b20925d6e26362a 100644 (file)
@@ -55,6 +55,21 @@ float sound_starttime;
 
 # SVQC
 
+Main loop:
+* SV_Physics()
+    * StartFrame()
+    * if (force_retouch)
+        * foreach entity:
+            * .touch()
+    * foreach client:
+        * PlayerPreThink()
+        * .think()
+        * PlayerPostThink()
+    * foreach nonclient:
+        * .think()
+    * EndFrame()
+
+
 ```
 
 .entity clientcamera;
@@ -199,6 +214,10 @@ void SV_PlayerPhysics();
 //   self
 void SV_ParseClientCommand(string cmd);
 
+// qcstatus server field
+string worldstatus;
+.string clientstatus;
+
 ```
 
 # MENUQC
index ff9214844b3e5c181878b7ef31c40621e85a59e3..2ed0f9063889af40f2270740e069f47d29f62789 100644 (file)
@@ -1,5 +1,4 @@
-#ifndef DPEXTENSIONS_H
-#define DPEXTENSIONS_H
+#pragma once
 
 #pragma noref 1
 
@@ -64,5 +63,3 @@ int() _buf_create = #460;
 #define buf_create _buf_create
 
 #pragma noref 0
-
-#endif
index f4c49f143b5c119cd3dbb1a7c434a53d701bf681..0267be882462d75055d6bf8bf6ed5b153bc7493c 100644 (file)
@@ -1,5 +1,4 @@
-#ifndef KEYCODES_H
-#define KEYCODES_H
+#pragma once
 
 #pragma noref 1
 
@@ -10,5 +9,3 @@
 //#undef float
 
 #pragma noref 0
-
-#endif
index 939a86adb359c502e8ddc767da306077ec6256f7..036d87ff2fa8e7a213932d69fc66e84e30700a94 100644 (file)
@@ -1,5 +1,4 @@
-#ifndef MENUDEFS_H
-#define MENUDEFS_H
+#pragma once
 
 #pragma noref 1
 
@@ -43,5 +42,3 @@ int() _buf_create = #440;
 bool(entity ent) wasfreed = #353;
 
 #pragma noref 0
-
-#endif
index e2668a54b7cc5173d2aad78b1b4681f0a54fbc30..ccdf9bc0c4293353a7e8392b059831e313474958 100644 (file)
@@ -1,5 +1,4 @@
-#ifndef PROGSDEFS_H
-#define PROGSDEFS_H
+#pragma once
 
 #pragma noref 1
 
@@ -30,5 +29,3 @@ MACRO_END
 
 #define use use1
 .void(entity this, entity actor, entity trigger) use;
-
-#endif
index 9fd6ad6948ac5e7b2501d338ea2b0f338743759c..d49094f7b48c68019752dd871f46ee360bd7478e 100644 (file)
@@ -44,5 +44,4 @@
 ### listening
 
     entity listener = new_pure(someListener);
-    listener.evt_$event = void(entity this) { code; };
-    subscribe(listener, $event);
+    subscribe(listener, $event, void(entity this) { code; });
index 32db1f3d3e6cb1f1b0a4f7672dfc1a058d522f07..726f693e9e8149e36ce0af9c29c6d81942c40382 100644 (file)
@@ -1,58 +1,4 @@
-/** Components always interpolate from the previous state */
-#define COMPONENT(com) \
-       void com_##com##_interpolate(entity it, float a); \
-       .bool com_##com
-
-#define FOREACH_COMPONENT(com, body) FOREACH_ENTITY_FLOAT(com_##com, true, body)
-
-
-#define EVENT(T, args) .bool evt_##T##_listener; .void args evt_##T
-
-#define emit(T, ...) \
-       MACRO_BEGIN \
-       FOREACH_ENTITY_FLOAT_ORDERED(evt_##T##_listener, true, it.evt_##T(__VA_ARGS__)); \
-       MACRO_END
-
-#define subscribe(listener, T) \
-       MACRO_BEGIN \
-       listener.evt_##T##_listener = true; \
-       MACRO_END
-
-
-/**
- * framelimit 0 is no limit, interpolation does not apply
- * framerate below minfps will result in less than 100% speed
- */
-#define SYSTEM(sys, frameLimit, minfps) \
-       void sys_##sys##_update(entity this, float dt); \
-       float autocvar_xon_sys_##sys##_dt = ((frameLimit) ? (1 / (frameLimit)) : 0); \
-       float autocvar_xon_sys_##sys##_minfps = (1 / (1 / (minfps)))
-
-#define SYSTEM_UPDATE(sys) \
-       MACRO_BEGIN \
-       static float t = 0; \
-       float dt = autocvar_xon_sys_##sys##_dt; \
-       float minfps = autocvar_xon_sys_##sys##_minfps; \
-       static float accumulator = 0; \
-       float a = 0; \
-       if (dt) { \
-               accumulator += min(frametime, 1 / (minfps)); \
-       } else { \
-               accumulator += frametime; \
-               dt = accumulator; \
-               a = 1; \
-       } \
-       while (accumulator >= dt) \
-       { \
-               time = t; \
-               FOREACH_COMPONENT(sys, sys_##sys##_update(it, dt)); \
-               t += dt; \
-               accumulator -= dt; \
-       } \
-       if (!a) a = accumulator / dt; \
-       FOREACH_COMPONENT(sys, com_##sys##_interpolate(it, a)); \
-       MACRO_END
-
+#include "_lib.qh"
 
 #include "_mod.inc"
 #include "components/_mod.inc"
diff --git a/qcsrc/ecs/_lib.qh b/qcsrc/ecs/_lib.qh
new file mode 100644 (file)
index 0000000..a617c73
--- /dev/null
@@ -0,0 +1,57 @@
+#pragma once
+
+/** Components always interpolate from the previous state */
+#define COMPONENT(com) \
+       void com_##com##_interpolate(entity it, float a); \
+       .bool com_##com
+
+#define FOREACH_COMPONENT(com, body) FOREACH_ENTITY_FLOAT(com_##com, true, body)
+
+
+#define EVENT(T, args) .bool evt_##T##_listener; .void args evt_##T
+
+#define emit(T, ...) \
+       MACRO_BEGIN \
+       FOREACH_ENTITY_FLOAT_ORDERED(evt_##T##_listener, true, it.evt_##T(__VA_ARGS__)); \
+       MACRO_END
+
+#define subscribe(listener, T, fn) \
+       MACRO_BEGIN \
+       listener.evt_##T = (fn); \
+       listener.evt_##T##_listener = true; \
+       MACRO_END
+
+
+/**
+ * framelimit 0 is no limit, interpolation does not apply
+ * framerate below minfps will result in less than 100% speed
+ */
+#define SYSTEM(sys, frameLimit, minfps) \
+       void sys_##sys##_update(entity this, float dt); \
+       float autocvar_xon_sys_##sys##_dt = ((frameLimit) ? (1 / (frameLimit)) : 0); \
+       float autocvar_xon_sys_##sys##_minfps = (1 / (1 / (minfps)))
+
+#define SYSTEM_UPDATE(sys) \
+       MACRO_BEGIN \
+       static float t = 0; \
+       float dt = autocvar_xon_sys_##sys##_dt; \
+       float minfps = autocvar_xon_sys_##sys##_minfps; \
+       static float accumulator = 0; \
+       float a = 0; \
+       if (dt) { \
+               accumulator += min(frametime, 1 / (minfps)); \
+       } else { \
+               accumulator += frametime; \
+               dt = accumulator; \
+               a = 1; \
+       } \
+       while (accumulator >= dt) \
+       { \
+               time = t; \
+               FOREACH_COMPONENT(sys, sys_##sys##_update(it, dt)); \
+               t += dt; \
+               accumulator -= dt; \
+       } \
+       if (!a) a = accumulator / dt; \
+       FOREACH_COMPONENT(sys, com_##sys##_interpolate(it, a)); \
+       MACRO_END
index 37944ca5c3f8d026ce1ae1b5a7c9da7188ec5b08..bc1c66ace4cb1746ed0b723bcfa1d7dcb4b6374a 100644 (file)
@@ -1,6 +1,7 @@
 #pragma once
 
 COMPONENT(in);
-.vector com_in_move;
+.vector com_in_move, com_in_move_prev;
 .vector com_in_angles;
 .bool   com_in_jump;
+.bool   com_in_crouch;
index 502657e4bcbeb52db0fa319c1c41161a21f13480..f150a296c299e8d46980c1ba2d4fb278665947d4 100644 (file)
@@ -4,4 +4,23 @@ COMPONENT(phys);
 .vector com_phys_pos, com_phys_pos_prev;
 .vector com_phys_ang, com_phys_ang_prev;
 .vector com_phys_vel;
+.float com_phys_vel_max;
+.float com_phys_vel_max_air;
+.float com_phys_vel_max_air_strafe;
 .vector com_phys_acc;
+.float com_phys_acc_rate;
+.float com_phys_acc_rate_air;
+.float com_phys_acc_rate_air_strafe;
+.float com_phys_acc_rate_air_stop;
+.float com_phys_friction;
+
+.vector com_phys_gravity;
+.float com_phys_gravity_factor;
+// TODO: remove
+.bool com_phys_ground;
+.bool com_phys_air;
+.bool com_phys_ladder;
+.bool com_phys_vel_2d;
+.bool com_phys_water;
+.bool com_phys_friction_air;
+.bool move_qcphysics;
index 98fb4815c1ce28cc699a429537ea75c2643b4487..c139d72b51ed4738fb396b3407fd335324cd921a 100644 (file)
@@ -1 +1,2 @@
 // generated file; do not modify
+#include <ecs/events/physics.qc>
index 98fb4815c1ce28cc699a429537ea75c2643b4487..1e8c791ce9b403aafc843acd2e95b6aebff0e082 100644 (file)
@@ -1 +1,2 @@
 // generated file; do not modify
+#include <ecs/events/physics.qh>
diff --git a/qcsrc/ecs/events/physics.qc b/qcsrc/ecs/events/physics.qc
new file mode 100644 (file)
index 0000000..909f45c
--- /dev/null
@@ -0,0 +1 @@
+#include "physics.qh"
diff --git a/qcsrc/ecs/events/physics.qh b/qcsrc/ecs/events/physics.qh
new file mode 100644 (file)
index 0000000..df32c55
--- /dev/null
@@ -0,0 +1,3 @@
+#pragma once
+
+EVENT(phys_land, (entity this));
index f79d7f065134aaff00519783a734cb1bba4ea8b7..a5ada6cfbed8684281f77a42c6ee4b24c0c161bd 100644 (file)
@@ -1,2 +1,9 @@
 // generated file; do not modify
+#include <ecs/systems/input.qc>
 #include <ecs/systems/physics.qc>
+#ifdef CSQC
+    #include <ecs/systems/cl_physics.qc>
+#endif
+#ifdef SVQC
+    #include <ecs/systems/sv_physics.qc>
+#endif
index e71e0591c747dfe996fa2295a73d1b363ac395dc..869aefd5571e4907ba47f65867eb415a276f6767 100644 (file)
@@ -1,2 +1,3 @@
 // generated file; do not modify
+#include <ecs/systems/input.qh>
 #include <ecs/systems/physics.qh>
diff --git a/qcsrc/ecs/systems/cl_physics.qc b/qcsrc/ecs/systems/cl_physics.qc
new file mode 100644 (file)
index 0000000..f90afcb
--- /dev/null
@@ -0,0 +1,30 @@
+#include "physics.qh"
+
+void sys_phys_fix(entity this, float dt)
+{
+       this.team = myteam + 1; // is this correct?
+       PHYS_WATERJUMP_TIME(this) -= dt;
+       this.oldmovement = this.movement;
+       this.movement = PHYS_INPUT_MOVEVALUES(this);
+       this.items = STAT(ITEMS, this);
+       this.spectatorspeed = STAT(SPECTATORSPEED, this);
+       if (!(PHYS_INPUT_BUTTON_JUMP(this))) // !jump
+               UNSET_JUMP_HELD(this);           // canjump = true
+       PM_ClientMovement_UpdateStatus(this);
+}
+
+bool sys_phys_override(entity this, float dt)
+{
+       // no vehicle prediction
+       return hud != HUD_NORMAL;
+}
+
+void sys_phys_monitor(entity this, float dt) {}
+
+void sys_phys_ai(entity this) {}
+
+void sys_phys_pregame_hold(entity this) {}
+
+void sys_phys_spectator_control(entity this) {}
+
+void sys_phys_fixspeed(entity this, float maxspeed_mod) {}
diff --git a/qcsrc/ecs/systems/input.qc b/qcsrc/ecs/systems/input.qc
new file mode 100644 (file)
index 0000000..eac3625
--- /dev/null
@@ -0,0 +1,7 @@
+#include "input.qh"
+
+void sys_in_update(entity this, float dt)
+{
+       this.com_in_jump = PHYS_INPUT_BUTTON_JUMP(this);
+       this.com_in_crouch = PHYS_INPUT_BUTTON_CROUCH(this);
+}
diff --git a/qcsrc/ecs/systems/input.qh b/qcsrc/ecs/systems/input.qh
new file mode 100644 (file)
index 0000000..fc3f11a
--- /dev/null
@@ -0,0 +1,3 @@
+#pragma once
+
+SYSTEM(in, 30, 10);
index 8348b87851cc82f8e3bf6999d54bd01a6246116b..c0a47e39b2a4aff558c3c53af50d49694d6c01f7 100644 (file)
@@ -1,6 +1,491 @@
 #include "physics.qh"
+#include "input.qh"
+
+.int disableclientprediction;
+
+void sys_phys_simulate(entity this, float dt);
+void sys_phys_simulate_simple(entity this, float dt);
 
 void sys_phys_update(entity this, float dt)
 {
-       PM_Main(this);
+       if (!IS_CLIENT(this)) {
+               sys_phys_simulate_simple(this, dt);
+               return;
+       }
+       sys_in_update(this, dt);
+
+       sys_phys_fix(this, dt);
+       if (sys_phys_override(this, dt)) { return; } sys_phys_monitor(this, dt);
+
+       this.buttons_old = PHYS_INPUT_BUTTON_MASK(this);
+       this.movement_old = this.movement;
+       this.v_angle_old = this.v_angle;
+
+       sys_phys_ai(this);
+
+       sys_phys_pregame_hold(this);
+
+       if (IS_SVQC) {
+               if (this.move_movetype == MOVETYPE_NONE) { return; }
+               // when we get here, disableclientprediction cannot be 2
+               this.disableclientprediction = (this.move_qcphysics) ? -1 : 0;
+       }
+
+       viewloc_PlayerPhysics(this);
+
+       PM_check_frozen(this);
+
+       PM_check_blocked(this);
+
+       float maxspeed_mod = (!this.in_swamp) ? 1 : this.swamp_slowdown;  // cvar("g_balance_swamp_moverate");
+
+// conveyors: first fix velocity
+       if (this.conveyor.state) { this.velocity -= this.conveyor.movedir; }
+       MUTATOR_CALLHOOK(PlayerPhysics, this, dt);
+
+       if (!IS_PLAYER(this)) {
+               sys_phys_spectator_control(this);
+               maxspeed_mod = this.spectatorspeed;
+       }
+       sys_phys_fixspeed(this, maxspeed_mod);
+
+       if (IS_DEAD(this)) {
+               // handle water here
+               vector midpoint = ((this.absmin + this.absmax) * 0.5);
+               if (pointcontents(midpoint) == CONTENT_WATER) {
+                       this.velocity = this.velocity * 0.5;
+
+                       // do we want this?
+                       // if(pointcontents(midpoint + '0 0 2') == CONTENT_WATER)
+                       // { this.velocity_z = 70; }
+               }
+               goto end;
+       }
+
+       if (IS_SVQC && !PHYS_FIXANGLE(this)) { this.angles = '0 1 0' * this.v_angle.y; }
+       if (IS_PLAYER(this)) {
+               if (IS_ONGROUND(this)) {
+                       PM_check_hitground(this);
+                       PM_Footsteps(this);
+               } else if (IsFlying(this)) {
+                       this.wasFlying = true;
+               }
+               CheckPlayerJump(this);
+       }
+
+       if (this.flags & FL_WATERJUMP) {
+               this.velocity_x = this.movedir.x;
+               this.velocity_y = this.movedir.y;
+               if (this.waterlevel == WATERLEVEL_NONE
+                   || time > PHYS_TELEPORT_TIME(this)
+                   || PHYS_WATERJUMP_TIME(this) <= 0
+                  ) {
+                       this.flags &= ~FL_WATERJUMP;
+                       PHYS_TELEPORT_TIME(this) = 0;
+                       PHYS_WATERJUMP_TIME(this) = 0;
+               }
+       } else if (MUTATOR_CALLHOOK(PM_Physics, this, maxspeed_mod, dt)) {
+               // handled
+       } else if (this.move_movetype == MOVETYPE_NOCLIP
+           || this.move_movetype == MOVETYPE_FLY
+           || this.move_movetype == MOVETYPE_FLY_WORLDONLY
+           || MUTATOR_CALLHOOK(IsFlying, this)) {
+               this.com_phys_friction = PHYS_FRICTION(this);
+               this.com_phys_vel_max = PHYS_MAXSPEED(this) * maxspeed_mod;
+               this.com_phys_acc_rate = PHYS_ACCELERATE(this) * maxspeed_mod;
+               this.com_phys_friction_air = true;
+               sys_phys_simulate(this, dt);
+               this.com_phys_friction_air = false;
+       } else if (this.waterlevel >= WATERLEVEL_SWIMMING) {
+               this.com_phys_vel_max = PHYS_MAXSPEED(this) * maxspeed_mod;
+               this.com_phys_acc_rate = PHYS_ACCELERATE(this) * maxspeed_mod;
+               this.com_phys_water = true;
+               sys_phys_simulate(this, dt);
+               this.com_phys_water = false;
+       } else if (time < this.ladder_time) {
+               this.com_phys_friction = PHYS_FRICTION(this);
+               this.com_phys_vel_max = PHYS_MAXSPEED(this) * maxspeed_mod;
+               this.com_phys_acc_rate = PHYS_ACCELERATE(this) * maxspeed_mod;
+               this.com_phys_gravity = '0 0 -1' * PHYS_GRAVITY(this) * dt;
+               if (PHYS_ENTGRAVITY(this)) { this.com_phys_gravity *= PHYS_ENTGRAVITY(this); }
+               this.com_phys_ladder = true;
+               this.com_phys_friction_air = true;
+               sys_phys_simulate(this, dt);
+               this.com_phys_friction_air = false;
+               this.com_phys_ladder = false;
+               this.com_phys_gravity = '0 0 0';
+       } else if (ITEMS_STAT(this) & IT_USING_JETPACK) {
+               PM_jetpack(this, maxspeed_mod, dt);
+       } else if (IS_ONGROUND(this)) {
+               if (!WAS_ONGROUND(this)) {
+                       emit(phys_land, this);
+                       if (this.lastground < time - 0.3) {
+                               this.velocity *= (1 - PHYS_FRICTION_ONLAND(this));
+                       }
+               }
+               this.com_phys_vel_max = PHYS_MAXSPEED(this) * maxspeed_mod;
+               this.com_phys_gravity = '0 0 -1' * PHYS_GRAVITY(this) * dt;
+               if (PHYS_ENTGRAVITY(this)) { this.com_phys_gravity *= PHYS_ENTGRAVITY(this); }
+               this.com_phys_ground = true;
+               this.com_phys_vel_2d = true;
+               sys_phys_simulate(this, dt);
+               this.com_phys_vel_2d = false;
+               this.com_phys_ground = false;
+               this.com_phys_gravity = '0 0 0';
+       } else {
+               this.com_phys_acc_rate_air = PHYS_AIRACCELERATE(this) * min(maxspeed_mod, 1);
+               this.com_phys_acc_rate_air_stop = PHYS_AIRSTOPACCELERATE(this) * maxspeed_mod;
+               this.com_phys_acc_rate_air_strafe = PHYS_AIRSTRAFEACCELERATE(this) * maxspeed_mod;
+               this.com_phys_vel_max_air_strafe = PHYS_MAXAIRSTRAFESPEED(this) * maxspeed_mod;
+               this.com_phys_vel_max_air = PHYS_MAXAIRSPEED(this) * maxspeed_mod;
+               this.com_phys_vel_max = PHYS_MAXAIRSPEED(this) * min(maxspeed_mod, 1);
+               this.com_phys_air = true;
+               this.com_phys_vel_2d = true;
+               sys_phys_simulate(this, dt);
+               this.com_phys_vel_2d = false;
+               this.com_phys_air = false;
+       }
+
+       LABEL(end)
+       if (IS_ONGROUND(this)) { this.lastground = time; }
+// conveyors: then break velocity again
+       if (this.conveyor.state) { this.velocity += this.conveyor.movedir; }
+       this.lastflags = this.flags;
+
+       this.lastclassname = this.classname;
+}
+
+/** for players */
+void sys_phys_simulate(entity this, float dt)
+{
+       const vector g = -this.com_phys_gravity;
+       const bool jump = this.com_in_jump;
+
+       if (!this.com_phys_ground && !this.com_phys_air) {
+               // noclipping
+               // flying
+               // on a spawnfunc_func_ladder
+               // swimming in spawnfunc_func_water
+               // swimming
+               UNSET_ONGROUND(this);
+
+               if (this.com_phys_friction_air) {
+                       this.velocity_z += g.z / 2;
+                       this.velocity = this.velocity * (1 - dt * this.com_phys_friction);
+                       this.velocity_z += g.z / 2;
+               }
+       }
+
+       if (this.com_phys_water) {
+               // water jump only in certain situations
+               // this mimics quakeworld code
+               if (jump && this.waterlevel == WATERLEVEL_SWIMMING && this.velocity_z >= -180 && !this.viewloc) {
+                       vector yawangles = '0 1 0' * this.v_angle.y;
+                       makevectors(yawangles);
+                       vector forward = v_forward;
+                       vector spot = this.origin + 24 * forward;
+                       spot_z += 8;
+                       traceline(spot, spot, MOVE_NOMONSTERS, this);
+                       if (trace_startsolid) {
+                               spot_z += 24;
+                               traceline(spot, spot, MOVE_NOMONSTERS, this);
+                               if (!trace_startsolid) {
+                                       this.velocity = forward * 50;
+                                       this.velocity_z = 310;
+                                       UNSET_ONGROUND(this);
+                                       SET_JUMP_HELD(this);
+                               }
+                       }
+               }
+       }
+       makevectors(vmul(this.v_angle, (this.com_phys_vel_2d ? '0 1 0' : '1 1 1')));
+       // wishvel = v_forward * this.movement.x + v_right * this.movement.y + v_up * this.movement.z;
+       vector wishvel = v_forward * this.movement.x
+           + v_right * this.movement.y
+           + '0 0 1' * this.movement.z * (this.com_phys_vel_2d ? 0 : 1);
+       if (this.com_phys_water) {
+               if (PHYS_INPUT_BUTTON_CROUCH(this)) {
+                       wishvel.z = -PHYS_MAXSPEED(this);
+               }
+               if (this.viewloc) {
+                       wishvel.z = -160;    // drift anyway
+               } else if (wishvel == '0 0 0') {
+                       wishvel = '0 0 -60'; // drift towards bottom
+               }
+       }
+       if (this.com_phys_ladder) {
+               if (this.viewloc) {
+                       wishvel.z = this.oldmovement.x;
+               }
+               if (this.ladder_entity.classname == "func_water") {
+                       float f = vlen(wishvel);
+                       if (f > this.ladder_entity.speed) {
+                               wishvel *= (this.ladder_entity.speed / f);
+                       }
+
+                       this.watertype = this.ladder_entity.skin;
+                       f = this.ladder_entity.origin_z + this.ladder_entity.maxs_z;
+                       if ((this.origin_z + this.view_ofs_z) < f) {
+                               this.waterlevel = WATERLEVEL_SUBMERGED;
+                       } else if ((this.origin_z + (this.mins_z + this.maxs_z) * 0.5) < f) {
+                               this.waterlevel = WATERLEVEL_SWIMMING;
+                       } else if ((this.origin_z + this.mins_z + 1) < f) {
+                               this.waterlevel = WATERLEVEL_WETFEET;
+                       } else {
+                               this.waterlevel = WATERLEVEL_NONE;
+                               this.watertype = CONTENT_EMPTY;
+                       }
+               }
+       }
+       // acceleration
+       const vector wishdir = normalize(wishvel);
+       float wishspeed = min(vlen(wishvel), this.com_phys_vel_max);
+
+       if (this.com_phys_air) {
+               if ((IS_SVQC && time >= PHYS_TELEPORT_TIME(this))
+                   ||  (IS_CSQC && PHYS_WATERJUMP_TIME(this) <= 0)) {
+                       // apply air speed limit
+                       float airaccelqw = PHYS_AIRACCEL_QW(this);
+                       float wishspeed0 = wishspeed;
+                       const float maxairspd = this.com_phys_vel_max;
+                       wishspeed = min(wishspeed, maxairspd);
+                       if (IS_DUCKED(this)) {
+                               wishspeed *= 0.5;
+                       }
+                       float airaccel = this.com_phys_acc_rate_air;
+
+                       float accelerating = (this.velocity * wishdir > 0);
+                       float wishspeed2 = wishspeed;
+
+                       // CPM: air control
+                       if (PHYS_AIRSTOPACCELERATE(this)) {
+                               vector curdir = normalize(vec2(this.velocity));
+                               airaccel += (this.com_phys_acc_rate_air_stop - airaccel) * max(0, -(curdir * wishdir));
+                       }
+                       // note that for straight forward jumping:
+                       // step = accel * dt * 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(this.movement, -90) + IsMoveInDirection(this.movement, +90);  // if one is nonzero, other is always zero
+                       if (PHYS_MAXAIRSTRAFESPEED(this)) {
+                               wishspeed =
+                                   min(wishspeed,
+                                       GeomLerp(this.com_phys_vel_max_air, strafity, this.com_phys_vel_max_air_strafe));
+                       }
+                       if (PHYS_AIRSTRAFEACCELERATE(this)) {
+                               airaccel = GeomLerp(airaccel, strafity, this.com_phys_acc_rate_air_strafe);
+                       }
+                       if (PHYS_AIRSTRAFEACCEL_QW(this)) {
+                               airaccelqw =
+                                   (((strafity > 0.5 ? PHYS_AIRSTRAFEACCEL_QW(this) : PHYS_AIRACCEL_QW(this)) >= 0) ? +1 : -1)
+                                   *
+                                   (1 - GeomLerp(1 - fabs(PHYS_AIRACCEL_QW(this)), strafity, 1 - fabs(PHYS_AIRSTRAFEACCEL_QW(this))));
+                       }
+                       // !CPM
+
+                       if (PHYS_WARSOWBUNNY_TURNACCEL(this) && accelerating && this.movement.y == 0 && this.movement.x != 0) {
+                               PM_AirAccelerate(this, dt, wishdir, wishspeed2);
+                       } else {
+                               float sidefric = maxairspd ? (PHYS_AIRACCEL_SIDEWAYS_FRICTION(this) / maxairspd) : 0;
+                               PM_Accelerate(this, dt, wishdir, wishspeed, wishspeed0, airaccel, airaccelqw,
+                                       PHYS_AIRACCEL_QW_STRETCHFACTOR(this), sidefric, PHYS_AIRSPEEDLIMIT_NONQW(this));
+                       }
+
+                       if (PHYS_AIRCONTROL(this)) {
+                               CPM_PM_Aircontrol(this, dt, wishdir, wishspeed2);
+                       }
+               }
+       } else {
+               if (this.com_phys_ground && IS_DUCKED(this)) { wishspeed *= 0.5; }
+               if (this.com_phys_water) {
+                       wishspeed *= 0.7;
+
+                       //      if (PHYS_WATERJUMP_TIME(this) <= 0) // TODO: use
+                       {
+                               // water friction
+                               float f = 1 - dt * PHYS_FRICTION(this);
+                               f = min(max(0, f), 1);
+                               this.velocity *= f;
+
+                               f = wishspeed - this.velocity * wishdir;
+                               if (f > 0) {
+                                       float accelspeed = min(PHYS_ACCELERATE(this) * dt * wishspeed, f);
+                                       this.velocity += accelspeed * wishdir;
+                               }
+
+                               // holding jump button swims upward slowly
+                               if (jump && !this.viewloc) {
+                                       // was:
+                                       // lava: 50
+                                       // slime: 80
+                                       // water: 100
+                                       // idea: double those
+                                       this.velocity_z = 200;
+                                       if (this.waterlevel >= WATERLEVEL_SUBMERGED) {
+                                               this.velocity_z = PHYS_MAXSPEED(this) * 0.7;
+                                       }
+                               }
+                       }
+                       if (this.viewloc) {
+                               const float addspeed = wishspeed - this.velocity * wishdir;
+                               if (addspeed > 0) {
+                                       const float accelspeed = min(PHYS_ACCELERATE(this) * dt * wishspeed, addspeed);
+                                       this.velocity += accelspeed * wishdir;
+                               }
+                       } else {
+                               // water acceleration
+                               PM_Accelerate(this, dt, wishdir, wishspeed, wishspeed, this.com_phys_acc_rate, 1, 0, 0, 0);
+                       }
+                       return;
+               }
+               if (this.com_phys_ground) {
+                       // apply edge friction
+                       const float f2 = vlen2(vec2(this.velocity));
+                       if (f2 > 0) {
+                               trace_dphitq3surfaceflags = 0;
+                               tracebox(this.origin, this.mins, this.maxs, this.origin - '0 0 1', MOVE_NOMONSTERS, this);
+                               // TODO: apply edge friction
+                               // apply ground friction
+                               const int realfriction = (trace_dphitq3surfaceflags & Q3SURFACEFLAG_SLICK)
+                                   ? PHYS_FRICTION_SLICK(this)
+                                       : PHYS_FRICTION(this);
+
+                               float f = sqrt(f2);
+                               f = 1 - dt * realfriction
+                                   * ((f < PHYS_STOPSPEED(this)) ? (PHYS_STOPSPEED(this) / f) : 1);
+                               f = max(0, f);
+                               this.velocity *= f;
+                               /*
+                                  Mathematical analysis time!
+
+                                  Our goal is to invert this mess.
+
+                                  For the two cases we get:
+                                   v = v0 * (1 - dt * (PHYS_STOPSPEED(this) / v0) * PHYS_FRICTION(this))
+                                     = v0 - dt * PHYS_STOPSPEED(this) * PHYS_FRICTION(this)
+                                   v0 = v + dt * PHYS_STOPSPEED(this) * PHYS_FRICTION(this)
+                                  and
+                                   v = v0 * (1 - dt * PHYS_FRICTION(this))
+                                   v0 = v / (1 - dt * PHYS_FRICTION(this))
+
+                                  These cases would be chosen ONLY if:
+                                   v0 < PHYS_STOPSPEED(this)
+                                   v + dt * PHYS_STOPSPEED(this) * PHYS_FRICTION(this) < PHYS_STOPSPEED(this)
+                                   v < PHYS_STOPSPEED(this) * (1 - dt * PHYS_FRICTION(this))
+                                  and, respectively:
+                                   v0 >= PHYS_STOPSPEED(this)
+                                   v / (1 - dt * PHYS_FRICTION(this)) >= PHYS_STOPSPEED(this)
+                                   v >= PHYS_STOPSPEED(this) * (1 - dt * PHYS_FRICTION(this))
+                                */
+                       }
+                       const float addspeed = wishspeed - this.velocity * wishdir;
+                       if (addspeed > 0) {
+                               const float accelspeed = min(PHYS_ACCELERATE(this) * dt * wishspeed, addspeed);
+                               this.velocity += accelspeed * wishdir;
+                       }
+                       return;
+               }
+
+               if (IS_CSQC ? PHYS_WATERJUMP_TIME(this) <= 0 : time >= PHYS_TELEPORT_TIME(this)) {
+                       PM_Accelerate(this, dt, wishdir, wishspeed, wishspeed, this.com_phys_acc_rate, 1, 0, 0, 0);
+               }
+       }
+}
+
+.entity groundentity;
+/** for other entities */
+void sys_phys_simulate_simple(entity this, float dt)
+{
+       vector mn = this.mins;
+       vector mx = this.maxs;
+
+       vector g = '0 0 0';
+       if (this.com_phys_gravity_factor && !g) g = '0 0 -1' * PHYS_GRAVITY(NULL);
+
+       vector acc = this.com_phys_acc;
+       vector vel = this.com_phys_vel;
+       vector pos = this.com_phys_pos;
+
+       // SV_Physics_Toss
+
+       vel += g * dt;
+
+       this.angles += dt * this.avelocity;
+       float movetime = dt;
+       for (int i = 0; i < MAX_CLIP_PLANES && movetime > 0; i++) {
+               vector push = vel * movetime;
+               vector p0 = pos;
+               vector p1 = p0 + push;
+               // SV_PushEntity
+               tracebox(p0, mn, mx, p1, MOVE_NORMAL, this);
+               if (!trace_startsolid) {
+                       bool hit = trace_fraction < 1;
+                       pos = trace_endpos;
+                       entity ent = trace_ent;
+                       // SV_LinkEdict_TouchAreaGrid
+                       if (this.solid != SOLID_NOT) {
+                               FOREACH_ENTITY_RADIUS_ORDERED(0.5 * (this.absmin + this.absmax), 0.5 * vlen(this.absmax - this.absmin), true, {
+                                       if (it.solid != SOLID_TRIGGER || it == this) continue;
+                                       if (gettouch(it) && boxesoverlap(it.absmin, it.absmax, this.absmin, this.absmax)) {
+                                           // SV_LinkEdict_TouchAreaGrid_Call
+                                           trace_allsolid = false;
+                                           trace_startsolid = false;
+                                           trace_fraction = 1;
+                                           trace_inwater = false;
+                                           trace_inopen = true;
+                                           trace_endpos = it.origin;
+                                           trace_plane_normal = '0 0 1';
+                                           trace_plane_dist = 0;
+                                           trace_ent = this;
+                                           trace_dpstartcontents = 0;
+                                           trace_dphitcontents = 0;
+                                           trace_dphitq3surfaceflags = 0;
+                                           trace_dphittexturename = string_null;
+                                           gettouch(it)(this, it);
+                                           vel = this.velocity;
+                                       }
+                               });
+                       }
+                       if (hit && this.solid >= SOLID_TRIGGER && (!IS_ONGROUND(this) || this.groundentity != ent)) {
+                               // SV_Impact (ent, trace);
+                               tracebox(p0, mn, mx, p1, MOVE_NORMAL, this);
+                               void(entity, entity) touched = gettouch(this);
+                               if (touched && this.solid != SOLID_NOT) {
+                                       touched(ent, this);
+                               }
+                               void(entity, entity) touched2 = gettouch(ent);
+                               if (this && ent && touched2 && ent.solid != SOLID_NOT) {
+                                       trace_endpos = ent.origin;
+                                       trace_plane_normal *= -1;
+                                       trace_plane_dist *= -1;
+                                       trace_ent = this;
+                                       trace_dpstartcontents = 0;
+                                       trace_dphitcontents = 0;
+                                       trace_dphitq3surfaceflags = 0;
+                                       trace_dphittexturename = string_null;
+                                       touched2(this, ent);
+                               }
+                       }
+               }
+               // end SV_PushEntity
+               if (wasfreed(this)) { return; }
+               tracebox(p0, mn, mx, p1, MOVE_NORMAL, this);
+               if (trace_fraction == 1) { break; }
+               movetime *= 1 - min(1, trace_fraction);
+               ClipVelocity(vel, trace_plane_normal, vel, 1);
+       }
+
+       this.com_phys_acc = acc;
+       this.com_phys_vel = vel;
+       this.com_phys_pos = pos;
+       setorigin(this, this.com_phys_pos);
+}
+
+void sys_phys_update_single(entity this)
+{
+       sys_phys_simulate_simple(this, frametime);
 }
index 38d4e55e55e94da8a31ba67c1ff3f832a286932c..cef9916f3d60e3412bb761fbc746afed9085db86 100644 (file)
@@ -1,3 +1,11 @@
 #pragma once
 
 SYSTEM(phys, 30, 10);
+
+void sys_phys_fix(entity this, float dt);
+bool sys_phys_override(entity this, float dt);
+void sys_phys_monitor(entity this, float dt);
+void sys_phys_pregame_hold(entity this);
+void sys_phys_ai(entity this);
+void sys_phys_spectator_control(entity this);
+void sys_phys_fixspeed(entity this, float maxspeed_mod);
diff --git a/qcsrc/ecs/systems/sv_physics.qc b/qcsrc/ecs/systems/sv_physics.qc
new file mode 100644 (file)
index 0000000..904ebba
--- /dev/null
@@ -0,0 +1,117 @@
+#include "physics.qh"
+
+void sys_phys_fix(entity this, float dt)
+{
+       WarpZone_PlayerPhysics_FixVAngle(this);
+       Physics_UpdateStats(this, PHYS_HIGHSPEED(this));
+}
+
+bool sys_phys_override(entity this, float dt)
+{
+       int buttons = PHYS_INPUT_BUTTON_MASK(this);
+       if (PM_check_specialcommand(this, buttons)) { return true; }
+       if (this.PlayerPhysplug && this.PlayerPhysplug(this, dt)) { return true; }
+       return false;
+}
+
+void sys_phys_monitor(entity this, float dt)
+{
+       int buttons = PHYS_INPUT_BUTTON_MASK(this);
+       anticheat_physics(this);
+       if (sv_maxidle > 0) {
+               if (buttons != this.buttons_old
+                   || this.movement != this.movement_old
+                   || this.v_angle != this.v_angle_old) { this.parm_idlesince = time; }
+       }
+       PM_check_nickspam(this);
+       PM_check_punch(this, dt);
+}
+
+void sys_phys_ai(entity this)
+{
+       if (!IS_BOT_CLIENT(this)) { return; }
+       if (playerdemo_read(this)) { return; }
+       bot_think(this);
+}
+
+void sys_phys_pregame_hold(entity this)
+{
+       if (!IS_PLAYER(this)) { return; }
+       const bool allowed_to_move = (time >= game_starttime);
+       if (!allowed_to_move) {
+               this.velocity = '0 0 0';
+               set_movetype(this, MOVETYPE_NONE);
+               this.disableclientprediction = 2;
+       } else if (this.disableclientprediction == 2) {
+               if (this.move_movetype == MOVETYPE_NONE) { set_movetype(this, MOVETYPE_WALK); }
+               this.disableclientprediction = 0;
+       }
+}
+
+void sys_phys_spectator_control(entity this)
+{
+       float maxspeed_mod = autocvar_sv_spectator_speed_multiplier;
+       if (!this.spectatorspeed) { this.spectatorspeed = maxspeed_mod; }
+       if ((this.impulse >= 1 && this.impulse <= 19)
+           || (this.impulse >= 200 && this.impulse <= 209)
+           || (this.impulse >= 220 && this.impulse <= 229)
+          ) {
+               if (this.lastclassname != STR_PLAYER) {
+                       if (this.impulse == 10
+                           || this.impulse == 15
+                           || this.impulse == 18
+                           || (this.impulse >= 200 && this.impulse <= 209)
+                          ) { this.spectatorspeed = bound(1, this.spectatorspeed + 0.5, 5); } else if (this.impulse == 11) {
+                               this.spectatorspeed = maxspeed_mod;
+                       } else if (this.impulse == 12
+                           || this.impulse == 16
+                           || this.impulse == 19
+                           || (this.impulse >= 220 && this.impulse <= 229)
+                                 ) {
+                               this.spectatorspeed = bound(1, this.spectatorspeed - 0.5, 5);
+                       } else if (this.impulse >= 1 && this.impulse <= 9) {
+                               this.spectatorspeed = 1 + 0.5 * (this.impulse - 1);
+                       }
+               }  // otherwise just clear
+               this.impulse = 0;
+       }
+}
+
+void sys_phys_fixspeed(entity this, float maxspeed_mod)
+{
+       float spd = max(PHYS_MAXSPEED(this), PHYS_MAXAIRSPEED(this)) * maxspeed_mod;
+       if (this.speed != spd) {
+               this.speed = spd;
+               string temps = ftos(spd);
+               stuffcmd(this, strcat("cl_forwardspeed ", temps, "\n"));
+               stuffcmd(this, strcat("cl_backspeed ", temps, "\n"));
+               stuffcmd(this, strcat("cl_sidespeed ", temps, "\n"));
+               stuffcmd(this, strcat("cl_upspeed ", temps, "\n"));
+       }
+
+       if (this.jumpspeedcap_min != autocvar_sv_jumpspeedcap_min) {
+               this.jumpspeedcap_min = autocvar_sv_jumpspeedcap_min;
+               stuffcmd(this, sprintf("\ncl_jumpspeedcap_min \"%s\"\n", autocvar_sv_jumpspeedcap_min));
+       }
+       if (this.jumpspeedcap_max != autocvar_sv_jumpspeedcap_max) {
+               this.jumpspeedcap_max = autocvar_sv_jumpspeedcap_max;
+               stuffcmd(this, sprintf("\ncl_jumpspeedcap_max \"%s\"\n", autocvar_sv_jumpspeedcap_max));
+       }
+}
+
+void sys_phys_land(entity this)
+{
+       if (autocvar_speedmeter) {
+               LOG_TRACEF("landing velocity: %v (abs: %f)", this.velocity, vlen(this.velocity));
+       }
+       if (this.jumppadcount > 1) {
+               LOG_TRACEF("%dx jumppad combo", this.jumppadcount);
+       }
+       this.jumppadcount = 0;
+}
+
+STATIC_INIT(sys_phys)
+{
+       entity listener = new_pure(sys_phys);
+       subscribe(listener, phys_land, sys_phys_land);
+}
index b0c9ec901c76103dae5531c9bb0136b7ace93471..83a0ebf34a01bb06755ba9021eeb0e2508340285 100644 (file)
@@ -2,6 +2,18 @@
        #define COMPAT_NO_MOD_IS_XONOTIC
 #endif
 
+#ifdef CSQC
+#define IS_CSQC 1
+#else
+#define IS_CSQC 0
+#endif
+
+#ifdef SVQC
+#define IS_SVQC 1
+#else
+#define IS_SVQC 0
+#endif
+
 #include "compiler.qh"
 
 #ifndef QCC_SUPPORT_INT
@@ -43,7 +55,7 @@
 #else
        #define TC(T, sym) MACRO_BEGIN \
                if (!is_##T(sym)) { \
-                       LOG_WARNINGF("Type check failed: " #sym " :: " #T); \
+                       LOG_WARNF("Type check failed: " #sym " :: " #T); \
                        isnt_##T(sym); \
                } \
        MACRO_END
@@ -120,12 +132,12 @@ void make_safe_for_remove(entity this);
 #endif
 
 #define objerror(this, msg) MACRO_BEGIN { \
-       LOG_WARNING("======OBJECT ERROR======"); \
+       LOG_WARN("======OBJECT ERROR======"); \
        entity _e = (this); \
        eprint(_e); \
        objerror_safe(_e); \
        delete(_e); \
-       LOG_WARNINGF("%s OBJECT ERROR in %s:\n%s\nTip: read above for entity information", PROGNAME, __FUNC__, msg); \
+       LOG_WARNF("%s OBJECT ERROR in %s:\n%s\nTip: read above for entity information", PROGNAME, __FUNC__, msg); \
 } MACRO_END
 
 #ifdef MENUQC
@@ -253,3 +265,8 @@ void make_safe_for_remove(entity this);
        #define CSQC_Ent_Remove _CSQC_Ent_Remove
 #endif
 #undef ENGINE_EVENT
+
+#ifndef MENUQC
+       #include <ecs/_lib.qh>
+       #include <ecs/components/_mod.qh>
+#endif
index c0809ecdf88d242e03fbd329dd648e636ee881a1..18305177bf8a266261e1be9ad143dfde695fcace 100644 (file)
@@ -20,7 +20,7 @@ USING(ArrayList, entity);
        MACRO_BEGIN \
        { \
                buf_del(this.al_buf); \
-               remove(this); \
+               delete(this); \
                this = NULL; \
        } MACRO_END
 
index 789f115d14ac960b3c361bac06ce8229e7960e0b..6b86092967e67dd5b9638bafce9585ebfbec16fb 100644 (file)
@@ -300,6 +300,6 @@ entity CSQCModel_server2csqc(int i)
 {
        if (i < maxclients) return CSQCModel_players[i];
        ++i;
-       LOG_DEBUGF("player out of bounds: %d\n", i);
+       LOG_DEBUGF("player out of bounds: %d", i);
        return findfloat(NULL, entnum, i);
 }
index 3b20972e25db6e1706aa4a59b944d0a65e71dfaa..b5d9f8bd361fff927dc54f70a5632300a64d4360 100644 (file)
@@ -19,8 +19,7 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  * IN THE SOFTWARE.
  */
-#ifndef LIB_CSQCMODEL_CL_MODEL_H
-#define LIB_CSQCMODEL_CL_MODEL_H
+#pragma once
 
 #include "common.qh"
 
@@ -50,4 +49,3 @@ void CSQCModel_InterpolateAnimation_1To2_Note(entity this, int sf, float set_tim
 void CSQCModel_InterpolateAnimation_2To4_Do(entity this);
 void CSQCModel_InterpolateAnimation_1To2_Do(entity this);
 // will overwrite lerpfrac, lerpfrac3, lerpfrac4, and possibly clear frame*time if they are undisplayed according to lerpfracs
-#endif
index 4bea5e36a7399098aa3defabd15185a688524806..4cc8458d51a4b0b359723f4f67b4db704bda544e 100644 (file)
@@ -97,7 +97,7 @@ void CSQCPlayer_SetPredictionError(vector o, vector v, float onground_diff)
 void CSQCPlayer_Unpredict(entity this)
 {
        if (csqcplayer_status == CSQCPLAYERSTATUS_UNPREDICTED) return;
-       if (csqcplayer_status != CSQCPLAYERSTATUS_PREDICTED) LOG_FATALF("Cannot unpredict in current status (%d)\n", csqcplayer_status);
+       if (csqcplayer_status != CSQCPLAYERSTATUS_PREDICTED) LOG_FATALF("Cannot unpredict in current status (%d)", csqcplayer_status);
        this.origin = csqcplayer_origin;
        this.velocity = csqcplayer_velocity;
        csqcplayer_moveframe = csqcplayer_sequence + 1; // + 1 because the recieved frame has the move already done (server side)
index 513875aa9889f05067373a4a13ea70ae417ba311..297e2e69d648c1826289fa21c95e389f5a61b5f2 100644 (file)
@@ -19,8 +19,7 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  * IN THE SOFTWARE.
  */
-#ifndef LIB_CSQCMODEL_CL_PLAYER_H
-#define LIB_CSQCMODEL_CL_PLAYER_H
+#pragma once
 
 bool autocvar_cl_movement = true;
 
@@ -42,4 +41,3 @@ void CSQCPlayer_SetCamera();
 float CSQCPlayer_PreUpdate(entity this);
 float CSQCPlayer_PostUpdate(entity this);
 float CSQCPlayer_IsLocalPlayer(entity this);
-#endif
index a700f3af2b9bda88665508f3456a0bd066c6f613..37b88997ef84bf7d456e34575fc0859d79f01442 100644 (file)
@@ -19,8 +19,7 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  * IN THE SOFTWARE.
  */
-#ifndef LIB_CSQCMODEL_COMMON_H
-#define LIB_CSQCMODEL_COMMON_H
+#pragma once
 
 #include <common/csqcmodel_settings.qh>
 
@@ -94,4 +93,3 @@ const int CSQCMODEL_PROPERTY_SIZE = BIT(15);
 #else
 #define ALLPROPERTIES ALLPROPERTIES_COMMON
 #endif
-#endif
index 2f4828053b0b98e73ec890398374aa3cd86618b6..3ea385cbcd8b5e4918c1f88ed8b3c6eaed9508d4 100644 (file)
@@ -19,8 +19,7 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  * IN THE SOFTWARE.
  */
-#ifndef LIB_CSQCMODEL_INTERPOLATE_H
-#define LIB_CSQCMODEL_INTERPOLATE_H
+#pragma once
 
 .int iflags;
 const int IFLAG_VELOCITY = BIT(0);
@@ -49,4 +48,3 @@ void InterpolateOrigin_Do(entity this);
 
 // in case we interpolate that:
 .vector v_angle;
-#endif
index 85b8a4fcbb80580059728230af0915e0096569b5..359cf1738f01666e5f9902a7cad17980bf14d194 100644 (file)
@@ -1,5 +1,4 @@
-#ifndef LIB_CSQCMODEL_SETTINGS_H
-#define LIB_CSQCMODEL_SETTINGS_H
+#pragma once
 // define this if svqc code wants to use .frame2 and .lerpfrac
 //#define CSQCMODEL_HAVE_TWO_FRAMES
 
@@ -24,4 +23,3 @@
 //vector PL_CROUCH_MIN  = ...;
 //vector PL_CROUCH_MAX  = ...;
 //vector PL_CROUCH_VIEW_OFS  = ...;
-#endif
index d495ae0154e58bd297d3de76de2c4eb7c8aed761..0f8ef06ac86a7fd890ca3a35bba045100b893050 100644 (file)
@@ -64,13 +64,9 @@ bool CSQCModel_Send(entity this, entity to, int sf)
 void CSQCModel_CheckUpdate(entity e)
 {
        // some nice flags for CSQCMODEL_IF
-       float isplayer = IS_CLIENT(e);
-       float islocalplayer = isplayer; // we set BOTH to 1 here as we need the sendflags
-       float isnolocalplayer = isplayer; // we set BOTH to 1 here as we need the sendflags
-
-       unused_float = isplayer;
-       unused_float = islocalplayer;
-       unused_float = isnolocalplayer;
+       noref float isplayer = IS_CLIENT(e);
+       noref float islocalplayer = isplayer; // we set BOTH to 1 here as we need the sendflags
+       noref float isnolocalplayer = isplayer; // we set BOTH to 1 here as we need the sendflags
 
 #if CSQCPLAYER_FORCE_UPDATES
        if(isplayer && time > e.csqcmodel_nextforcedupdate)
index 3e043d3532130748d44e5900ec6c253b435fd013..e963f12a1bf6ac79d9d3e45bf941e10e92927fef 100644 (file)
@@ -19,8 +19,7 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  * IN THE SOFTWARE.
  */
-#ifndef LIB_CSQCMODEL_SV_MODEL_H
-#define LIB_CSQCMODEL_SV_MODEL_H
+#pragma once
 
 #include "common.qh"
 
@@ -41,4 +40,3 @@ void CSQCModel_UnlinkEntity(entity e);
 #undef CSQCMODEL_PROPERTY
 #undef CSQCMODEL_ENDIF
 #undef CSQCMODEL_IF
-#endif
index 3e7e020c67a5fea2ea7368fb3444a30f9fbebea2..c20c53440785ceb09f8b236f6bfeef606794b6b2 100644 (file)
@@ -12,7 +12,7 @@
        /** Remove entity */
        void SUB_Remove(entity this)
        {
-               remove(this);
+               delete(this);
        }
 
        void defer_think(entity this)
index c66d7b9a88bd8a163d20d5a13cef85132102892c..8ebedb76f65f66110d3fd26ffaa46277e1b24021 100644 (file)
@@ -49,7 +49,7 @@ string CTX(string s)
        int p = strstrofs(s, "^", 0);
        string ret = (p < 0) ? s : substring(s, p + 1, -1);
 #if CTX_CACHE
-        LOG_DEBUGF("CTX(\"%s\")\n", s);
+        LOG_DEBUGF("CTX(\"%s\")", s);
                HM_sets(CTX_cache, s, ret);
 #endif
        return ret;
index 1d7b2516868fb9548802be74f7f5a64ddad901a8..2927a62fe667f9f65484186e7ac9b47c5163f62a 100644 (file)
@@ -16,8 +16,8 @@ void IL_ENDFRAME();
  *   freed entities must be removed from the list
  */
 CLASS(IntrusiveList, Object)
-       ATTRIB(IntrusiveList, il_head, entity, NULL);
-       ATTRIB(IntrusiveList, il_tail, entity, NULL);
+       ATTRIB(IntrusiveList, il_head, entity);
+       ATTRIB(IntrusiveList, il_tail, entity);
        ATTRIB(IntrusiveList, il_nextfld, .entity, nil);
        ATTRIB(IntrusiveList, il_prevfld, .entity, nil);
        INIT(IntrusiveList) { IL_INIT(this); }
@@ -127,7 +127,7 @@ void IL_REMOVE(IntrusiveList this, entity it)
        entity otail = this.il_tail;
        next ? next.(il_prev) = prev : this.il_tail = prev;
        prev ? prev.(il_next) = next : this.il_head = next;
-       LOG_DEBUGF("remove %i (%i :: %i), head: %i -> %i, tail: %i -> %i\n", it, it.(il_prev), it.(il_next), ohead, this.il_head, otail, this.il_tail);
+       LOG_DEBUGF("remove %i (%i :: %i), head: %i -> %i, tail: %i -> %i", it, it.(il_prev), it.(il_next), ohead, this.il_head, otail, this.il_tail);
        it.(il_next) = it.(il_prev) = NULL;
 }
 
@@ -150,7 +150,7 @@ void IL_REMOVE(IntrusiveList this, entity it)
 #define IL_DELETE(this, dtor) \
        MACRO_BEGIN \
        { \
-               remove(this); \
+               delete(this); \
                this = NULL; \
        } MACRO_END
 
@@ -204,7 +204,7 @@ void IL_INIT(IntrusiveList this)
                        return;
                }
        }
-       LOG_WARNINGF("IntrusiveList overflow");
+       LOG_WARNF("IntrusiveList overflow");
 }
 
 void IL_DTOR(IntrusiveList this)
index 82448b931bed86c3788be433ea8fd9588b130145..7183e90feab6bad7a26ce4ba98f8e01886ea8bca 100644 (file)
             if (cond) LAMBDA(body) \
         } \
     } MACRO_END
+#define MUTEX_LOCK(this) MACRO_BEGIN \
+       if (this) LOG_SEVEREF("Loop mutex held by %s", this); \
+       this = __FUNC__; \
+MACRO_END
+#define MUTEX_UNLOCK(this) MACRO_BEGIN \
+       this = string_null; \
+MACRO_END
 #define _FOREACH_ENTITY_FIND_UNORDERED(id, T, fld, match, cond, body) \
        MACRO_BEGIN { \
-               if (_FOREACH_ENTITY_FIND_##T##_##id##mutex) LOG_SEVEREF("Loop mutex held by %s", _FOREACH_ENTITY_FIND_##T##_##id##mutex); \
-               _FOREACH_ENTITY_FIND_##T##_##id##mutex = __FUNC__; \
+               MUTEX_LOCK(_FOREACH_ENTITY_FIND_##T##_##id##mutex); \
                entity _foundchain_first = _findchain##T##_tofield(fld, match, _FOREACH_ENTITY_FIND_##T##_next##id); \
                FOREACH_LIST(_foundchain, _FOREACH_ENTITY_FIND_##T##_next##id, cond, body); \
-               _FOREACH_ENTITY_FIND_##T##_##id##mutex = string_null; \
+               MUTEX_UNLOCK(_FOREACH_ENTITY_FIND_##T##_##id##mutex); \
        } MACRO_END
 
 #define FOREACH_ENTITY(cond, body) ORDERED(FOREACH_ENTITY)(cond, body)
 
 #ifndef MENUQC
 entity(vector org, float rad, .entity tofield) _findchainradius_tofield = #22;
-#define FOREACH_ENTITY_RADIUS(org, dist, cond, body) FOREACH_ENTITY_RADIUS_UNORDERED(org, dist, cond, body)
+#define FOREACH_ENTITY_RADIUS(org, dist, cond, body) ORDERED(FOREACH_ENTITY_RADIUS)(org, dist, cond, body)
 .entity _FOREACH_ENTITY_FIND_radius_next; noref string _FOREACH_ENTITY_FIND_radius_mutex;
 #define FOREACH_ENTITY_RADIUS_UNORDERED(org, dist, cond, body) _FOREACH_ENTITY_FIND_UNORDERED(, radius, org, dist, cond, body)
+.entity _FOREACH_ENTITY_FIND_radius_nexttmp; noref string _FOREACH_ENTITY_FIND_radius_tmpmutex;
+#define FOREACH_ENTITY_RADIUS_ORDERED(org, dist, cond, body) \
+MACRO_BEGIN \
+       entity _rev_first = NULL; \
+       _FOREACH_ENTITY_FIND_UNORDERED(tmp, radius, org, dist, cond, (it._FOREACH_ENTITY_FIND_radius_nexttmp = _rev_first, _rev_first = it)); \
+       MUTEX_LOCK(_FOREACH_ENTITY_FIND_radius_tmpmutex); \
+       FOREACH_LIST(_rev, _FOREACH_ENTITY_FIND_radius_nexttmp, true, body); \
+       MUTEX_UNLOCK(_FOREACH_ENTITY_FIND_radius_tmpmutex); \
+MACRO_END
 #endif
 
 #define FOREACH_ENTITY_FLOAT(fld, match, body) ORDERED(FOREACH_ENTITY_FLOAT)(fld, match, body)
index ad30115a2e74c3fb00e25564cfe0e998816d42a9..62d04b32e909bb741b55a74f77c37f9bccfa084c 100644 (file)
@@ -3,7 +3,7 @@
 #include "oo.qh"
 
 CLASS(Lazy, Object)
-       ATTRIB(Lazy, m_get, entity(), func_null);
+       ATTRIB(Lazy, m_get, entity());
        CONSTRUCTOR(Lazy, entity() _compute)
        {
                this.m_get = _compute;
index 6afc862ed0a6306b97e2ad5ca02702b3a79a4817..0dd430722f755218f5f796883a5dcf4317caf885 100644 (file)
@@ -1,14 +1,14 @@
 #pragma once
 
 CLASS(LinkedListNode, Object)
-       ATTRIB(LinkedListNode, ll_data, entity, NULL)
-       ATTRIB(LinkedListNode, ll_prev, LinkedListNode, NULL)
-       ATTRIB(LinkedListNode, ll_next, LinkedListNode, NULL)
+       ATTRIB(LinkedListNode, ll_data, entity);
+       ATTRIB(LinkedListNode, ll_prev, LinkedListNode);
+       ATTRIB(LinkedListNode, ll_next, LinkedListNode);
 ENDCLASS(LinkedListNode)
 
 CLASS(LinkedList, Object)
-       ATTRIB(LinkedList, ll_head, LinkedListNode, NULL);
-       ATTRIB(LinkedList, ll_tail, LinkedListNode, NULL);
+       ATTRIB(LinkedList, ll_head, LinkedListNode);
+       ATTRIB(LinkedList, ll_tail, LinkedListNode);
 ENDCLASS(LinkedList)
 
 #define LL_NEW() NEW(LinkedList)
@@ -40,7 +40,7 @@ entity LL_POP(LinkedList this)
        LinkedListNode prev = n.ll_prev;
        if (prev) (this.ll_tail = prev).ll_next = NULL;
        else this.ll_head = this.ll_tail = NULL;
-       remove(n);
+       delete(n);
        return e;
 }
 
@@ -57,7 +57,7 @@ entity LL_POP(LinkedList this)
                        entity it = LL_POP(_ll); \
                        if (!it) continue; \
                        dtor \
-                       remove(it); \
+                       delete(it); \
                } \
        } MACRO_END
 
@@ -68,7 +68,7 @@ entity LL_POP(LinkedList this)
        MACRO_BEGIN \
        { \
                LL_CLEAR_2(this, dtor); \
-               remove(this); \
+               delete(this); \
                this = NULL; \
        } MACRO_END
 
index a8874adbd4630d69a03458346404391ac23bd2a6..7f5bc720412348f2dcc8df053027f4de84f3e1b1 100644 (file)
 
 
 #if defined(MENUQC)
-string(string...) strcat0n = #53;
+string(string, string...) strcat1n = #53;
 #else
-string(string...) strcat0n = #115;
+string(string, string...) strcat1n = #115;
 #endif
 
-#define __SOURCELOC__ (sprintf("^7%s^9" "(" "^9"__FILE__"^7"  ":"  "^9"STR(__LINE__)"^7" ")", __FUNC__))
+// would be nice if __FUNC__ could be concatenated at compile time
+#if 0
+       // less work, bigger binary
+       #define __SOURCELOC__ (sprintf("^7%s^9" "(" "^9"__FILE__"^7"  ":"  "^9"STR(__LINE__)"^7" ")", __FUNC__))
+#else
+       #define __SOURCELOC__ (sprintf("^7%s^9" "(" "^9%s^7"  ":"  "^9%s^7" ")", __FUNC__, __FILE__, STR(__LINE__)))
+#endif
 
+#define _LOG_HEADER(level) "^9[::" "^7"PROGNAME"^9" "::" level"^9" "] ", __SOURCELOC__
 #define _LOG(f, level, s) \
        MACRO_BEGIN { \
-               f(sprintf("^9[::" "^7"PROGNAME"^9" "::" level"^9" "] %s\n^7%s\n", __SOURCELOC__, s)); \
+               f(strcat1n(_LOG_HEADER(level), "\n^7", s, "\n")); \
        } MACRO_END
 
-#define  LOG_FATAL(...) _LOG_FATAL(strcat0n(__VA_ARGS__))
+#define  LOG_FATAL(...) _LOG_FATAL(strcat1n(__VA_ARGS__))
 #define  LOG_FATALF(...) _LOG_FATAL(sprintf(__VA_ARGS__))
 #define _LOG_FATAL(s) _LOG(error, "^1FATAL", s)
 
-#define  LOG_SEVERE(...) _LOG_SEVERE(strcat0n(__VA_ARGS__))
+#define  LOG_SEVERE(...) _LOG_SEVERE(strcat1n(__VA_ARGS__))
 #define  LOG_SEVEREF(...) _LOG_SEVERE(sprintf(__VA_ARGS__))
 #define _LOG_SEVERE(s) _LOG(backtrace, "^1SEVERE", s)
 
-#define  LOG_WARNING(...) _LOG_WARNING(strcat0n(__VA_ARGS__))
-#define  LOG_WARNINGF(...) _LOG_WARNING(sprintf(__VA_ARGS__))
-#define _LOG_WARNING(s) _LOG(print, "^3WARNING", s)
+#define  LOG_WARN(...) _LOG_WARN(strcat1n(__VA_ARGS__))
+#define  LOG_WARNF(...) _LOG_WARN(sprintf(__VA_ARGS__))
+#define _LOG_WARN(s) _LOG(print, "^3WARNING", s)
 
-#define  LOG_INFO(...) _LOG_INFO(strcat0n(__VA_ARGS__))
+#define  LOG_INFO(...) _LOG_INFO(strcat1n(__VA_ARGS__))
 #define  LOG_INFOF(...) _LOG_INFO(sprintf(__VA_ARGS__))
 #define _LOG_INFO(s) \
        MACRO_BEGIN { \
-               string ___s = s; \
-               if (autocvar_developer) \
-                       _LOG(print, "^5INFO", ___s); \
-               else \
-                       print(___s); \
+               dprint(_LOG_HEADER("^5INFO")); \
+               print("\n^7", s); \
        } MACRO_END
 
-#define  LOG_TRACE(...) _LOG_TRACE(strcat0n(__VA_ARGS__))
+#define  LOG_TRACE(...) _LOG_TRACE(strcat1n(__VA_ARGS__))
 #define  LOG_TRACEF(...) _LOG_TRACE(sprintf(__VA_ARGS__))
 #define _LOG_TRACE(s) _LOG(dprint, "^6TRACE", s)
 
-#define  LOG_DEBUG(...) _LOG_DEBUG(strcat0n(__VA_ARGS__))
+#define  LOG_DEBUG(...) _LOG_DEBUG(strcat1n(__VA_ARGS__))
 #define  LOG_DEBUGF(...) _LOG_DEBUG(sprintf(__VA_ARGS__))
 #define _LOG_DEBUG(s) _LOG(dprint2, "^2DEBUG", s)
 
index 57b8f8c67939a113fee43e48d3f00b65673eac67..55da4d63f0caab22ec1c305a02ad0ca85822e116 100644 (file)
@@ -9,7 +9,7 @@ void db_save(int db, string filename)
        int fh = fopen(filename, FILE_WRITE);
        if (fh < 0)
        {
-               LOG_WARNINGF("^1Can't write DB to %s\n", filename);
+               LOG_WARNF("^1Can't write DB to %s", filename);
                return;
        }
        fputs(fh, strcat(ftos(DB_BUCKETS), "\n"));
@@ -64,7 +64,7 @@ int db_load(string filename)
 void db_dump(int db, string filename)
 {
        int fh = fopen(filename, FILE_WRITE);
-       if (fh < 0) LOG_FATALF("Can't dump DB to %s\n");
+       if (fh < 0) LOG_FATALF("Can't dump DB to %s");
        fputs(fh, "0\n");
        for (int i = 0, n = buf_getsize(db); i < n; ++i)
        {
index 23ec02e823242d3d58d74959d21695ece58ac6fc..c399c2aa6cf86e2d9a9ba910667c8cd1c926ba43 100644 (file)
@@ -22,7 +22,7 @@ void MX_Nick_(entity fh, entity pass, int status)
             fh.url_verb = "PUT";
             fh.url_content_type = "application/json";
             url_fputs(fh, sprintf("{\"displayname\": \"%s\"}", pass.message));
-            remove(pass);
+            delete(pass);
             url_fclose(fh);
             break;
         }
@@ -46,7 +46,7 @@ void MX_Messages_(entity fh, entity pass, int status)
 {
     switch (status) {
         default: {
-            LOG_WARNINGF("status: %d", status);
+            LOG_WARNF("status: %d", status);
             break;
         }
         case URL_READY_CLOSED: break;
@@ -90,7 +90,7 @@ void MX_Sync_(entity fh, entity pass, int status)
 {
     switch (status) {
         default: {
-            LOG_WARNINGF("status: %d", status);
+            LOG_WARNF("status: %d", status);
             break;
         }
         case URL_READY_CLOSED: break;
@@ -175,7 +175,7 @@ void MX_Typing_(entity fh, entity pass, int status)
             fh.url_verb = "PUT";
             fh.url_content_type = "application/json";
             url_fputs(fh, sprintf("{\"typing\": %s, \"timeout\": 30000}", pass.message));
-            remove(pass);
+            delete(pass);
             url_fclose(fh);
             break;
         }
@@ -204,7 +204,7 @@ void MX_Say_(entity fh, entity pass, int status)
             fh.url_verb = "PUT";
             fh.url_content_type = "application/json";
             url_fputs(fh, sprintf("{\"msgtype\": \"m.text\", \"body\": \"%s\"}", pass.message));
-            strunzone(pass.message); remove(pass);
+            strunzone(pass.message); delete(pass);
             url_fclose(fh);
             break;
         }
index 0ce157848e2ad6d1a411664016eb1644d99db88f..106f00998c3daac770fbbc562d583ba62441c99a 100644 (file)
@@ -156,13 +156,13 @@ STATIC_INIT(C2S_Protocol_renumber) { FOREACH(C2S_Protocol, true, it.m_id = i); }
                {
                        entity reader = C2S_Protocol_from(C2S);
                        if (reader && reader.m_read && reader.m_read(NULL, sender, true)) continue;
-                       LOG_SEVEREF("Net_ClientCommand() with malformed C2S=%d\n", C2S);
+                       LOG_SEVEREF("Net_ClientCommand() with malformed C2S=%d", C2S);
                        return;
                }
                g_buf_i--;
                int expected = strlen(buf);
-               if (g_buf_i > expected) LOG_WARNINGF("Underflow: %d", g_buf_i - expected);
-               if (g_buf_i < expected) LOG_WARNINGF("Overrflow: %d", expected - g_buf_i);
+               if (g_buf_i > expected) LOG_WARNF("Underflow: %d", g_buf_i - expected);
+               if (g_buf_i < expected) LOG_WARNF("Overrflow: %d", expected - g_buf_i);
        }
 
 #endif
@@ -176,7 +176,7 @@ STATIC_INIT(C2S_Protocol_renumber) { FOREACH(C2S_Protocol, true, it.m_id = i); }
                } MACRO_END
        #define Net_Reject() \
                MACRO_BEGIN { \
-                       if (this)     remove(this); \
+                       if (this)     delete(this); \
                } MACRO_END
 
        string g_buf;
index e3206dcf3ee799b584e85bf71457fbe44d20ee3e..7a7a72641a0601a1d857a0654631223d452275dd 100644 (file)
@@ -227,13 +227,17 @@ STATIC_INIT(RegisterClasses)
     } \
        STATIC_METHOD(cname, dtorimpl, void(cname this))
 
-#define ATTRIB(cname, name, type, val)      \
-       class(cname).type name;                \
+#define ATTRIB(...) EVAL_ATTRIB(OVERLOAD_(ATTRIB, __VA_ARGS__))
+#define EVAL_ATTRIB(...) __VA_ARGS__
+#define ATTRIB_3(cname, name, type) INIT(cname) {} class(cname) .type name
+#define ATTRIB_4(cname, name, type, val) \
+       ATTRIB_3(cname, name, type); \
        INIT(cname) \
        { \
                noref bool strzone; /* Error on strzone() calls. */ \
                this.name = val; \
-       }
+       } \
+       ATTRIB_3(cname, name, type)
 
 #define STATIC_ATTRIB(cname, name, type, val) \
        type cname##_##name; \
@@ -264,7 +268,7 @@ STATIC_INIT(RegisterClasses)
        }
 
 #define ATTRIBARRAY(cname, name, type, cnt) \
-       class(cname).type name[cnt];
+       class(cname) .type name[cnt]
 
 #define ENDCLASS(cname) \
        INIT(cname) \
index d3228d47c864b9fdcce2d64c54570805f4d71a0a..927410cde115de908e5357781ba789c33378716b 100644 (file)
@@ -12,8 +12,7 @@
 /* without even the implied warranty of merchantability or fitness for a      */
 /* particular purpose.                                                        */
 /*                                                                            */
-#ifndef P99_H_
-#define P99_H_
+#pragma once
 
 #define P99_MAX_NUMBER 16
 #define P00_ARG(                            \
@@ -83,5 +82,3 @@
     P99_PASTE2(P99_PASTE3(_1, _2, _3), _4)
 #define P99_PASTE5(_1, _2, _3, _4, _5) \
     P99_PASTE2(P99_PASTE4(_1, _2, _3, _4), _5)
-
-#endif /* !P99_H_ */
index aff961c55da56b9dcde016c90335dbee7026d5e9..2287d869d0c455bdbf15c77950ac8a5671f20b64 100644 (file)
@@ -38,8 +38,7 @@ void DistributeEvenly_Init(float amount, float totalweight)
 {
        if (DistributeEvenly_amount)
        {
-               LOG_TRACE("DistributeEvenly_Init: UNFINISHED DISTRIBUTION (", ftos(DistributeEvenly_amount), " for ");
-               LOG_TRACE(ftos(DistributeEvenly_totalweight), " left!)\n");
+               LOG_TRACE("DistributeEvenly_Init: UNFINISHED DISTRIBUTION (", ftos(DistributeEvenly_amount), " for ", ftos(DistributeEvenly_totalweight), " left!)");
        }
        if (totalweight == 0) DistributeEvenly_amount = 0;
        else DistributeEvenly_amount = amount;
@@ -97,7 +96,7 @@ float gsl_ran_gaussian(float sigma)
                prandom_seed = c;
 
        #ifdef USE_PRANDOM_DEBUG
-                       LOG_TRACE("RANDOM -> ", ftos(c), "\n");
+                       LOG_TRACE("RANDOM -> ", ftos(c));
        #endif
 
                return c / 65536;  // in [0..1[
@@ -122,14 +121,14 @@ float gsl_ran_gaussian(float sigma)
        {
                prandom_seed = seed;
        #ifdef USE_PRANDOM_DEBUG
-                       LOG_TRACE("SRANDOM ", ftos(seed), "\n");
+                       LOG_TRACE("SRANDOM ", ftos(seed));
        #endif
        }
 
        #ifdef USE_PRANDOM_DEBUG
                void prandom_debug()
                {
-                       LOG_TRACE("Current random seed = ", ftos(prandom_seed), "\n");
+                       LOG_TRACE("Current random seed = ", ftos(prandom_seed));
                }
        #endif
 #endif
index 5f2f5851688d490ef5b973db1442ccc4ebd40c12..9d171e031ab4391090341737d675574a0154aca2 100644 (file)
@@ -160,7 +160,7 @@ void Registry_send(string id, string hash);
                FOREACH(id, true, s = strcat(s, join, it.registered_id)); \
                s = substring(s, strlen(join), -1); \
                string h = REGISTRY_HASH(id) = strzone(digest_hex(algo, s)); \
-               LOG_DEBUGF(#id ": %s\n[%s]\n", h, s); \
+               LOG_DEBUGF(#id ": %s\n[%s]", h, s); \
        } \
        void Registry_check(string r, string sv) \
        { \
@@ -169,7 +169,7 @@ void Registry_send(string id, string hash);
                        string cl = REGISTRY_HASH(id); \
                        if (cl != sv) \
                        { \
-                               LOG_FATALF("client/server mismatch (%s).\nCL: %s\nSV: %s\n", r, cl, sv); \
+                               LOG_FATALF("client/server mismatch (%s).\nCL: %s\nSV: %s", r, cl, sv); \
                        } \
                } \
        } \
@@ -181,8 +181,8 @@ void Registry_send(string id, string hash);
 #define REGISTER_REGISTRY_2(id, str) \
        ACCUMULATE_FUNCTION(__static_init, Register##id) \
        CLASS(id##Registry, Object) \
-               ATTRIB(id##Registry, m_name, string, str) \
-               ATTRIB(id##Registry, REGISTRY_NEXT, entity, id##_first) \
+               ATTRIB(id##Registry, m_name, string, str); \
+               ATTRIB(id##Registry, REGISTRY_NEXT, entity, id##_first); \
                METHOD(id##Registry, m_reload, void()); \
        ENDCLASS(id##Registry) \
        REGISTER(Registries, REGISTRY, id, m_id, NEW(id##Registry)); \
index 0463979c1a3fb855c3245360ffcb3be7f4387a6a..ae6db507f82b527babf8cb1bd49239b5df812a4b 100644 (file)
@@ -20,7 +20,7 @@ noref bool require_spawnfunc_prefix;
 
        #define _spawnfunc_checktypes(fld) \
                if (fieldname == #fld) \
-                       if (!entityfieldassignablefromeditor(i)) LOG_FATALF("Entity field '%s' cannot be whitelisted\n", fieldname);
+                       if (!entityfieldassignablefromeditor(i)) LOG_FATALF("Entity field '%s' cannot be whitelisted", fieldname);
 #else
        #define _spawnfunc_checktypes(fld)
 #endif
@@ -62,7 +62,7 @@ noref bool require_spawnfunc_prefix;
                                        if (fieldname == "") continue; \
                                        FIELDS_COMMON(_spawnfunc_check) \
                                        whitelist(_spawnfunc_check) \
-                                       LOG_WARNINGF(_("Entity field %s.%s (%s) is not whitelisted. If you believe this is an error, please file an issue.\n"), #id, fieldname, value); \
+                                       LOG_WARNF(_("Entity field %s.%s (%s) is not whitelisted. If you believe this is an error, please file an issue."), #id, fieldname, value); \
                                } \
                                this.spawnfunc_checked = true; \
                        } \
@@ -144,6 +144,7 @@ noref bool require_spawnfunc_prefix;
                FIELD_SCALAR(fld, monster_moveflags) \
                FIELD_SCALAR(fld, monster_name) \
                FIELD_SCALAR(fld, movetype) \
+               FIELD_SCALAR(fld, move_movetype) \
                FIELD_SCALAR(fld, netname) \
                FIELD_SCALAR(fld, nextthink) \
                FIELD_SCALAR(fld, noalign) \
index 8aaacdec428e366123d197810684927ed97cf030..4642f76403c3124b6cdc30fb9b3f923263394548 100644 (file)
@@ -8,6 +8,24 @@
 .int m_id;
 USING(vectori, vector);
 
+const int STATS_ENGINE_RESERVE = 32;
+// must be listed in ascending order
+#define MAGIC_STATS(_, x) \
+       _(x, MOVEVARS_TIMESCALE, 241) \
+       /**/
+
+int g_magic_stats_hole = 0;
+
+#define MAGIC_STATS_FIX_MANUAL(it, var, id) \
+       if (it.registered_id == "STAT_" #var) { --g_magic_stats_hole; it.m_id = id; } else
+
+#define MAGIC_STATS_FIX_AUTO(it, var, id) \
+       if (it.m_id == id) { ++g_magic_stats_hole; ++it.m_id; }
+
+#define MAGIC_STATS_FIX(it) \
+       it.m_id += g_magic_stats_hole; \
+       MAGIC_STATS(MAGIC_STATS_FIX_MANUAL, it) { MAGIC_STATS(MAGIC_STATS_FIX_AUTO, it) }
+
 #define REGISTER_STAT(...) EVAL_REGISTER_STAT(OVERLOAD(REGISTER_STAT, __VA_ARGS__))
 #define EVAL_REGISTER_STAT(...) __VA_ARGS__
 #if defined(CSQC)
@@ -68,8 +86,11 @@ USING(vectori, vector);
        /** Prevent engine stats being sent */
        STATIC_INIT(stats_clear)
        {
-               int r = 32;
+               int r = STATS_ENGINE_RESERVE;
                for (int i = 0, n = 256 - r; i < n; ++i) {
+                       #define X(_, name, id) if (i == id) continue;
+                       MAGIC_STATS(X, );
+                       #undef X
                        addstat(r + i, AS_INT, __stat_null);
                }
        }
@@ -99,15 +120,16 @@ USING(vectori, vector);
     #define REGISTER_STAT_3(id, T, expr)
 #endif
 
-const int STATS_ENGINE_RESERVE = 32;
-
 REGISTRY(Stats, 256 - STATS_ENGINE_RESERVE)
 REGISTER_REGISTRY(Stats)
 REGISTRY_SORT(Stats)
 REGISTRY_CHECK(Stats)
 STATIC_INIT(RegisterStats_renumber)
 {
-       FOREACH(Stats, true, it.m_id = STATS_ENGINE_RESERVE + i);
+       FOREACH(Stats, true, {
+               it.m_id = STATS_ENGINE_RESERVE + i;
+               MAGIC_STATS_FIX(it);
+       });
 }
 #ifdef SVQC
 STATIC_INIT(stats_add) { stats_add(); }
index d05ae28cd903b76edc4770204b142d5f8689c589..ff6f2d23d5b52f1e00d75ba699c6552031ba8f5b 100644 (file)
@@ -15,7 +15,7 @@
 #define SUCCEED() (TEST_ok = true)
 
 /** Add a failure, but continue */
-#define ADD_FAILURE(msg) MACRO_BEGIN { ++TEST_failed; LOG_WARNINGF(msg); } MACRO_END
+#define ADD_FAILURE(msg) MACRO_BEGIN { ++TEST_failed; LOG_WARN(msg); } MACRO_END
 
 /** Add a failure and return */
 #define FAIL(msg) _TEST_ASSERT(ADD_FAILURE(msg))
@@ -87,7 +87,7 @@ int TEST_failed;
 
 #define EXPECT_NO_FATAL_FAILURE_(statement, then) \
        EXPECT_NO_FATAL_FAILURE__(statement, { \
-               LOG_WARNINGF( \
+               LOG_WARNF( \
                        "  Actual: %d fatal failures\n" \
                        "Expected: no fatal failures\n", \
                        TEST_fatal - TEST_prevfatal \
index c4c700a72d6b8341e9e561af642d638853c78e9d..d1d5c65ed2a3d4bcf34e1a35789a709e44521c07 100644 (file)
@@ -55,7 +55,7 @@ float url_URI_Get_Callback(int id, float status, string data)
                        LOG_INFO("url_URI_Get_Callback: out of memory in buf_create\n");
                        e.url_ready(e, e.url_ready_pass, URL_READY_ERROR);
                        strunzone(e.url_url);
-                       remove(e);
+                       delete(e);
                        return 1;
                }
                e.url_rbufpos = 0;
@@ -64,7 +64,7 @@ float url_URI_Get_Callback(int id, float status, string data)
                        LOG_INFO("url_URI_Get_Callback: out of memory in buf_create\n");
                        e.url_ready(e, e.url_ready_pass, URL_READY_ERROR);
                        strunzone(e.url_url);
-                       remove(e);
+                       delete(e);
                        return 1;
                }
                for (i = 0; i < n; ++i)
@@ -77,7 +77,7 @@ float url_URI_Get_Callback(int id, float status, string data)
                // an ERROR
                e.url_ready(e, e.url_ready_pass, -fabs(status));
                strunzone(e.url_url);
-               remove(e);
+               delete(e);
                return 1;
        }
 }
@@ -107,7 +107,7 @@ void url_single_fopen(string url, int mode, url_ready_func rdy, entity pass)
                                        LOG_INFO("url_single_fopen: out of memory in buf_create\n");
                                        rdy(e, pass, URL_READY_ERROR);
                                        strunzone(e.url_url);
-                                       remove(e);
+                                       delete(e);
                                        return;
                                }
                                e.url_wbufpos = 0;
@@ -229,7 +229,7 @@ void url_fclose(entity e)
                                        e.url_ready(e, e.url_ready_pass, URL_READY_ERROR);
                                        buf_del(e.url_wbuf);
                                        strunzone(e.url_url);
-                                       remove(e);
+                                       delete(e);
                                        return;
                                }
                        }
@@ -241,7 +241,7 @@ void url_fclose(entity e)
                                e.url_ready(e, e.url_ready_pass, URL_READY_ERROR);
                                buf_del(e.url_wbuf);
                                strunzone(e.url_url);
-                               remove(e);
+                               delete(e);
                                return;
                        }
 
@@ -262,20 +262,20 @@ void url_fclose(entity e)
                        e.url_ready(e, e.url_ready_pass, URL_READY_CLOSED);
                        buf_del(e.url_rbuf);
                        strunzone(e.url_url);
-                       remove(e);
+                       delete(e);
                }
        }
        else if (e.url_fh == URL_FH_STDOUT)
        {
                e.url_ready(e, e.url_ready_pass, URL_READY_CLOSED);  // closing creates no reading handle
-               remove(e);
+               delete(e);
        }
        else
        {
                // file
                fclose(e.url_fh);
                e.url_ready(e, e.url_ready_pass, URL_READY_CLOSED);  // closing creates no reading handle
-               remove(e);
+               delete(e);
        }
 }
 
@@ -316,7 +316,7 @@ void url_fputs(entity e, string s)
        else if (e.url_fh == URL_FH_STDOUT)
        {
                // stdout
-               LOG_INFO(s);
+               print(s);
        }
        else
        {
@@ -336,7 +336,7 @@ void url_multi_ready(entity fh, entity me, float status)
                        LOG_INFO("uri_multi_ready: got HTTP error 422, data is in unusable format - not continuing\n");
                        me.url_ready(fh, me.url_ready_pass, status);
                        strunzone(me.url_url);
-                       remove(me);
+                       delete(me);
                        return;
                }
                me.url_attempt += 1;
@@ -345,7 +345,7 @@ void url_multi_ready(entity fh, entity me, float status)
                {
                        me.url_ready(fh, me.url_ready_pass, status);
                        strunzone(me.url_url);
-                       remove(me);
+                       delete(me);
                        return;
                }
                url_single_fopen(argv(me.url_attempt), me.url_mode, url_multi_ready, me);
index adb6d6a95b272fdfc59f6c650e318411ad3738c3..10e8ed8c437f98983b55945e0e938bf9f5d73e0f 100644 (file)
@@ -34,6 +34,13 @@ vector cross(vector a, vector b)
 }
 #endif
 
+noref vector _vmul_a, _vmul_b;
+#define vmul(a, b) \
+    (_vmul_a = (a), _vmul_b = (b), \
+         '1 0 0' * (_vmul_a.x * _vmul_b.x) \
+       + '0 1 0' * (_vmul_a.y * _vmul_b.y) \
+       + '0 0 1' * (_vmul_a.z * _vmul_b.z))
+
 const vector eX = '1 0 0';
 const vector eY = '0 1 0';
 const vector eZ = '0 0 1';
@@ -124,6 +131,17 @@ vector vec_reflect(vector vel, vector norm, float bounce)
        return vel - (1 + bounce) * (vel * norm) * norm;
 }
 
+vector vec_epsilon(vector this, float eps)
+{
+       if (this.x > -eps && this.x < eps) this.x = 0;
+       if (this.y > -eps && this.y < eps) this.y = 0;
+       if (this.z > -eps && this.z < eps) this.z = 0;
+       return this;
+}
+
+#define ClipVelocity(in, normal, out, overbounce) \
+       (out = vec_epsilon(vec_reflect(in, normal, (overbounce) - 1), 0.1))
+
 #ifndef MENUQC
        vector get_corner_position(entity box, int corner)
        {
index 0a10843c0087872de9ed0a0046747331d438543f..b287651a10a4fb868acdfeca18d2c0dfaf77b4d0 100644 (file)
@@ -1,5 +1,4 @@
-#ifndef LIB_WARPZONE_ANGLETRANSFORM_H
-#define LIB_WARPZONE_ANGLETRANSFORM_H
+#pragma once
 
 #ifndef POSITIVE_PITCH_IS_DOWN
 #define POSITIVE_PITCH_IS_DOWN 1
@@ -42,4 +41,3 @@ vector AnglesTransform_ToVAngles(vector v);
 // transformed = original * transform + postshift
 vector AnglesTransform_Multiply_GetPostShift(vector sf0, vector st0, vector t1, vector st1);
 vector AnglesTransform_PrePostShift_GetPostShift(vector sf, vector t, vector st);
-#endif
index 8f3e643b5c0eabae6e8d30817a40ccebc071a7df..47ff24136839d23144caa37af2c9f2265e367a57 100644 (file)
@@ -1,5 +1,4 @@
-#ifndef LIB_WARPZONE_CLIENT_H
-#define LIB_WARPZONE_CLIENT_H
+#pragma once
 
 void WarpZone_FixPMove();
 void WarpZone_FixView();
@@ -8,4 +7,3 @@ void WarpZone_Shutdown();
 
 vector warpzone_save_view_origin;
 vector warpzone_save_view_angles;
-#endif
index 5acacc7734d47953601c3fd385fa35b2f86497e4..cff5be75890ec42062ed7f95db63500d54c91e2a 100644 (file)
@@ -112,7 +112,7 @@ float WarpZoneLib_BoxTouchesBrush_Recurse()
 #ifdef CSQC
        if (trace_networkentity)
        {
-               LOG_TRACE("hit a network ent, cannot continue WarpZoneLib_BoxTouchesBrush\n");
+               LOG_TRACE("hit a network ent, cannot continue WarpZoneLib_BoxTouchesBrush");
                // we cannot continue, as a player blocks us...
                // so, abort
                return 0;
@@ -271,7 +271,7 @@ void WarpZone_TraceBox_ThroughZone(vector org, vector mi, vector ma, vector end,
        {
                if(--i < 1)
                {
-                       LOG_TRACE("Too many warpzones in sequence, aborting trace.\n");
+                       LOG_TRACE("Too many warpzones in sequence, aborting trace.");
                        trace_ent = NULL;
                        break;
                }
@@ -299,7 +299,7 @@ void WarpZone_TraceBox_ThroughZone(vector org, vector mi, vector ma, vector end,
                if(trace_ent == wz)
                {
                        // FIXME can this check be removed? Do we really need it?
-                       LOG_TRACE("I transformed into the same zone again, wtf, aborting the trace\n");
+                       LOG_TRACE("I transformed into the same zone again, wtf, aborting the trace");
                        trace_ent = NULL;
                        break;
                }
@@ -395,7 +395,7 @@ void WarpZone_TraceToss_ThroughZone(entity e, entity forent, entity zone, WarpZo
        {
                if(--i < 1)
                {
-                       LOG_TRACE("Too many warpzones in sequence, aborting trace.\n");
+                       LOG_TRACE("Too many warpzones in sequence, aborting trace.");
                        trace_ent = NULL;
                        break;
                }
@@ -413,7 +413,7 @@ void WarpZone_TraceToss_ThroughZone(entity e, entity forent, entity zone, WarpZo
                if(trace_ent == wz)
                {
                        // FIXME can this check be removed? Do we really need it?
-                       LOG_TRACE("I transformed into the same zone again, wtf, aborting the trace\n");
+                       LOG_TRACE("I transformed into the same zone again, wtf, aborting the trace");
                        trace_ent = NULL;
                        break;
                }
@@ -671,7 +671,7 @@ void WarpZone_RefSys_GC(entity this)
        // garbage collect unused reference systems
        this.nextthink = time + 1;
        if(this.owner.WarpZone_refsys != this)
-               remove(this);
+               delete(this);
 }
 void WarpZone_RefSys_CheckCreate(entity me)
 {
@@ -688,7 +688,7 @@ void WarpZone_RefSys_Clear(entity me)
 {
        if(me.WarpZone_refsys)
        {
-               remove(me.WarpZone_refsys);
+               delete(me.WarpZone_refsys);
                me.WarpZone_refsys = NULL;
        }
 }
index 6669ae1aff4d300c7cde3fc0f9bfc34ce3feb4a3..4bbbb853b00bad0266f2482cd5ef7efcccd738d3 100644 (file)
@@ -1,5 +1,4 @@
-#ifndef LIB_WARPZONE_COMMON_H
-#define LIB_WARPZONE_COMMON_H
+#pragma once
 
 // uncomment this if your mod uses the roll angle in fixangle
 // #define KEEP_ROLL
@@ -113,4 +112,3 @@ void WarpZoneLib_ExactTrigger_Init(entity this);
 // WARNING: this kills the trace globals
 #define EXACTTRIGGER_TOUCH(e,t) if(WarpZoneLib_ExactTrigger_Touch((e), (t))) return
 #define EXACTTRIGGER_INIT  WarpZoneLib_ExactTrigger_Init(this)
-#endif
index c3de3838dde28cb70ed0d9e915751554436ccd49..2b35c92f8457e6fbb00ba0f05610598ea10faa5e 100644 (file)
@@ -1,5 +1,4 @@
-#ifndef LIB_WARPZONE_MATHLIB_H
-#define LIB_WARPZONE_MATHLIB_H
+#pragma once
 
 // <math.h>
 
@@ -114,5 +113,3 @@ const float M_2_PI     = 0.63661977236758134308;  /* 2/pi */
 const float M_2_SQRTPI = 1.12837916709551257390;  /* 2/sqrt(pi) */
 const float M_SQRT2    = 1.41421356237309504880;  /* sqrt(2) */
 const float M_SQRT1_2  = 0.70710678118654752440;  /* 1/sqrt(2) */
-
-#endif
index f1bd0e524e5bbd3c6cebaa2784c0c226579fa765..de692ee8198f06577d1e2f38406e3ed9b0c6e466 100644 (file)
@@ -225,7 +225,7 @@ void WarpZone_Touch(entity this, entity toucher)
        }
        else
        {
-               LOG_TRACE("WARPZONE FAIL AHAHAHAHAH))\n");
+               LOG_TRACE("WARPZONE FAIL AHAHAHAHAH))");
        }
 }
 
index 0ec67e4d38125b4eefe5f147a2c10ed4f5ee65e8..b0c583d2dc7bf31728f28e0d53de23219f689c22 100644 (file)
@@ -1,5 +1,4 @@
-#ifndef LIB_WARPZONE_SERVER_H
-#define LIB_WARPZONE_SERVER_H
+#pragma once
 
 #ifdef SVQC
 void WarpZone_StartFrame();
@@ -17,5 +16,3 @@ void WarpZone_PlayerPhysics_FixVAngle(entity this);
 
 void WarpZone_PostInitialize_Callback();
 #endif
-
-#endif
index 39d1d24699caab93e8d209c4489844f7cbd6fb5c..b73289927b474878d93081425a75876f7b2ae62d 100644 (file)
@@ -1,9 +1,7 @@
-#ifndef LIB_WARPZONE_UTIL_SERVER_H
-#define LIB_WARPZONE_UTIL_SERVER_H
+#pragma once
 
 float WarpZoneLib_MoveOutOfSolid(entity e);
 float WarpZoneLib_ExactTrigger_Touch(entity this, entity toucher);
 #ifdef SVQC
 void WarpZoneLib_ExactTrigger_Init(entity this);
 #endif
-#endif
index 0427f322ae3884c451f0954ba3cafcc3b962660b..009feb577c00fbaa1454ed373845f7cd6998fedb 100644 (file)
@@ -15,14 +15,14 @@ CLASS(Animation, Object)
        METHOD(Animation, resumeAnim, void(Animation this));
        METHOD(Animation, isFinished, float(Animation this));
        METHOD(Animation, finishAnim, void(Animation this));
-       ATTRIB(Animation, object, entity, NULL)
+       ATTRIB(Animation, object, entity);
        void setterDummy(Animation this, float) {}
-       ATTRIB(Animation, setter, void(Animation this, float), setterDummy)
-       ATTRIB(Animation, value, float, 0)
-       ATTRIB(Animation, startTime, float, 0)
-       ATTRIB(Animation, duration, float, 0)
-       ATTRIB(Animation, startValue, float, 0)
-       ATTRIB(Animation, delta, float, 0)
-       ATTRIB(Animation, stopped, float, false)
-       ATTRIB(Animation, finished, float, false)
+       ATTRIB(Animation, setter, void(Animation this, float), setterDummy);
+       ATTRIB(Animation, value, float, 0);
+       ATTRIB(Animation, startTime, float, 0);
+       ATTRIB(Animation, duration, float, 0);
+       ATTRIB(Animation, startValue, float, 0);
+       ATTRIB(Animation, delta, float, 0);
+       ATTRIB(Animation, stopped, float, false);
+       ATTRIB(Animation, finished, float, false);
 ENDCLASS(Animation)
index 5e39191dd658c71d38dd363393483854ba7cb3e4..3009ab4eaf8b00f47fd4efdf362b3c0ba42b67b0 100644 (file)
@@ -37,7 +37,7 @@
 
                if (n) n.prevSibling = p;
                else this.lastChild = p;
-               remove(other);
+               delete(other);
        }
 
        METHOD(AnimHost, removeAllAnim, void(entity this))
index 1292b7d8b4e25380f57edb8cd89b4ce1c287460d..85b03aecf35cf7ae93ee5050dde2efe3108cfd48 100644 (file)
@@ -14,6 +14,6 @@ CLASS(AnimHost, Object)
        METHOD(AnimHost, finishAllAnim, void(entity));
        METHOD(AnimHost, finishObjAnim, void(entity, entity));
        METHOD(AnimHost, tickAll, void(entity));
-       ATTRIB(AnimHost, firstChild, entity, NULL)
-       ATTRIB(AnimHost, lastChild, entity, NULL)
+       ATTRIB(AnimHost, firstChild, entity);
+       ATTRIB(AnimHost, lastChild, entity);
 ENDCLASS(AnimHost)
index 832a87c73bc070d069ab376e3e8e0832e3bcfcb9..bb2c0dbc0a6c39076ca516994aac715625763853 100644 (file)
@@ -10,5 +10,5 @@ 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)
+       ATTRIB(Easing, math, float(float, float, float, float), easingLinear);
 ENDCLASS(Easing)
index d21db6920bb198be95815379f4a7adc61c98de7b..abf18de96fcc7598d9d8b100a8893c4a8f52a56b 100644 (file)
@@ -5,9 +5,9 @@ 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));
-       ATTRIB(Keyframe, currentChild, entity, NULL)
-       ATTRIB(Keyframe, firstChild, entity, NULL)
-       ATTRIB(Keyframe, lastChild, entity, NULL)
+       ATTRIB(Keyframe, currentChild, entity);
+       ATTRIB(Keyframe, firstChild, entity);
+       ATTRIB(Keyframe, lastChild, entity);
 ENDCLASS(Keyframe)
 entity makeHostedKeyframe(entity, void(entity, float), float, float, float);
 entity makeKeyframe(entity, void(entity, float), float, float, float);
index 283cca0c1b98b1d0c5dfc61917c00c946175c43f..2f8df96b6bfb57d773d6e237a6ad9f542c63f3a4 100644 (file)
@@ -1 +1,3 @@
+#include "all.qh"
+
 #include <common/command/all.qc>
diff --git a/qcsrc/menu/command/all.qh b/qcsrc/menu/command/all.qh
new file mode 100644 (file)
index 0000000..6f70f09
--- /dev/null
@@ -0,0 +1 @@
+#pragma once
index b2ce50382a5e16b7a647085f93cd59ad16aede0f..01184a4bf5d026e2c5c0580c8ef625e07610772a 100644 (file)
@@ -271,7 +271,7 @@ void draw_BorderPicture(vector theOrigin, string pic, vector theSize, vector the
 void draw_Text(vector theOrigin, string theText, vector theSize, vector theColor, float theAlpha, float ICanHasKallerz)
 {
        if(theSize.x <= 0 || theSize.y <= 0) {
-               LOG_TRACE("Drawing zero size text?\n");
+               LOG_TRACE("Drawing zero size text?");
                return;
        }
 
index 118a45426788a044479e882f2961a7ae0ede0605..00dae2ed37db4ae2eb84c01977b2a78917831ebb 100644 (file)
@@ -19,12 +19,12 @@ CLASS(Item, Object)
        METHOD(Item, hideNotify, void(Item));
        METHOD(Item, toString, string(Item));
        METHOD(Item, destroy, void(Item));
-       ATTRIB(Item, focused, float, 0)
-       ATTRIB(Item, focusable, float, 0)
-       ATTRIB(Item, allowFocusSound, float, 0)
-       ATTRIB(Item, parent, entity, NULL)
-       ATTRIB(Item, preferredFocusPriority, float, 0)
-       ATTRIB(Item, origin, vector, '0 0 0')
-       ATTRIB(Item, size, vector, '0 0 0')
-       ATTRIB(Item, tooltip, string, string_null)
+       ATTRIB(Item, focused, float, 0);
+       ATTRIB(Item, focusable, float, 0);
+       ATTRIB(Item, allowFocusSound, float, 0);
+       ATTRIB(Item, parent, entity);
+       ATTRIB(Item, preferredFocusPriority, float, 0);
+       ATTRIB(Item, origin, vector, '0 0 0');
+       ATTRIB(Item, size, vector, '0 0 0');
+       ATTRIB(Item, tooltip, string);
 ENDCLASS(Item)
index c956d362d22827af30204d1c7f2e45d561512ea7..9db9360f8f08a2fd2236a5ef17e7dbbf0f3c4ec0 100644 (file)
@@ -5,21 +5,21 @@ 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));
-       ATTRIB(BorderImage, isBold, float, 1)
+       ATTRIB(BorderImage, isBold, float, 1);
        METHOD(BorderImage, draw, void(entity));
-       ATTRIB(BorderImage, src, string, string_null)
-       ATTRIB(BorderImage, borderHeight, float, 0)
-       ATTRIB(BorderImage, borderVec, vector, '0 0 0')
-       ATTRIB(BorderImage, color, vector, '1 1 1')
-       ATTRIB(BorderImage, closeButton, entity, NULL)
-       ATTRIB(BorderImage, realFontSize_Nexposeed, vector, '0 0 0')
-       ATTRIB(BorderImage, realOrigin_Nexposeed, vector, '0 0 0')
-       ATTRIB(BorderImage, isNexposeeTitleBar, float, 0)
-       ATTRIB(BorderImage, zoomedOutTitleBarPosition, float, 0)
-       ATTRIB(BorderImage, zoomedOutTitleBar, float, 0)
-       ATTRIB(BorderImage, overrideRealOrigin, vector, '0 1 0')
-       ATTRIB(BorderImage, saveRelOrigin, vector, '0 0 0')
-       ATTRIB(BorderImage, saveRelSize, vector, '0 0 0')
+       ATTRIB(BorderImage, src, string);
+       ATTRIB(BorderImage, borderHeight, float, 0);
+       ATTRIB(BorderImage, borderVec, vector, '0 0 0');
+       ATTRIB(BorderImage, color, vector, '1 1 1');
+       ATTRIB(BorderImage, closeButton, entity);
+       ATTRIB(BorderImage, realFontSize_Nexposeed, vector, '0 0 0');
+       ATTRIB(BorderImage, realOrigin_Nexposeed, vector, '0 0 0');
+       ATTRIB(BorderImage, isNexposeeTitleBar, float, 0);
+       ATTRIB(BorderImage, zoomedOutTitleBarPosition, float, 0);
+       ATTRIB(BorderImage, zoomedOutTitleBar, float, 0);
+       ATTRIB(BorderImage, overrideRealOrigin, vector, '0 1 0');
+       ATTRIB(BorderImage, saveRelOrigin, vector, '0 0 0');
+       ATTRIB(BorderImage, saveRelSize, vector, '0 0 0');
 ENDCLASS(BorderImage)
 
 .vector colorC, colorF;
index 6fd2bc8882b032c00b924765c8cee27015bdbccb..1a164245c8f269368067b3b43c4ae6f92fd9066f 100644 (file)
@@ -13,30 +13,30 @@ CLASS(Button, Label)
        METHOD(Button, mouseDrag, float(entity, vector));
        METHOD(Button, mouseRelease, float(entity, vector));
        METHOD(Button, playClickSound, void(entity));
-       ATTRIB(Button, onClick, void(entity, entity), func_null)
-       ATTRIB(Button, onClickEntity, entity, NULL)
-       ATTRIB(Button, src, string, string_null)
-       ATTRIB(Button, srcSuffix, string, string_null)
-       ATTRIB(Button, src2, string, string_null) // is centered, same aspect, and stretched to label size
-       ATTRIB(Button, src2scale, float, 1)
-       ATTRIB(Button, srcMulti, float, 1)        // 0: button square left, text right; 1: button stretched, text over it
-       ATTRIB(Button, buttonLeftOfText, float, 0)
-       ATTRIB(Button, focusable, float, 1)
-       ATTRIB(Button, allowFocusSound, float, 1)
-       ATTRIB(Button, pressed, float, 0)
-       ATTRIB(Button, clickTime, float, 0)
-       ATTRIB(Button, applyButton, entity, NULL)
-       ATTRIB(Button, disableOnClick, bool, false)
-       ATTRIB(Button, disabled, float, 0)
-       ATTRIB(Button, disabledAlpha, float, 0.3)
-       ATTRIB(Button, forcePressed, float, 0)
-       ATTRIB(Button, color, vector, '1 1 1')
-       ATTRIB(Button, colorC, vector, '1 1 1')
-       ATTRIB(Button, colorF, vector, '1 1 1')
-       ATTRIB(Button, colorD, vector, '1 1 1')
-       ATTRIB(Button, color2, vector, '1 1 1')
-       ATTRIB(Button, alpha2, float, 1)
+       ATTRIB(Button, onClick, void(entity, entity));
+       ATTRIB(Button, onClickEntity, entity);
+       ATTRIB(Button, src, string);
+       ATTRIB(Button, srcSuffix, string);
+       ATTRIB(Button, src2, string); // is centered, same aspect, and stretched to label size
+       ATTRIB(Button, src2scale, float, 1);
+       ATTRIB(Button, srcMulti, float, 1);        // 0: button square left, text right; 1: button stretched, text over it
+       ATTRIB(Button, buttonLeftOfText, float, 0);
+       ATTRIB(Button, focusable, float, 1);
+       ATTRIB(Button, allowFocusSound, float, 1);
+       ATTRIB(Button, pressed, float, 0);
+       ATTRIB(Button, clickTime, float, 0);
+       ATTRIB(Button, applyButton, entity);
+       ATTRIB(Button, disableOnClick, bool, false);
+       ATTRIB(Button, disabled, float, 0);
+       ATTRIB(Button, disabledAlpha, float, 0.3);
+       ATTRIB(Button, forcePressed, float, 0);
+       ATTRIB(Button, color, vector, '1 1 1');
+       ATTRIB(Button, colorC, vector, '1 1 1');
+       ATTRIB(Button, colorF, vector, '1 1 1');
+       ATTRIB(Button, colorD, vector, '1 1 1');
+       ATTRIB(Button, color2, vector, '1 1 1');
+       ATTRIB(Button, alpha2, float, 1);
 
-       ATTRIB(Button, origin, vector, '0 0 0')
-       ATTRIB(Button, size, vector, '0 0 0')
+       ATTRIB(Button, origin, vector, '0 0 0');
+       ATTRIB(Button, size, vector, '0 0 0');
 ENDCLASS(Button)
index 32f6b0f5023a22eb89698851804093ce07956789..931e4f79c8f1c09f32270b9ae8aa1c5b2b23f12d 100644 (file)
@@ -7,10 +7,10 @@ CLASS(CheckBox, Button)
        METHOD(CheckBox, playClickSound, void(entity));
        METHOD(CheckBox, toString, string(entity));
        METHOD(CheckBox, setChecked, void(entity, float));
-       ATTRIB(CheckBox, useDownAsChecked, float, 0)
-       ATTRIB(CheckBox, checked, float, 0)
+       ATTRIB(CheckBox, useDownAsChecked, float, 0);
+       ATTRIB(CheckBox, checked, float, 0);
     void CheckBox_Click(entity me, entity other);
-       ATTRIB(CheckBox, onClick, void(entity, entity), CheckBox_Click)
-       ATTRIB(CheckBox, srcMulti, float, 0)
-       ATTRIB(CheckBox, disabled, float, 0)
+       ATTRIB(CheckBox, onClick, void(entity, entity), CheckBox_Click);
+       ATTRIB(CheckBox, srcMulti, float, 0);
+       ATTRIB(CheckBox, disabled, float, 0);
 ENDCLASS(CheckBox)
index dbb4cf2211c27f2b641c9d017e42fe353cfa512e..8273f5ddde38a43ec3e153d3a5f02247f452a775 100644 (file)
@@ -25,12 +25,12 @@ CLASS(Container, Item)
        METHOD(Container, showNotify, void(entity));
        METHOD(Container, hideNotify, void(entity));
        METHOD(Container, preferredFocusedGrandChild, entity(entity));
-       ATTRIB(Container, focusable, float, 0)
-       ATTRIB(Container, firstChild, entity, NULL)
-       ATTRIB(Container, lastChild, entity, NULL)
-       ATTRIB(Container, focusedChild, entity, NULL)
-       ATTRIB(Container, savedFocus, entity, NULL)
-       ATTRIB(Container, shown, float, 0)
+       ATTRIB(Container, focusable, float, 0);
+       ATTRIB(Container, firstChild, entity);
+       ATTRIB(Container, lastChild, entity);
+       ATTRIB(Container, focusedChild, entity);
+       ATTRIB(Container, savedFocus, entity);
+       ATTRIB(Container, shown, float, 0);
 
        METHOD(Container, enterSubitem, void(entity, entity));
        METHOD(Container, enterLieSubitem, void(entity, vector, vector, vector, float));
index 17343e7cd2f3697d7914f8d29742ddf125465ea2..6099fea22d77f28de06cad990d54b597717f45e3 100644 (file)
@@ -30,43 +30,43 @@ CLASS(Dialog, InputContainer)
        METHOD(Dialog, TR, void(entity));
        METHOD(Dialog, gotoRC, void(entity, float, float));
 
-       ATTRIB(Dialog, isTabRoot, float, 1)
-       ATTRIB(Dialog, closeButton, entity, NULL)
-       ATTRIB(Dialog, intendedHeight, float, 0)
-       ATTRIB(Dialog, itemOrigin, vector, '0 0 0')
-       ATTRIB(Dialog, itemSize, vector, '0 0 0')
-       ATTRIB(Dialog, itemSpacing, vector, '0 0 0')
-       ATTRIB(Dialog, currentRow, float, 0)
-       ATTRIB(Dialog, currentColumn, float, 0)
-       ATTRIB(Dialog, firstColumn, float, 0)
+       ATTRIB(Dialog, isTabRoot, float, 1);
+       ATTRIB(Dialog, closeButton, entity);
+       ATTRIB(Dialog, intendedHeight, float, 0);
+       ATTRIB(Dialog, itemOrigin, vector, '0 0 0');
+       ATTRIB(Dialog, itemSize, vector, '0 0 0');
+       ATTRIB(Dialog, itemSpacing, vector, '0 0 0');
+       ATTRIB(Dialog, currentRow, float, 0);
+       ATTRIB(Dialog, currentColumn, float, 0);
+       ATTRIB(Dialog, firstColumn, float, 0);
 
        // to be customized
-       ATTRIB(Dialog, closable, float, 1)
-       ATTRIB(Dialog, title, string, "Form1")  // ;)
-       ATTRIB(Dialog, color, vector, '1 0.5 1')
-       ATTRIB(Dialog, intendedWidth, float, 0)
-       ATTRIB(Dialog, rows, float, 3)
-       ATTRIB(Dialog, columns, float, 2)
+       ATTRIB(Dialog, closable, float, 1);
+       ATTRIB(Dialog, title, string, "Form1");
+       ATTRIB(Dialog, color, vector, '1 0.5 1');
+       ATTRIB(Dialog, intendedWidth, float, 0);
+       ATTRIB(Dialog, rows, float, 3);
+       ATTRIB(Dialog, columns, float, 2);
 
-       ATTRIB(Dialog, marginTop, float, 0)     // pixels
-       ATTRIB(Dialog, marginBottom, float, 0)  // pixels
-       ATTRIB(Dialog, marginLeft, float, 0)    // pixels
-       ATTRIB(Dialog, marginRight, float, 0)   // pixels
-       ATTRIB(Dialog, columnSpacing, float, 0) // pixels
-       ATTRIB(Dialog, rowSpacing, float, 0)    // pixels
-       ATTRIB(Dialog, rowHeight, float, 0)     // pixels
-       ATTRIB(Dialog, titleHeight, float, 0)   // pixels
-       ATTRIB(Dialog, titleFontSize, float, 0) // pixels; if 0, title causes no margin
-       ATTRIB(Dialog, zoomedOutTitleBarPosition, float, 0)
-       ATTRIB(Dialog, zoomedOutTitleBar, float, 0)
+       ATTRIB(Dialog, marginTop, float, 0);     // pixels
+       ATTRIB(Dialog, marginBottom, float, 0);  // pixels
+       ATTRIB(Dialog, marginLeft, float, 0);    // pixels
+       ATTRIB(Dialog, marginRight, float, 0);   // pixels
+       ATTRIB(Dialog, columnSpacing, float, 0); // pixels
+       ATTRIB(Dialog, rowSpacing, float, 0);    // pixels
+       ATTRIB(Dialog, rowHeight, float, 0);     // pixels
+       ATTRIB(Dialog, titleHeight, float, 0);   // pixels
+       ATTRIB(Dialog, titleFontSize, float, 0); // pixels; if 0, title causes no margin
+       ATTRIB(Dialog, zoomedOutTitleBarPosition, float, 0);
+       ATTRIB(Dialog, zoomedOutTitleBar, float, 0);
 
-       ATTRIB(Dialog, requiresConnection, float, 0)  // set to true if the dialog requires a connection to be opened
+       ATTRIB(Dialog, requiresConnection, float, 0);  // set to true if the dialog requires a connection to be opened
 
-       ATTRIB(Dialog, backgroundImage, string, string_null)
-       ATTRIB(Dialog, borderLines, float, 1)
-       ATTRIB(Dialog, closeButtonImage, string, string_null)
+       ATTRIB(Dialog, backgroundImage, string);
+       ATTRIB(Dialog, borderLines, float, 1);
+       ATTRIB(Dialog, closeButtonImage, string);
 
-       ATTRIB(Dialog, frame, entity, NULL)
+       ATTRIB(Dialog, frame, entity);
 ENDCLASS(Dialog)
 
 void Dialog_Close(entity button, entity me);
index 35bca5985a056c7fc949d027caaa8f655d486cbb..726f328600d79b570c210b3bb234006868ef2982 100644 (file)
@@ -11,18 +11,18 @@ CLASS(Image, Item)
        METHOD(Image, setZoom, void(entity, float, float));
        METHOD(Image, drag_setStartPos, float(entity, vector));
        METHOD(Image, drag, float(entity, vector));
-       ATTRIB(Image, src, string, string_null)
-       ATTRIB(Image, color, vector, '1 1 1')
-       ATTRIB(Image, forcedAspect, float, 0)        // special values: -1 keep image aspect ratio, -2 keep image size but bound to the containing box, -3 always keep image size
-       ATTRIB(Image, zoomBox, float, 0)             // used by forcedAspect -2 when the image is larger than the containing box
-       ATTRIB(Image, zoomFactor, float, 1)
-       ATTRIB(Image, zoomOffset, vector, '0.5 0.5 0')
-       ATTRIB(Image, zoomSnapToTheBox, float, 1)    // snap the zoomed in image to the box borders when zooming/dragging it
-       ATTRIB(Image, zoomTime, float, 0)
-       ATTRIB(Image, zoomLimitedByTheBox, float, 0) // forbids zoom if image would be larger than the containing box
-       ATTRIB(Image, zoomMax, float, 0)
-       ATTRIB(Image, start_zoomOffset, vector, '0 0 0')
-       ATTRIB(Image, start_coords, vector, '0 0 0')
-       ATTRIB(Image, imgOrigin, vector, '0 0 0')
-       ATTRIB(Image, imgSize, vector, '0 0 0')
+       ATTRIB(Image, src, string);
+       ATTRIB(Image, color, vector, '1 1 1');
+       ATTRIB(Image, forcedAspect, float, 0);        // special values: -1 keep image aspect ratio, -2 keep image size but bound to the containing box, -3 always keep image size
+       ATTRIB(Image, zoomBox, float, 0);             // used by forcedAspect -2 when the image is larger than the containing box
+       ATTRIB(Image, zoomFactor, float, 1);
+       ATTRIB(Image, zoomOffset, vector, '0.5 0.5 0');
+       ATTRIB(Image, zoomSnapToTheBox, float, 1);    // snap the zoomed in image to the box borders when zooming/dragging it
+       ATTRIB(Image, zoomTime, float, 0);
+       ATTRIB(Image, zoomLimitedByTheBox, float, 0); // forbids zoom if image would be larger than the containing box
+       ATTRIB(Image, zoomMax, float, 0);
+       ATTRIB(Image, start_zoomOffset, vector, '0 0 0');
+       ATTRIB(Image, start_coords, vector, '0 0 0');
+       ATTRIB(Image, imgOrigin, vector, '0 0 0');
+       ATTRIB(Image, imgSize, vector, '0 0 0');
 ENDCLASS(Image)
index cfb576cfaa3c4544fec21fd9b286bb9cc7c90553..e3eede653b9c0c297bf698b36ed1b4108ae5035b 100644 (file)
@@ -14,31 +14,31 @@ CLASS(InputBox, Label)
        METHOD(InputBox, showNotify, void(entity));
        METHOD(InputBox, resizeNotify, void(entity, vector, vector, vector, vector));
 
-       ATTRIB(InputBox, src, string, string_null)
+       ATTRIB(InputBox, src, string);
 
-       ATTRIB(InputBox, cursorPos, float, 0)  // characters
-       ATTRIB(InputBox, scrollPos, float, 0)  // widths
+       ATTRIB(InputBox, cursorPos, float, 0);  // characters
+       ATTRIB(InputBox, scrollPos, float, 0);  // widths
 
-       ATTRIB(InputBox, focusable, float, 1)
-       ATTRIB(InputBox, allowFocusSound, float, 1)
-       ATTRIB(InputBox, disabled, float, 0)
-       ATTRIB(InputBox, lastChangeTime, float, 0)
-       ATTRIB(InputBox, dragScrollTimer, float, 0)
-       ATTRIB(InputBox, dragScrollPos, vector, '0 0 0')
-       ATTRIB(InputBox, pressed, float, 0)
-       ATTRIB(InputBox, editColorCodes, float, 1)
-       ATTRIB(InputBox, forbiddenCharacters, string, "")
-       ATTRIB(InputBox, color, vector, '1 1 1')
-       ATTRIB(InputBox, colorF, vector, '1 1 1')
-       ATTRIB(InputBox, maxLength, float, 255)  // if negative, it counts bytes, not chars
-       ATTRIB(InputBox, applyButton, entity, NULL)
+       ATTRIB(InputBox, focusable, float, 1);
+       ATTRIB(InputBox, allowFocusSound, float, 1);
+       ATTRIB(InputBox, disabled, float, 0);
+       ATTRIB(InputBox, lastChangeTime, float, 0);
+       ATTRIB(InputBox, dragScrollTimer, float, 0);
+       ATTRIB(InputBox, dragScrollPos, vector, '0 0 0');
+       ATTRIB(InputBox, pressed, float, 0);
+       ATTRIB(InputBox, editColorCodes, float, 1);
+       ATTRIB(InputBox, forbiddenCharacters, string, "");
+       ATTRIB(InputBox, color, vector, '1 1 1');
+       ATTRIB(InputBox, colorF, vector, '1 1 1');
+       ATTRIB(InputBox, maxLength, float, 255);  // if negative, it counts bytes, not chars
+       ATTRIB(InputBox, applyButton, entity);
 
-       ATTRIB(InputBox, enableClearButton, float, 1)
-       ATTRIB(InputBox, clearButton, entity, NULL)
-       ATTRIB(InputBox, cb_width, float, 0)
-       ATTRIB(InputBox, cb_pressed, float, 0)
-       ATTRIB(InputBox, cb_focused, float, 0)
-       ATTRIB(InputBox, cb_color, vector, '1 1 1')
-       ATTRIB(InputBox, cb_colorF, vector, '1 1 1')
-       ATTRIB(InputBox, cb_colorC, vector, '1 1 1')
+       ATTRIB(InputBox, enableClearButton, float, 1);
+       ATTRIB(InputBox, clearButton, entity);
+       ATTRIB(InputBox, cb_width, float, 0);
+       ATTRIB(InputBox, cb_pressed, float, 0);
+       ATTRIB(InputBox, cb_focused, float, 0);
+       ATTRIB(InputBox, cb_color, vector, '1 1 1');
+       ATTRIB(InputBox, cb_colorF, vector, '1 1 1');
+       ATTRIB(InputBox, cb_colorC, vector, '1 1 1');
 ENDCLASS(InputBox)
index 5d84189fafeb34653d352b98699be757bea5b51f..9ae4a537506bcad1a54fb7721b7816dd74685d35 100644 (file)
@@ -11,6 +11,6 @@ CLASS(InputContainer, Container)
        METHOD(InputContainer, resizeNotify, void(entity, vector, vector, vector, vector));
 
        METHOD(InputContainer, _changeFocusXY, bool(entity this, vector pos));
-       ATTRIB(InputContainer, mouseFocusedChild, entity, NULL)
-       ATTRIB(InputContainer, isTabRoot, float, 0)
+       ATTRIB(InputContainer, mouseFocusedChild, entity);
+       ATTRIB(InputContainer, isTabRoot, float, 0);
 ENDCLASS(InputContainer)
index ca9ec00b09dd0f90618c935575e47e9108b239b7..d21b5676bd597d32da93d61b3f3a850d15d5af7b 100644 (file)
@@ -38,7 +38,7 @@
                {
                        if (!me.overrideRealOrigin_x) me.realOrigin_x = me.keepspaceLeft;
                        if (!me.overrideCondenseFactor) me.condenseFactor = spaceAvail / spaceUsed;
-                       LOG_TRACEF("NOTE: label text %s too wide for label, condensed by factor %f\n", t, me.condenseFactor);
+                       LOG_TRACEF("NOTE: label text %s too wide for label, condensed by factor %f", t, me.condenseFactor);
                }
 
                if (!me.overrideRealOrigin_y)
index 428958c20107c0fbf52dfbabe7304ee9b45765bf..f91ae8ad3cb12a13265d085fe937cf32959f2a95 100644 (file)
@@ -8,27 +8,27 @@ CLASS(Label, Item)
        METHOD(Label, setText, void(entity, string));
        METHOD(Label, toString, string(entity));
        METHOD(Label, recalcPositionWithText, void(entity, string));
-       ATTRIB(Label, isBold, float, 0)
-       ATTRIB(Label, text, string, string_null)
-       ATTRIB(Label, currentText, string, string_null)
-       ATTRIB(Label, fontSize, float, 8)
-       ATTRIB(Label, align, float, 0.5)
-       ATTRIB(Label, allowCut, float, 0)
-       ATTRIB(Label, allowColors, float, 0)
-       ATTRIB(Label, keepspaceLeft, float, 0) // for use by subclasses (radiobuttons for example)
-       ATTRIB(Label, keepspaceRight, float, 0)
-       ATTRIB(Label, marginLeft, float, 0)    // alternate way to specify keepspace* (in characters from the font)
-       ATTRIB(Label, marginRight, float, 0)
-       ATTRIB(Label, realFontSize, vector, '0 0 0')
-       ATTRIB(Label, realOrigin, vector, '0 0 0')
-       ATTRIB(Label, alpha, float, 0.7)
-       ATTRIB(Label, colorL, vector, SKINCOLOR_TEXT)
-       ATTRIB(Label, disabled, float, 0)
-       ATTRIB(Label, disabledAlpha, float, 0.3)
-       ATTRIB(Label, textEntity, entity, NULL)
-       ATTRIB(Label, allowWrap, float, 0)
-       ATTRIB(Label, recalcPos, float, 0)
-       ATTRIB(Label, condenseFactor, float, 1)
-       ATTRIB(Label, overrideRealOrigin, vector, '0 0 0')
-       ATTRIB(Label, overrideCondenseFactor, float, 0)
+       ATTRIB(Label, isBold, float, 0);
+       ATTRIB(Label, text, string);
+       ATTRIB(Label, currentText, string);
+       ATTRIB(Label, fontSize, float, 8);
+       ATTRIB(Label, align, float, 0.5);
+       ATTRIB(Label, allowCut, float, 0);
+       ATTRIB(Label, allowColors, float, 0);
+       ATTRIB(Label, keepspaceLeft, float, 0); // for use by subclasses (radiobuttons for example);
+       ATTRIB(Label, keepspaceRight, float, 0);
+       ATTRIB(Label, marginLeft, float, 0);    // alternate way to specify keepspace* (in characters from the font);
+       ATTRIB(Label, marginRight, float, 0);
+       ATTRIB(Label, realFontSize, vector, '0 0 0');
+       ATTRIB(Label, realOrigin, vector, '0 0 0');
+       ATTRIB(Label, alpha, float, 0.7);
+       ATTRIB(Label, colorL, vector, SKINCOLOR_TEXT);
+       ATTRIB(Label, disabled, float, 0);
+       ATTRIB(Label, disabledAlpha, float, 0.3);
+       ATTRIB(Label, textEntity, entity);
+       ATTRIB(Label, allowWrap, float, 0);
+       ATTRIB(Label, recalcPos, float, 0);
+       ATTRIB(Label, condenseFactor, float, 1);
+       ATTRIB(Label, overrideRealOrigin, vector, '0 0 0');
+       ATTRIB(Label, overrideCondenseFactor, float, 0);
 ENDCLASS(Label)
index 461125e303fbc34bb2e41c9c2344f5cdf21a450d..56fda91cc15d82e163e362e9a250c38a8c1bb525 100644 (file)
@@ -11,46 +11,46 @@ CLASS(ListBox, Item)
        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, focusable, float, 1);
+       ATTRIB(ListBox, focusedItem, int, -1);
+       ATTRIB(ListBox, focusedItemAlpha, float, 0.3);
        METHOD(ListBox, setFocusedItem, void(entity, int));
-       ATTRIB(ListBox, mouseMoveOffset, float, -1)  // let know where the cursor is when the list scrolls without moving the cursor
-       ATTRIB(ListBox, allowFocusSound, float, 1)
-       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
-       ATTRIB(ListBox, scrollPosTarget, float, 0)
+       ATTRIB(ListBox, mouseMoveOffset, float, -1);  // let know where the cursor is when the list scrolls without moving the cursor
+       ATTRIB(ListBox, allowFocusSound, float, 1);
+       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
+       ATTRIB(ListBox, scrollPosTarget, float, 0);
        METHOD(ListBox, isScrolling, bool(entity));
-       ATTRIB(ListBox, needScrollToItem, float, -1)
+       ATTRIB(ListBox, needScrollToItem, float, -1);
        METHOD(ListBox, scrollToItem, void(entity, int));
-       ATTRIB(ListBox, previousValue, float, 0)
-       ATTRIB(ListBox, pressed, float, 0)  // 0 = normal, 1 = scrollbar dragging, 2 = item dragging, 3 = released
-       ATTRIB(ListBox, pressOffset, float, 0)
+       ATTRIB(ListBox, previousValue, float, 0);
+       ATTRIB(ListBox, pressed, float, 0);  // 0 = normal, 1 = scrollbar dragging, 2 = item dragging, 3 = released
+       ATTRIB(ListBox, pressOffset, float, 0);
 
        METHOD(ListBox, updateControlTopBottom, void(entity));
-       ATTRIB(ListBox, controlTop, float, 0)
-       ATTRIB(ListBox, controlBottom, float, 0)
-       ATTRIB(ListBox, controlWidth, float, 0)
-       ATTRIB(ListBox, dragScrollPos, vector, '0 0 0')
-       ATTRIB(ListBox, selectionDoesntMatter, bool, false) // improves scrolling by keys for lists that don't need to show an active selection
+       ATTRIB(ListBox, controlTop, float, 0);
+       ATTRIB(ListBox, controlBottom, float, 0);
+       ATTRIB(ListBox, controlWidth, float, 0);
+       ATTRIB(ListBox, dragScrollPos, vector, '0 0 0');
+       ATTRIB(ListBox, selectionDoesntMatter, bool, false); // improves scrolling by keys for lists that don't need to show an active selection
 
-       ATTRIB(ListBox, src, string, string_null)           // scrollbar
-       ATTRIB(ListBox, color, vector, '1 1 1')
-       ATTRIB(ListBox, color2, vector, '1 1 1')
-       ATTRIB(ListBox, colorC, vector, '1 1 1')
-       ATTRIB(ListBox, colorF, vector, '1 1 1')
-       ATTRIB(ListBox, tolerance, vector, '0 0 0') // drag tolerance
-       ATTRIB(ListBox, scrollbarWidth, float, 0)   // pixels
-       ATTRIB(ListBox, nItems, float, 42)          // FIXME: why?!?
-       ATTRIB(ListBox, itemHeight, float, 0)
-    ATTRIB(ListBox, itemAbsSize, vector, '0 0 0')
-       ATTRIB(ListBox, colorBG, vector, '0 0 0')
-       ATTRIB(ListBox, alphaBG, float, 0)
+       ATTRIB(ListBox, src, string);           // scrollbar
+       ATTRIB(ListBox, color, vector, '1 1 1');
+       ATTRIB(ListBox, color2, vector, '1 1 1');
+       ATTRIB(ListBox, colorC, vector, '1 1 1');
+       ATTRIB(ListBox, colorF, vector, '1 1 1');
+       ATTRIB(ListBox, tolerance, vector, '0 0 0'); // drag tolerance
+       ATTRIB(ListBox, scrollbarWidth, float, 0);   // pixels
+       ATTRIB(ListBox, nItems, float, 42);          // FIXME: why?!?
+       ATTRIB(ListBox, itemHeight, float, 0);
+    ATTRIB(ListBox, itemAbsSize, vector, '0 0 0');
+       ATTRIB(ListBox, colorBG, vector, '0 0 0');
+       ATTRIB(ListBox, alphaBG, float, 0);
 
-       ATTRIB(ListBox, lastClickedItem, float, -1)
-       ATTRIB(ListBox, lastClickedTime, float, 0)
+       ATTRIB(ListBox, lastClickedItem, float, -1);
+       ATTRIB(ListBox, lastClickedTime, float, 0);
 
        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
index 27faaa86bfbc15b2df1e97d163198e35c1cd4d96..e950b8d87ebc99cbb5e00e030e995e72a6c9f55c 100644 (file)
@@ -34,10 +34,10 @@ CLASS(ModalController, Container)
        METHOD(ModalController, initializeDialog, void(entity, entity));
 
        METHOD(ModalController, switchState, void(entity, entity, float, float));
-       ATTRIB(ModalController, origin, vector, '0 0 0')
-       ATTRIB(ModalController, size, vector, '0 0 0')
-       ATTRIB(ModalController, previousButton, entity, NULL)
-       ATTRIB(ModalController, fadedAlpha, float, 0.3)
+       ATTRIB(ModalController, origin, vector, '0 0 0');
+       ATTRIB(ModalController, size, vector, '0 0 0');
+       ATTRIB(ModalController, previousButton, entity);
+       ATTRIB(ModalController, fadedAlpha, float, 0.3);
 ENDCLASS(ModalController)
 
 .float ModalController_state;
index 2d8e3ec49dfc1d8ea60bfdd23440bdaff74c548e..4159648f974207260d502ab8efb4ad90907258f4 100644 (file)
@@ -13,14 +13,14 @@ CLASS(Nexposee, Container)
        METHOD(Nexposee, focusEnter, void(entity));
        METHOD(Nexposee, close, void(entity));
 
-       ATTRIB(Nexposee, animationState, float, -1)
-       ATTRIB(Nexposee, animationFactor, float, 0)
-       ATTRIB(Nexposee, selectedChild, entity, NULL)
-       ATTRIB(Nexposee, mouseFocusedChild, entity, NULL)
+       ATTRIB(Nexposee, animationState, float, -1);
+       ATTRIB(Nexposee, animationFactor, float, 0);
+       ATTRIB(Nexposee, selectedChild, entity);
+       ATTRIB(Nexposee, mouseFocusedChild, entity);
        METHOD(Nexposee, addItem, void(entity, entity, vector, vector, float));
        METHOD(Nexposee, calc, void(entity));
        METHOD(Nexposee, setNexposee, void(entity, entity, vector, float, float));
-       ATTRIB(Nexposee, mousePosition, vector, '0 0 0')
+       ATTRIB(Nexposee, mousePosition, vector, '0 0 0');
        METHOD(Nexposee, pullNexposee, void(entity, entity, vector));
 ENDCLASS(Nexposee)
 
index 53aa7ff2e8af8da330637c597c3ddf4b5db021d7..7bd737787657ff8f74eb642c5a22f600f69e8a2d 100644 (file)
@@ -4,8 +4,8 @@
 void RadioButton_Click(entity me, entity other);
 CLASS(RadioButton, CheckBox)
        METHOD(RadioButton, configureRadioButton, void(entity, string, float, string, float, float));
-       ATTRIB(RadioButton, checked, float, 0)
-       ATTRIB(RadioButton, group, float, 0)
-       ATTRIB(RadioButton, allowDeselect, float, 0)
-       ATTRIB(RadioButton, onClick, void(entity, entity), RadioButton_Click)
+       ATTRIB(RadioButton, checked, float, 0);
+       ATTRIB(RadioButton, group, float, 0);
+       ATTRIB(RadioButton, allowDeselect, float, 0);
+       ATTRIB(RadioButton, onClick, void(entity, entity), RadioButton_Click);
 ENDCLASS(RadioButton)
index f5e8fd496f7f446092d752ecb026ae6da762827e..3b7327788c0d130afb230471b076b8b8262587e9 100644 (file)
@@ -20,31 +20,31 @@ CLASS(Slider, Label)
        METHOD(Slider, setValue, void(entity, float));
        METHOD(Slider, setSliderValue, void(entity, float));
        METHOD(Slider, showNotify, void(entity));
-       ATTRIB(Slider, src, string, string_null)
-       ATTRIB(Slider, focusable, float, 1)
-       ATTRIB(Slider, allowFocusSound, float, 1)
-       ATTRIB(Slider, value, float, 0)
-       ATTRIB(Slider, animated, float, 1)
-       ATTRIB(Slider, sliderValue, float, 0)
-       ATTRIB(Slider, sliderAnim, entity, NULL)
-       ATTRIB(Slider, valueMin, float, 0)
-       ATTRIB(Slider, valueMax, float, 0)
-       ATTRIB(Slider, valueStep, float, 0)
-       ATTRIB(Slider, valueDigits, float, 0)
-       ATTRIB(Slider, valueKeyStep, float, 0)
-       ATTRIB(Slider, valuePageStep, float, 0)
-       ATTRIB(Slider, valueDisplayMultiplier, float, 1.0)
-       ATTRIB(Slider, textSpace, float, 0)
-       ATTRIB(Slider, controlWidth, float, 0)
-       ATTRIB(Slider, pressed, float, 0)
-       ATTRIB(Slider, pressOffset, float, 0)
-       ATTRIB(Slider, previousValue, float, 0)
-       ATTRIB(Slider, tolerance, vector, '0 0 0')
-       ATTRIB(Slider, disabled, float, 0)
-       ATTRIB(Slider, color, vector, '1 1 1')
-       ATTRIB(Slider, color2, vector, '1 1 1')
-       ATTRIB(Slider, colorD, vector, '1 1 1')
-       ATTRIB(Slider, colorC, vector, '1 1 1')
-       ATTRIB(Slider, colorF, vector, '1 1 1')
-       ATTRIB(Slider, disabledAlpha, float, 0.3)
+       ATTRIB(Slider, src, string);
+       ATTRIB(Slider, focusable, float, 1);
+       ATTRIB(Slider, allowFocusSound, float, 1);
+       ATTRIB(Slider, value, float, 0);
+       ATTRIB(Slider, animated, float, 1);
+       ATTRIB(Slider, sliderValue, float, 0);
+       ATTRIB(Slider, sliderAnim, entity);
+       ATTRIB(Slider, valueMin, float, 0);
+       ATTRIB(Slider, valueMax, float, 0);
+       ATTRIB(Slider, valueStep, float, 0);
+       ATTRIB(Slider, valueDigits, float, 0);
+       ATTRIB(Slider, valueKeyStep, float, 0);
+       ATTRIB(Slider, valuePageStep, float, 0);
+       ATTRIB(Slider, valueDisplayMultiplier, float, 1.0);
+       ATTRIB(Slider, textSpace, float, 0);
+       ATTRIB(Slider, controlWidth, float, 0);
+       ATTRIB(Slider, pressed, float, 0);
+       ATTRIB(Slider, pressOffset, float, 0);
+       ATTRIB(Slider, previousValue, float, 0);
+       ATTRIB(Slider, tolerance, vector, '0 0 0');
+       ATTRIB(Slider, disabled, float, 0);
+       ATTRIB(Slider, color, vector, '1 1 1');
+       ATTRIB(Slider, color2, vector, '1 1 1');
+       ATTRIB(Slider, colorD, vector, '1 1 1');
+       ATTRIB(Slider, colorC, vector, '1 1 1');
+       ATTRIB(Slider, colorF, vector, '1 1 1');
+       ATTRIB(Slider, disabledAlpha, float, 0.3);
 ENDCLASS(Slider)
index e9ba81a90387f1d71cce1aabba9d4f584bf4feda..18c9e495979f1ae24a5b2a495bf575c4571006eb 100644 (file)
@@ -2,25 +2,25 @@
 
 #include "dialog.qh"
 CLASS(Tab, Dialog)
-       ATTRIB(Tab, isTabRoot, float, 0)
-       ATTRIB(Tab, closable, float, 0)
-       ATTRIB(Tab, rootDialog, float, 0)
-       ATTRIB(Tab, title, string, string_null)
-       ATTRIB(Tab, titleFontSize, float, 0)  // pixels
+       ATTRIB(Tab, isTabRoot, float, 0);
+       ATTRIB(Tab, closable, float, 0);
+       ATTRIB(Tab, rootDialog, float, 0);
+       ATTRIB(Tab, title, string);
+       ATTRIB(Tab, titleFontSize, float, 0);  // pixels
 
        // still to be customized
-       ATTRIB(Tab, intendedWidth, float, 0)
-       ATTRIB(Tab, rows, float, 3)
-       ATTRIB(Tab, columns, float, 2)
+       ATTRIB(Tab, intendedWidth, float, 0);
+       ATTRIB(Tab, rows, float, 3);
+       ATTRIB(Tab, columns, float, 2);
 
-       ATTRIB(Tab, marginTop, float, 0)     // pixels
-       ATTRIB(Tab, marginBottom, float, 0)  // pixels
-       ATTRIB(Tab, marginLeft, float, 0)    // pixels
-       ATTRIB(Tab, marginRight, float, 0)   // pixels
-       ATTRIB(Tab, columnSpacing, float, 0) // pixels
-       ATTRIB(Tab, rowSpacing, float, 0)    // pixels
-       ATTRIB(Tab, rowHeight, float, 0)     // pixels
-       ATTRIB(Tab, titleHeight, float, 0)   // pixels
+       ATTRIB(Tab, marginTop, float, 0);     // pixels
+       ATTRIB(Tab, marginBottom, float, 0);  // pixels
+       ATTRIB(Tab, marginLeft, float, 0);    // pixels
+       ATTRIB(Tab, marginRight, float, 0);   // pixels
+       ATTRIB(Tab, columnSpacing, float, 0); // pixels
+       ATTRIB(Tab, rowSpacing, float, 0);    // pixels
+       ATTRIB(Tab, rowHeight, float, 0);     // pixels
+       ATTRIB(Tab, titleHeight, float, 0);   // pixels
 
-       ATTRIB(Tab, backgroundImage, string, string_null)
+       ATTRIB(Tab, backgroundImage, string);
 ENDCLASS(Tab)
index 0703942f95b03b5b733741416a55a5c082c0a72e..9a6a586a16c9bd2eed839628d4ccb8f44cf8e109 100644 (file)
@@ -14,7 +14,7 @@ CLASS(TextSlider, Slider)
        METHOD(TextSlider, addValue, void(entity, string, string));
        METHOD(TextSlider, insertValue, void(entity, float, string, string));
        METHOD(TextSlider, configureTextSliderValues, void(entity, string));
-       ATTRIBARRAY(TextSlider, valueStrings, string, 256)
-       ATTRIBARRAY(TextSlider, valueIdentifiers, string, 256)
-       ATTRIB(TextSlider, nValues, int, 0)
+       ATTRIBARRAY(TextSlider, valueStrings, string, 256);
+       ATTRIBARRAY(TextSlider, valueIdentifiers, string, 256);
+       ATTRIB(TextSlider, nValues, int, 0);
 ENDCLASS(TextSlider)
index b0c4ec880c1b2da9c3bb014270f4e6fc5c2b8e80..3039b4a7d4222bda22044f2dc60c8aee5a89c7ad 100644 (file)
@@ -1,3 +1,5 @@
+#include "matrix.qh"
+
 var void MX_Handle(int buf, string ancestor)
 {
     string type = json_get(buf, strcat(ancestor, ".type"));
diff --git a/qcsrc/menu/matrix.qh b/qcsrc/menu/matrix.qh
new file mode 100644 (file)
index 0000000..6f70f09
--- /dev/null
@@ -0,0 +1 @@
+#pragma once
index f32b85298ed7e23a8a70c04f46aa8d1fedad6dde..22934ca908fcf3fcc916f61cae51b2a75630110c 100644 (file)
@@ -237,7 +237,7 @@ void m_keyup(float key, float ascii)
                if (mouseButtonsPressed < 0)
                {
                        mouseButtonsPressed = 0;
-                       LOG_TRACE("Warning: released an already released button\n");
+                       LOG_TRACE("Warning: released an already released button");
                }
        }
        if (key == K_ALT) menuShiftState &= ~S_ALT;
@@ -286,7 +286,7 @@ void m_keydown(float key, float ascii)
                if (mouseButtonsPressed > 10)
                {
                        mouseButtonsPressed = 10;
-                       LOG_TRACE("Warning: pressed an already pressed button\n");
+                       LOG_TRACE("Warning: pressed an already pressed button");
                }
        }
        if (key == K_ALT) menuShiftState |= S_ALT;
index 7cc2d2d3b4d49084f8bbbd2c4fce75cdf100c3d6..4287e24e59f3ddfbc156f04b3a287fcdd894b113 100644 (file)
@@ -19,7 +19,7 @@
 //#define SKINSTRING(name,def) case #name: 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: LOG_TRACE("Invalid key in skin file: ", key, "\n"); } }
+#define SKINEND case "": break; case "//": break; default: LOG_TRACE("Invalid key in skin file: ", key); } }
 #include "skin-customizables.inc"
 #undef SKINEND
 #undef SKINSTRING
index 14b6893a7d16f93a56725c737c49563ce8cd7746..b34014bc3879fb4497642a0304d50966e90f5d9b 100644 (file)
@@ -3,7 +3,7 @@
 #include "button.qh"
 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)
+       ATTRIB(XonoticBigButton, image, string, SKINGFX_BUTTON_BIG);
+       ATTRIB(XonoticBigButton, grayImage, string, SKINGFX_BUTTON_BIG_GRAY);
 ENDCLASS(XonoticBigButton)
 entity makeXonoticBigButton(string theText, vector theColor);
index 4713fa3709765d050bc70576282975c23d8b37c7..b6bb782aee8639335411309dec8a31dacdff8d7d 100644 (file)
@@ -3,8 +3,8 @@
 #include "commandbutton.qh"
 CLASS(XonoticBigCommandButton, XonoticCommandButton)
        METHOD(XonoticBigCommandButton, configureXonoticBigCommandButton, void(entity, string, vector, string, float, string));
-       ATTRIB(XonoticBigCommandButton, image, string, SKINGFX_BUTTON_BIG)
-       ATTRIB(XonoticBigCommandButton, grayImage, string, SKINGFX_BUTTON_BIG_GRAY)
+       ATTRIB(XonoticBigCommandButton, image, string, SKINGFX_BUTTON_BIG);
+       ATTRIB(XonoticBigCommandButton, grayImage, string, SKINGFX_BUTTON_BIG_GRAY);
 ENDCLASS(XonoticBigCommandButton)
 entity makeXonoticBigCommandButton_T(string theText, vector theColor, string theCommand, float closesMenu, string theTooltip);
 entity makeXonoticBigCommandButton(string theText, vector theColor, string theCommand, float closesMenu);
index c7e85fabe0838b8c9659d379c32e40c4258e8283..e4a520d2b67afcee5d76610999e4231e6faeedf9 100644 (file)
@@ -3,17 +3,17 @@
 #include "../item/button.qh"
 CLASS(XonoticButton, Button)
        METHOD(XonoticButton, configureXonoticButton, void(entity, string, vector, string));
-       ATTRIB(XonoticButton, fontSize, float, SKINFONTSIZE_NORMAL)
-       ATTRIB(XonoticButton, image, string, SKINGFX_BUTTON)
-       ATTRIB(XonoticButton, grayImage, string, SKINGFX_BUTTON_GRAY)
-       ATTRIB(XonoticButton, color, vector, SKINCOLOR_BUTTON_N)
-       ATTRIB(XonoticButton, colorC, vector, SKINCOLOR_BUTTON_C)
-       ATTRIB(XonoticButton, colorF, vector, SKINCOLOR_BUTTON_F)
-       ATTRIB(XonoticButton, colorD, vector, SKINCOLOR_BUTTON_D)
-       ATTRIB(XonoticButton, alpha, float, SKINALPHA_TEXT)
-       ATTRIB(XonoticButton, disabledAlpha, float, SKINALPHA_DISABLED)
-       ATTRIB(XonoticButton, marginLeft, float, SKINMARGIN_BUTTON)  // chars
-       ATTRIB(XonoticButton, marginRight, float, SKINMARGIN_BUTTON) // chars
+       ATTRIB(XonoticButton, fontSize, float, SKINFONTSIZE_NORMAL);
+       ATTRIB(XonoticButton, image, string, SKINGFX_BUTTON);
+       ATTRIB(XonoticButton, grayImage, string, SKINGFX_BUTTON_GRAY);
+       ATTRIB(XonoticButton, color, vector, SKINCOLOR_BUTTON_N);
+       ATTRIB(XonoticButton, colorC, vector, SKINCOLOR_BUTTON_C);
+       ATTRIB(XonoticButton, colorF, vector, SKINCOLOR_BUTTON_F);
+       ATTRIB(XonoticButton, colorD, vector, SKINCOLOR_BUTTON_D);
+       ATTRIB(XonoticButton, alpha, float, SKINALPHA_TEXT);
+       ATTRIB(XonoticButton, disabledAlpha, float, SKINALPHA_DISABLED);
+       ATTRIB(XonoticButton, marginLeft, float, SKINMARGIN_BUTTON);  // chars
+       ATTRIB(XonoticButton, marginRight, float, SKINMARGIN_BUTTON); // chars
 ENDCLASS(XonoticButton)
 
 entity makeXonoticButton_T(string theText, vector theColor, string theTooltip);
index 17585a86d4f51233f0d6963b3dee85d4ec1d81db..784926f7df8636cd58d8513a24e5aed8b0dc475c 100644 (file)
@@ -3,7 +3,7 @@
 #include "listbox.qh"
 CLASS(XonoticCampaignList, XonoticListBox)
        METHOD(XonoticCampaignList, configureXonoticCampaignList, void(entity));
-       ATTRIB(XonoticCampaignList, rowsPerItem, float, 10)
+       ATTRIB(XonoticCampaignList, rowsPerItem, float, 10);
        METHOD(XonoticCampaignList, draw, void(entity));
        METHOD(XonoticCampaignList, drawListBoxItem, void(entity, int, vector, bool, bool));
        METHOD(XonoticCampaignList, doubleClickListBoxItem, void(entity, float, vector));
@@ -13,31 +13,31 @@ CLASS(XonoticCampaignList, XonoticListBox)
        METHOD(XonoticCampaignList, campaignGo, void(entity, float));
        METHOD(XonoticCampaignList, destroy, void(entity));
 
-       ATTRIB(XonoticCampaignList, campaignGlob, float, 0)
-       ATTRIB(XonoticCampaignList, realFontSize, vector, '0 0 0')
-       ATTRIB(XonoticCampaignList, columnPreviewOrigin, float, 0)
-       ATTRIB(XonoticCampaignList, columnPreviewSize, float, 0)
-       ATTRIB(XonoticCampaignList, columnNameOrigin, float, 0)
-       ATTRIB(XonoticCampaignList, columnNameSize, float, 0)
-       ATTRIB(XonoticCampaignList, columnCheckMarkOrigin, float, 0)
-       ATTRIB(XonoticCampaignList, columnCheckMarkSize, float, 0)
-       ATTRIB(XonoticCampaignList, checkMarkOrigin, vector, '0 0 0')
-       ATTRIB(XonoticCampaignList, checkMarkSize, vector, '0 0 0')
-       ATTRIB(XonoticCampaignList, realUpperMargin1, float, 0)
-       ATTRIB(XonoticCampaignList, realUpperMargin2, float, 0)
+       ATTRIB(XonoticCampaignList, campaignGlob, float, 0);
+       ATTRIB(XonoticCampaignList, realFontSize, vector, '0 0 0');
+       ATTRIB(XonoticCampaignList, columnPreviewOrigin, float, 0);
+       ATTRIB(XonoticCampaignList, columnPreviewSize, float, 0);
+       ATTRIB(XonoticCampaignList, columnNameOrigin, float, 0);
+       ATTRIB(XonoticCampaignList, columnNameSize, float, 0);
+       ATTRIB(XonoticCampaignList, columnCheckMarkOrigin, float, 0);
+       ATTRIB(XonoticCampaignList, columnCheckMarkSize, float, 0);
+       ATTRIB(XonoticCampaignList, checkMarkOrigin, vector, '0 0 0');
+       ATTRIB(XonoticCampaignList, checkMarkSize, vector, '0 0 0');
+       ATTRIB(XonoticCampaignList, realUpperMargin1, float, 0);
+       ATTRIB(XonoticCampaignList, realUpperMargin2, float, 0);
 
-       ATTRIB(XonoticCampaignList, origin, vector, '0 0 0')
-       ATTRIB(XonoticCampaignList, itemAbsSize, vector, '0 0 0')
-       ATTRIB(XonoticCampaignList, emptyLineHeight, float, 0.5)
+       ATTRIB(XonoticCampaignList, origin, vector, '0 0 0');
+       ATTRIB(XonoticCampaignList, itemAbsSize, vector, '0 0 0');
+       ATTRIB(XonoticCampaignList, emptyLineHeight, float, 0.5);
 
-       ATTRIB(XonoticCampaignList, campaignIndex, float, 0)
-       ATTRIB(XonoticCampaignList, cvarName, string, string_null)
+       ATTRIB(XonoticCampaignList, campaignIndex, float, 0);
+       ATTRIB(XonoticCampaignList, cvarName, string);
        METHOD(XonoticCampaignList, loadCvars, void(entity));
        METHOD(XonoticCampaignList, saveCvars, void(entity));
 
-       ATTRIB(XonoticCampaignList, buttonNext, entity, NULL)
-       ATTRIB(XonoticCampaignList, buttonPrev, entity, NULL)
-       ATTRIB(XonoticCampaignList, labelTitle, entity, NULL)
+       ATTRIB(XonoticCampaignList, buttonNext, entity);
+       ATTRIB(XonoticCampaignList, buttonPrev, entity);
+       ATTRIB(XonoticCampaignList, labelTitle, entity);
 ENDCLASS(XonoticCampaignList)
 entity makeXonoticCampaignList();
 void CampaignList_LoadMap(entity btn, entity me);
index c8d5b313492076922bd4fdf026069aa6d39ba8e1..3993e1dbc0a727c1ba3272a21ce8ae1b53eda8e1 100644 (file)
@@ -6,15 +6,15 @@ CLASS(XonoticCharmap, XonoticPicker)
        METHOD(XonoticCharmap, focusLeave, void(entity));
        METHOD(XonoticCharmap, resizeNotify, void(entity, vector, vector, vector, vector));
        METHOD(XonoticCharmap, keyDown, float(entity, float, float, float));
-       ATTRIB(XonoticCharmap, inputBox, entity, NULL)
-       ATTRIB(XonoticCharmap, realFontSize, vector, '0 0 0')
+       ATTRIB(XonoticCharmap, inputBox, entity);
+       ATTRIB(XonoticCharmap, realFontSize, vector, '0 0 0');
 
-       ATTRIB(XonoticCharmap, rows, float, 10)
-       ATTRIB(XonoticCharmap, columns, float, 14)
+       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));
-       ATTRIB(XonoticCharmap, charOffset, vector, '0 0 0')
+       ATTRIB(XonoticCharmap, charOffset, vector, '0 0 0');
 ENDCLASS(XonoticCharmap)
 entity makeXonoticCharmap(entity controlledInputBox);
index 90a1bf5d4b67e4906223b4c8bf5392e5e82e0dab..e46c9ce4a0bb0f20c342c7f5737cc7ec531ffeb9 100644 (file)
@@ -4,24 +4,24 @@
 CLASS(XonoticCheckBox, CheckBox)
        METHOD(XonoticCheckBox, configureXonoticCheckBox, void(entity, float, float, string, string, string));
        METHOD(XonoticCheckBox, setChecked, void(entity, float));
-       ATTRIB(XonoticCheckBox, fontSize, float, SKINFONTSIZE_NORMAL)
-       ATTRIB(XonoticCheckBox, image, string, SKINGFX_CHECKBOX)
-       ATTRIB(XonoticCheckBox, yesValue, float, 1)
-       ATTRIB(XonoticCheckBox, noValue, float, 0)
+       ATTRIB(XonoticCheckBox, fontSize, float, SKINFONTSIZE_NORMAL);
+       ATTRIB(XonoticCheckBox, image, string, SKINGFX_CHECKBOX);
+       ATTRIB(XonoticCheckBox, yesValue, float, 1);
+       ATTRIB(XonoticCheckBox, noValue, float, 0);
 
-       ATTRIB(XonoticCheckBox, color, vector, SKINCOLOR_CHECKBOX_N)
-       ATTRIB(XonoticCheckBox, colorC, vector, SKINCOLOR_CHECKBOX_C)
-       ATTRIB(XonoticCheckBox, colorF, vector, SKINCOLOR_CHECKBOX_F)
-       ATTRIB(XonoticCheckBox, colorD, vector, SKINCOLOR_CHECKBOX_D)
+       ATTRIB(XonoticCheckBox, color, vector, SKINCOLOR_CHECKBOX_N);
+       ATTRIB(XonoticCheckBox, colorC, vector, SKINCOLOR_CHECKBOX_C);
+       ATTRIB(XonoticCheckBox, colorF, vector, SKINCOLOR_CHECKBOX_F);
+       ATTRIB(XonoticCheckBox, colorD, vector, SKINCOLOR_CHECKBOX_D);
 
-       ATTRIB(XonoticCheckBox, cvarName, string, string_null)
+       ATTRIB(XonoticCheckBox, cvarName, string);
        METHOD(XonoticCheckBox, loadCvars, void(entity));
        METHOD(XonoticCheckBox, saveCvars, void(entity));
-       ATTRIB(XonoticCheckBox, sendCvars, float, 0)
+       ATTRIB(XonoticCheckBox, sendCvars, float, 0);
 
-       ATTRIB(XonoticCheckBox, alpha, float, SKINALPHA_TEXT)
-       ATTRIB(XonoticCheckBox, disabledAlpha, float, SKINALPHA_DISABLED)
-       ATTRIB(XonoticCheckBox, linkedCheckBox, entity, NULL)
+       ATTRIB(XonoticCheckBox, alpha, float, SKINALPHA_TEXT);
+       ATTRIB(XonoticCheckBox, disabledAlpha, float, SKINALPHA_DISABLED);
+       ATTRIB(XonoticCheckBox, linkedCheckBox, entity);
 ENDCLASS(XonoticCheckBox)
 entity makeXonoticCheckBox_T(float, string, string, string);
 entity makeXonoticCheckBox(float, string, string);
index d9c144c6ab763c35616db64d97b54d8e8f8b5f7f..259c2104fea2ac2abd33a232ace783c0f02ea2f4 100644 (file)
@@ -5,20 +5,20 @@ CLASS(XonoticSliderCheckBox, CheckBox)
        METHOD(XonoticSliderCheckBox, configureXonoticSliderCheckBox, void(entity, float, float, entity, string));
        METHOD(XonoticSliderCheckBox, setChecked, void(entity, float));
        METHOD(XonoticSliderCheckBox, draw, void(entity));
-       ATTRIB(XonoticSliderCheckBox, fontSize, float, SKINFONTSIZE_NORMAL)
-       ATTRIB(XonoticSliderCheckBox, image, string, SKINGFX_CHECKBOX)
+       ATTRIB(XonoticSliderCheckBox, fontSize, float, SKINFONTSIZE_NORMAL);
+       ATTRIB(XonoticSliderCheckBox, image, string, SKINGFX_CHECKBOX);
 
-       ATTRIB(XonoticSliderCheckBox, color, vector, SKINCOLOR_CHECKBOX_N)
-       ATTRIB(XonoticSliderCheckBox, colorC, vector, SKINCOLOR_CHECKBOX_C)
-       ATTRIB(XonoticSliderCheckBox, colorF, vector, SKINCOLOR_CHECKBOX_F)
-       ATTRIB(XonoticSliderCheckBox, colorD, vector, SKINCOLOR_CHECKBOX_D)
+       ATTRIB(XonoticSliderCheckBox, color, vector, SKINCOLOR_CHECKBOX_N);
+       ATTRIB(XonoticSliderCheckBox, colorC, vector, SKINCOLOR_CHECKBOX_C);
+       ATTRIB(XonoticSliderCheckBox, colorF, vector, SKINCOLOR_CHECKBOX_F);
+       ATTRIB(XonoticSliderCheckBox, colorD, vector, SKINCOLOR_CHECKBOX_D);
 
-       ATTRIB(XonoticSliderCheckBox, alpha, float, SKINALPHA_TEXT)
-       ATTRIB(XonoticSliderCheckBox, disabledAlpha, float, SKINALPHA_DISABLED)
+       ATTRIB(XonoticSliderCheckBox, alpha, float, SKINALPHA_TEXT);
+       ATTRIB(XonoticSliderCheckBox, disabledAlpha, float, SKINALPHA_DISABLED);
 
-       ATTRIB(XonoticSliderCheckBox, controlledSlider, entity, NULL)
-       ATTRIB(XonoticSliderCheckBox, offValue, float, -1)
-       ATTRIB(XonoticSliderCheckBox, inverted, float, 0)
-       ATTRIB(XonoticSliderCheckBox, savedValue, float, -1)
+       ATTRIB(XonoticSliderCheckBox, controlledSlider, entity);
+       ATTRIB(XonoticSliderCheckBox, offValue, float, -1);
+       ATTRIB(XonoticSliderCheckBox, inverted, float, 0);
+       ATTRIB(XonoticSliderCheckBox, savedValue, float, -1);
 ENDCLASS(XonoticSliderCheckBox)
 entity makeXonoticSliderCheckBox(float, float, entity, string);
index b4dc8e5d20e6aefe2db6657dd1982e4ace9d64fe..e73a7144fc4a0cdd0ff643e600832b5ac2bd775c 100644 (file)
@@ -4,22 +4,22 @@
 CLASS(XonoticCheckBoxString, CheckBox)
        METHOD(XonoticCheckBoxString, configureXonoticCheckBoxString, void(entity, string, string, string, string));
        METHOD(XonoticCheckBoxString, setChecked, void(entity, float));
-       ATTRIB(XonoticCheckBoxString, fontSize, float, SKINFONTSIZE_NORMAL)
-       ATTRIB(XonoticCheckBoxString, image, string, SKINGFX_CHECKBOX)
-       ATTRIB(XonoticCheckBoxString, yesString, string, string_null)
-       ATTRIB(XonoticCheckBoxString, noString, string, string_null)
+       ATTRIB(XonoticCheckBoxString, fontSize, float, SKINFONTSIZE_NORMAL);
+       ATTRIB(XonoticCheckBoxString, image, string, SKINGFX_CHECKBOX);
+       ATTRIB(XonoticCheckBoxString, yesString, string);
+       ATTRIB(XonoticCheckBoxString, noString, string);
 
-       ATTRIB(XonoticCheckBoxString, color, vector, SKINCOLOR_CHECKBOX_N)
-       ATTRIB(XonoticCheckBoxString, colorC, vector, SKINCOLOR_CHECKBOX_C)
-       ATTRIB(XonoticCheckBoxString, colorF, vector, SKINCOLOR_CHECKBOX_F)
-       ATTRIB(XonoticCheckBoxString, colorD, vector, SKINCOLOR_CHECKBOX_D)
+       ATTRIB(XonoticCheckBoxString, color, vector, SKINCOLOR_CHECKBOX_N);
+       ATTRIB(XonoticCheckBoxString, colorC, vector, SKINCOLOR_CHECKBOX_C);
+       ATTRIB(XonoticCheckBoxString, colorF, vector, SKINCOLOR_CHECKBOX_F);
+       ATTRIB(XonoticCheckBoxString, colorD, vector, SKINCOLOR_CHECKBOX_D);
 
-       ATTRIB(XonoticCheckBoxString, cvarName, string, string_null)
+       ATTRIB(XonoticCheckBoxString, cvarName, string);
        METHOD(XonoticCheckBoxString, loadCvars, void(entity));
        METHOD(XonoticCheckBoxString, saveCvars, void(entity));
-       ATTRIB(XonoticCheckBoxString, sendCvars, float, 0)
+       ATTRIB(XonoticCheckBoxString, sendCvars, float, 0);
 
-       ATTRIB(XonoticCheckBoxString, alpha, float, SKINALPHA_TEXT)
-       ATTRIB(XonoticCheckBoxString, disabledAlpha, float, SKINALPHA_DISABLED)
+       ATTRIB(XonoticCheckBoxString, alpha, float, SKINALPHA_TEXT);
+       ATTRIB(XonoticCheckBoxString, disabledAlpha, float, SKINALPHA_DISABLED);
 ENDCLASS(XonoticCheckBoxString)
 entity makeXonoticCheckBoxString(string, string, string, string);
index c253f8f11293329bcf1faeb0573f897061a251c9..9ff9639c588b0d0100ff36617ed45365c02a5885 100644 (file)
@@ -5,14 +5,14 @@ CLASS(XonoticColorButton, RadioButton)
        METHOD(XonoticColorButton, configureXonoticColorButton, void(entity, float, float, float));
        METHOD(XonoticColorButton, setChecked, void(entity, float));
        METHOD(XonoticColorButton, draw, void(entity));
-       ATTRIB(XonoticColorButton, fontSize, float, 0)
-       ATTRIB(XonoticColorButton, image, string, SKINGFX_COLORBUTTON)
+       ATTRIB(XonoticColorButton, fontSize, float, 0);
+       ATTRIB(XonoticColorButton, image, string, SKINGFX_COLORBUTTON);
 
-       ATTRIB(XonoticColorButton, useDownAsChecked, float, 1)
+       ATTRIB(XonoticColorButton, useDownAsChecked, float, 1);
 
-       ATTRIB(XonoticColorButton, cvarPart, float, 0)
-       ATTRIB(XonoticColorButton, cvarName, string, string_null)
-       ATTRIB(XonoticColorButton, cvarValueFloat, float, 0)
+       ATTRIB(XonoticColorButton, cvarPart, float, 0);
+       ATTRIB(XonoticColorButton, cvarName, string);
+       ATTRIB(XonoticColorButton, cvarValueFloat, float, 0);
        METHOD(XonoticColorButton, loadCvars, void(entity));
        METHOD(XonoticColorButton, saveCvars, void(entity));
 ENDCLASS(XonoticColorButton)
index 03567dfa45d929d5f2f60c55fbcb24d444fda602..b1c9d1e80ae566dd5a5dcddc8fb569f46bb3f3b3 100644 (file)
@@ -6,10 +6,10 @@ CLASS(XonoticColorpicker, Image)
        METHOD(XonoticColorpicker, mousePress, float(entity, vector));
        METHOD(XonoticColorpicker, mouseRelease, float(entity, vector));
        METHOD(XonoticColorpicker, mouseDrag, float(entity, vector));
-       ATTRIB(XonoticColorpicker, controlledTextbox, entity, NULL)
-       ATTRIB(XonoticColorpicker, image, string, SKINGFX_COLORPICKER)
-       ATTRIB(XonoticColorpicker, imagemargin, vector, SKINMARGIN_COLORPICKER)
-       ATTRIB(XonoticColorpicker, focusable, float, 1)
+       ATTRIB(XonoticColorpicker, controlledTextbox, entity);
+       ATTRIB(XonoticColorpicker, image, string, SKINGFX_COLORPICKER);
+       ATTRIB(XonoticColorpicker, imagemargin, vector, SKINMARGIN_COLORPICKER);
+       ATTRIB(XonoticColorpicker, focusable, float, 1);
        METHOD(XonoticColorpicker, focusLeave, void(entity));
        METHOD(XonoticColorpicker, keyDown, float(entity, float, float, float));
        METHOD(XonoticColorpicker, draw, void(entity));
index 3caf9d9bf0d5a9d891a828527cefa6bd3aa6c570..e990234b3f0a24779b9e3b40da6850b31299cd82 100644 (file)
@@ -9,15 +9,15 @@ CLASS(XonoticColorpickerString, Image)
        METHOD(XonoticColorpickerString, mouseRelease, float(entity, vector));
        METHOD(XonoticColorpickerString, mouseDrag, float(entity, vector));
 
-       ATTRIB(XonoticColorpickerString, cvarName, string, string_null)
+       ATTRIB(XonoticColorpickerString, cvarName, string);
        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)
-       ATTRIB(XonoticColorpickerString, focusable, float, 1)
+       ATTRIB(XonoticColorpickerString, prevcoords, vector, '0 0 0');
+       ATTRIB(XonoticColorpickerString, image, string, SKINGFX_COLORPICKER);
+       ATTRIB(XonoticColorpickerString, imagemargin, vector, SKINMARGIN_COLORPICKER);
+       ATTRIB(XonoticColorpickerString, focusable, float, 1);
        METHOD(XonoticColorpickerString, draw, void(entity));
-       ATTRIB(XonoticColorpickerString, disabledAlpha, float, 0.3)
+       ATTRIB(XonoticColorpickerString, disabledAlpha, float, 0.3);
 ENDCLASS(XonoticColorpickerString)
 entity makeXonoticColorpickerString(string theCvar, string theDefaultCvar);
index 072890ab1e23b60738f631fed68e61c8a8556169..5de59ee07b9e6d3d6d80920422e807b260255dcd 100644 (file)
@@ -3,8 +3,8 @@
 #include "button.qh"
 CLASS(XonoticCommandButton, XonoticButton)
        METHOD(XonoticCommandButton, configureXonoticCommandButton, void(entity, string, vector, string, float, string));
-       ATTRIB(XonoticCommandButton, onClickCommand, string, string_null)
-       ATTRIB(XonoticCommandButton, flags, float, 0)
+       ATTRIB(XonoticCommandButton, onClickCommand, string);
+       ATTRIB(XonoticCommandButton, flags, float, 0);
 ENDCLASS(XonoticCommandButton)
 
 entity makeXonoticCommandButton_T(string theText, vector theColor, string theCommand, float closesMenu, string theTooltip);
index d376beaa774adecd6e6fd7c91991548fd17d5ddc..8abc12c1998bc675d3c68f4fb2ca4dec751cd90b 100644 (file)
@@ -3,20 +3,20 @@
 #include "listbox.qh"
 CLASS(XonoticCreditsList, XonoticListBox)
        METHOD(XonoticCreditsList, configureXonoticCreditsList, void(entity));
-       ATTRIB(XonoticCreditsList, rowsPerItem, float, 1)
+       ATTRIB(XonoticCreditsList, rowsPerItem, float, 1);
        METHOD(XonoticCreditsList, draw, void(entity));
        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));
-       ATTRIB(XonoticCreditsList, selectionDoesntMatter, bool, true)
+       ATTRIB(XonoticCreditsList, selectionDoesntMatter, bool, true);
 
-       ATTRIB(XonoticCreditsList, realFontSize, vector, '0 0 0')
-       ATTRIB(XonoticCreditsList, realUpperMargin, float, 0)
-       ATTRIB(XonoticCreditsList, bufferIndex, float, 0)
-       ATTRIB(XonoticCreditsList, scrolling, float, 0)
+       ATTRIB(XonoticCreditsList, realFontSize, vector, '0 0 0');
+       ATTRIB(XonoticCreditsList, realUpperMargin, float, 0);
+       ATTRIB(XonoticCreditsList, bufferIndex, float, 0);
+       ATTRIB(XonoticCreditsList, scrolling, float, 0);
 
-       ATTRIB(XonoticCreditsList, alphaBG, float, 0)
+       ATTRIB(XonoticCreditsList, alphaBG, float, 0);
 ENDCLASS(XonoticCreditsList)
 entity makeXonoticCreditsList();
 
index b6f39457d2ff30a6b2de249422015b3d88e22870..78cb5df0c50ce601a9299f52dca8a996638cd260 100644 (file)
@@ -4,8 +4,8 @@
 CLASS(XonoticCrosshairPicker, XonoticPicker)
        METHOD(XonoticCrosshairPicker, configureXonoticCrosshairPicker, void(entity));
 
-       ATTRIB(XonoticCrosshairPicker, rows, float, 3)
-       ATTRIB(XonoticCrosshairPicker, columns, float, 12)
+       ATTRIB(XonoticCrosshairPicker, rows, float, 3);
+       ATTRIB(XonoticCrosshairPicker, columns, float, 12);
 
        METHOD(XonoticCrosshairPicker, cellSelect, void(entity, vector));
        METHOD(XonoticCrosshairPicker, cellIsValid, bool(entity, vector));
index dcc7be5ac6bff16490b6f72b7fe0c7018b1c74b4..7bf363def7f4b42ebf413bcea99b7871a7418a39 100644 (file)
@@ -4,9 +4,9 @@
 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)
+       ATTRIB(XonoticCrosshairPreview, src, string);
+       ATTRIB(XonoticCrosshairPreview, src2, string);
+       ATTRIB(XonoticCrosshairPreview, disabled, float, 0);
+       ATTRIB(XonoticCrosshairPreview, disabledAlpha, float, SKINALPHA_DISABLED);
 ENDCLASS(XonoticCrosshairPreview)
 entity makeXonoticCrosshairPreview();
index 2c99866cf7671d7bf35c9cdf438c7f2dbcdeeea7..1260ae447a42d0162c4b9969e06217886fe7675a 100644 (file)
@@ -3,7 +3,7 @@
 #include "listbox.qh"
 CLASS(XonoticCvarList, XonoticListBox)
        METHOD(XonoticCvarList, configureXonoticCvarList, void(entity));
-       ATTRIB(XonoticCvarList, rowsPerItem, float, 1)
+       ATTRIB(XonoticCvarList, rowsPerItem, float, 1);
        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));
@@ -12,30 +12,30 @@ CLASS(XonoticCvarList, XonoticListBox)
 
        METHOD(XonoticCvarList, destroy, void(entity));
 
-       ATTRIB(XonoticCvarList, realFontSize, vector, '0 0 0')
-       ATTRIB(XonoticCvarList, realUpperMargin, float, 0)
-       ATTRIB(XonoticCvarList, columnNameOrigin, float, 0)
-       ATTRIB(XonoticCvarList, columnNameSize, float, 0)
-       ATTRIB(XonoticCvarList, columnValueOrigin, float, 0)
-       ATTRIB(XonoticCvarList, columnValueSize, float, 0)
+       ATTRIB(XonoticCvarList, realFontSize, vector, '0 0 0');
+       ATTRIB(XonoticCvarList, realUpperMargin, float, 0);
+       ATTRIB(XonoticCvarList, columnNameOrigin, float, 0);
+       ATTRIB(XonoticCvarList, columnNameSize, float, 0);
+       ATTRIB(XonoticCvarList, columnValueOrigin, float, 0);
+       ATTRIB(XonoticCvarList, columnValueSize, float, 0);
 
        METHOD(XonoticCvarList, mouseRelease, float(entity, vector));
        METHOD(XonoticCvarList, setSelected, void(entity, float));
        METHOD(XonoticCvarList, updateCvarType, float(entity));
 
-       ATTRIB(XonoticCvarList, controlledTextbox, entity, NULL)
-       ATTRIB(XonoticCvarList, cvarNameBox, entity, NULL)
-       ATTRIB(XonoticCvarList, cvarDescriptionBox, entity, NULL)
-       ATTRIB(XonoticCvarList, cvarTypeBox, entity, NULL)
-       ATTRIB(XonoticCvarList, cvarValueBox, entity, NULL)
-       ATTRIB(XonoticCvarList, cvarDefaultBox, entity, NULL)
-       ATTRIB(XonoticCvarList, cvarNeedsForcing, float, 0)
+       ATTRIB(XonoticCvarList, controlledTextbox, entity);
+       ATTRIB(XonoticCvarList, cvarNameBox, entity);
+       ATTRIB(XonoticCvarList, cvarDescriptionBox, entity);
+       ATTRIB(XonoticCvarList, cvarTypeBox, entity);
+       ATTRIB(XonoticCvarList, cvarValueBox, entity);
+       ATTRIB(XonoticCvarList, cvarDefaultBox, entity);
+       ATTRIB(XonoticCvarList, cvarNeedsForcing, float, 0);
 
-       ATTRIB(XonoticCvarList, handle, float, -1)
-       ATTRIB(XonoticCvarList, cvarName, string, string_null)
-       ATTRIB(XonoticCvarList, cvarDescription, string, string_null)
-       ATTRIB(XonoticCvarList, cvarType, string, string_null)
-       ATTRIB(XonoticCvarList, cvarDefault, string, string_null)
+       ATTRIB(XonoticCvarList, handle, float, -1);
+       ATTRIB(XonoticCvarList, cvarName, string);
+       ATTRIB(XonoticCvarList, cvarDescription, string);
+       ATTRIB(XonoticCvarList, cvarType, string);
+       ATTRIB(XonoticCvarList, cvarDefault, string);
 ENDCLASS(XonoticCvarList)
 entity makeXonoticCvarList();
 void CvarList_Filter_Change(entity box, entity me);
index 1ca3d5811fd316192c7ca4b86bbf5b10ada6ca5c..87c614ab737b31a34d5a2c447693b69679e6a3a7 100644 (file)
@@ -19,15 +19,15 @@ ENDCLASS(DataSource)
 
 
 CLASS(StringSource, DataSource)
-    ATTRIB(StringSource, StringSource_str, string, string_null)
-    ATTRIB(StringSource, StringSource_sep, string, string_null)
+    ATTRIB(StringSource, StringSource_str, string);
+    ATTRIB(StringSource, StringSource_sep, string);
     CONSTRUCTOR(StringSource, string str, string sep);
     METHOD(StringSource, getEntry, entity(entity this, int i, void(string name, string icon) returns));
     METHOD(StringSource, reload, int(entity this, string filter));
 ENDCLASS(StringSource)
 
 CLASS(CvarStringSource, StringSource)
-    ATTRIB(CvarStringSource, CvarStringSource_cvar, string, string_null)
+    ATTRIB(CvarStringSource, CvarStringSource_cvar, string);
     CONSTRUCTOR(CvarStringSource, string cv, string sep);
     METHOD(CvarStringSource, getEntry, entity(entity this, int i, void(string name, string icon) returns));
     METHOD(CvarStringSource, reload, int(entity this, string filter));
index 547bf6695dff6ea62df429f7432679e3a204fe77..6341db1a3e1da23f081c28044d4b057e43d0243d 100644 (file)
@@ -4,7 +4,7 @@
 #include "listbox.qh"
 CLASS(XonoticDemoList, XonoticListBox)
        METHOD(XonoticDemoList, configureXonoticDemoList, void(entity));
-       ATTRIB(XonoticDemoList, rowsPerItem, float, 1)
+       ATTRIB(XonoticDemoList, rowsPerItem, float, 1);
        METHOD(XonoticDemoList, resizeNotify, void(entity, vector, vector, vector, vector));
        METHOD(XonoticDemoList, drawListBoxItem, void(entity, int, vector, bool, bool));
        METHOD(XonoticDemoList, getDemos, void(entity));
@@ -16,15 +16,15 @@ CLASS(XonoticDemoList, XonoticListBox)
        METHOD(XonoticDemoList, destroy, void(entity));
        METHOD(XonoticDemoList, showNotify, void(entity));
 
-       ATTRIB(XonoticDemoList, listDemo, float, -1)
-       ATTRIB(XonoticDemoList, realFontSize, vector, '0 0 0')
-       ATTRIB(XonoticDemoList, columnNameOrigin, float, 0)
-       ATTRIB(XonoticDemoList, columnNameSize, float, 0)
-       ATTRIB(XonoticDemoList, realUpperMargin, float, 0)
-       ATTRIB(XonoticDemoList, origin, vector, '0 0 0')
-       ATTRIB(XonoticDemoList, itemAbsSize, vector, '0 0 0')
+       ATTRIB(XonoticDemoList, listDemo, float, -1);
+       ATTRIB(XonoticDemoList, realFontSize, vector, '0 0 0');
+       ATTRIB(XonoticDemoList, columnNameOrigin, float, 0);
+       ATTRIB(XonoticDemoList, columnNameSize, float, 0);
+       ATTRIB(XonoticDemoList, realUpperMargin, float, 0);
+       ATTRIB(XonoticDemoList, origin, vector, '0 0 0');
+       ATTRIB(XonoticDemoList, itemAbsSize, vector, '0 0 0');
 
-       ATTRIB(XonoticDemoList, filterString, string, string_null)
+       ATTRIB(XonoticDemoList, filterString, string);
 ENDCLASS(XonoticDemoList)
 
 entity demolist;  // for reference elsewhere
index a3612698ff80e93a8f1b0236b9c952abb93f9da8..847233d6ac908615abcf348d4e49dfe1ba2b7721 100644 (file)
@@ -4,30 +4,30 @@
 CLASS(XonoticDialog, Dialog)
        // still to be customized by user
        /*
-       ATTRIB(XonoticDialog, closable, float, 1)
-       ATTRIB(XonoticDialog, title, string, _("Form1")) // ;)
-       ATTRIB(XonoticDialog, color, vector, '1 0.5 1')
-       ATTRIB(XonoticDialog, intendedWidth, float, 0)
-       ATTRIB(XonoticDialog, rows, float, 3)
-       ATTRIB(XonoticDialog, columns, float, 2)
+       ATTRIB(XonoticDialog, closable, float, 1);
+       ATTRIB(XonoticDialog, title, string, _("Form1")); // ;);
+       ATTRIB(XonoticDialog, color, vector, '1 0.5 1');
+       ATTRIB(XonoticDialog, intendedWidth, float, 0);
+       ATTRIB(XonoticDialog, rows, float, 3);
+       ATTRIB(XonoticDialog, columns, float, 2);
        */
-       ATTRIB(XonoticDialog, marginTop, float, SKINMARGIN_TOP)                          // pixels
-       ATTRIB(XonoticDialog, marginBottom, float, SKINMARGIN_BOTTOM)                    // pixels
-       ATTRIB(XonoticDialog, marginLeft, float, SKINMARGIN_LEFT)                        // pixels
-       ATTRIB(XonoticDialog, marginRight, float, SKINMARGIN_RIGHT)                      // pixels
-       ATTRIB(XonoticDialog, columnSpacing, float, SKINMARGIN_COLUMNS)                  // pixels
-       ATTRIB(XonoticDialog, rowSpacing, float, SKINMARGIN_ROWS)                        // pixels
-       ATTRIB(XonoticDialog, rowHeight, float, SKINFONTSIZE_NORMAL * SKINHEIGHT_NORMAL) // pixels
-       ATTRIB(XonoticDialog, titleHeight, float, SKINFONTSIZE_TITLE * SKINHEIGHT_TITLE) // pixels
-       ATTRIB(XonoticDialog, titleFontSize, float, SKINFONTSIZE_TITLE)                  // pixels
+       ATTRIB(XonoticDialog, marginTop, float, SKINMARGIN_TOP);                          // pixels
+       ATTRIB(XonoticDialog, marginBottom, float, SKINMARGIN_BOTTOM);                    // pixels
+       ATTRIB(XonoticDialog, marginLeft, float, SKINMARGIN_LEFT);                        // pixels
+       ATTRIB(XonoticDialog, marginRight, float, SKINMARGIN_RIGHT);                      // pixels
+       ATTRIB(XonoticDialog, columnSpacing, float, SKINMARGIN_COLUMNS);                  // pixels
+       ATTRIB(XonoticDialog, rowSpacing, float, SKINMARGIN_ROWS);                        // pixels
+       ATTRIB(XonoticDialog, rowHeight, float, SKINFONTSIZE_NORMAL * SKINHEIGHT_NORMAL); // pixels
+       ATTRIB(XonoticDialog, titleHeight, float, SKINFONTSIZE_TITLE * SKINHEIGHT_TITLE); // pixels
+       ATTRIB(XonoticDialog, titleFontSize, float, SKINFONTSIZE_TITLE);                  // pixels
 
-       ATTRIB(XonoticDialog, backgroundImage, string, SKINGFX_DIALOGBORDER)
-       ATTRIB(XonoticDialog, borderLines, float, SKINHEIGHT_DIALOGBORDER)
-       ATTRIB(XonoticDialog, closeButtonImage, string, SKINGFX_CLOSEBUTTON)
-       ATTRIB(XonoticDialog, zoomedOutTitleBarPosition, float, SKINHEIGHT_ZOOMEDTITLE * 0.5 - 0.5)
-       ATTRIB(XonoticDialog, zoomedOutTitleBar, float, SKINHEIGHT_ZOOMEDTITLE != 0)
+       ATTRIB(XonoticDialog, backgroundImage, string, SKINGFX_DIALOGBORDER);
+       ATTRIB(XonoticDialog, borderLines, float, SKINHEIGHT_DIALOGBORDER);
+       ATTRIB(XonoticDialog, closeButtonImage, string, SKINGFX_CLOSEBUTTON);
+       ATTRIB(XonoticDialog, zoomedOutTitleBarPosition, float, SKINHEIGHT_ZOOMEDTITLE * 0.5 - 0.5);
+       ATTRIB(XonoticDialog, zoomedOutTitleBar, float, SKINHEIGHT_ZOOMEDTITLE != 0);
 
-       ATTRIB(XonoticDialog, alpha, float, SKINALPHA_TEXT)
+       ATTRIB(XonoticDialog, alpha, float, SKINALPHA_TEXT);
 
        METHOD(XonoticDialog, configureDialog, void(entity));
 ENDCLASS(XonoticDialog)
index 90d722ed35aa3fe624274e83f4eee5f1fc0a7fca..3be2e2b3f5873b5e3f7160c32150caa4383c6b4d 100644 (file)
@@ -4,11 +4,11 @@
 CLASS(XonoticCreditsDialog, XonoticDialog)
        METHOD(XonoticCreditsDialog, fill, void(entity));
        METHOD(XonoticCreditsDialog, focusEnter, void(entity));
-       ATTRIB(XonoticCreditsDialog, title, string, _("Credits"))
-       ATTRIB(XonoticCreditsDialog, tooltip, string, _("The Xonotic credits"))
-       ATTRIB(XonoticCreditsDialog, color, vector, SKINCOLOR_DIALOG_CREDITS)
-       ATTRIB(XonoticCreditsDialog, intendedWidth, float, SKINWIDTH_CREDITS)
-       ATTRIB(XonoticCreditsDialog, rows, float, SKINROWS_CREDITS)
-       ATTRIB(XonoticCreditsDialog, columns, float, 2)
-       ATTRIB(XonoticCreditsDialog, creditsList, entity, NULL)
+       ATTRIB(XonoticCreditsDialog, title, string, _("Credits"));
+       ATTRIB(XonoticCreditsDialog, tooltip, string, _("The Xonotic credits"));
+       ATTRIB(XonoticCreditsDialog, color, vector, SKINCOLOR_DIALOG_CREDITS);
+       ATTRIB(XonoticCreditsDialog, intendedWidth, float, SKINWIDTH_CREDITS);
+       ATTRIB(XonoticCreditsDialog, rows, float, SKINROWS_CREDITS);
+       ATTRIB(XonoticCreditsDialog, columns, float, 2);
+       ATTRIB(XonoticCreditsDialog, creditsList, entity);
 ENDCLASS(XonoticCreditsDialog)
index ff7099b6b98b398a90da70dc3cba3273eaea275e..51a56bb6aa66a7e3d9b1411d5351015a1904c11f 100644 (file)
@@ -3,14 +3,14 @@
 #include "rootdialog.qh"
 CLASS(XonoticFirstRunDialog, XonoticRootDialog)
        METHOD(XonoticFirstRunDialog, fill, void(entity));
-       ATTRIB(XonoticFirstRunDialog, title, string, _("Welcome"))
-       ATTRIB(XonoticFirstRunDialog, color, vector, SKINCOLOR_DIALOG_FIRSTRUN)
-       ATTRIB(XonoticFirstRunDialog, intendedWidth, float, 0.7)
-       ATTRIB(XonoticFirstRunDialog, rows, float, 16)
-       ATTRIB(XonoticFirstRunDialog, columns, float, 6)
-       ATTRIB(XonoticFirstRunDialog, name, string, "FirstRun")
-       ATTRIB(XonoticFirstRunDialog, playerNameLabel, entity, NULL)
-       ATTRIB(XonoticFirstRunDialog, playerNameLabelAlpha, float, 0)
+       ATTRIB(XonoticFirstRunDialog, title, string, _("Welcome"));
+       ATTRIB(XonoticFirstRunDialog, color, vector, SKINCOLOR_DIALOG_FIRSTRUN);
+       ATTRIB(XonoticFirstRunDialog, intendedWidth, float, 0.7);
+       ATTRIB(XonoticFirstRunDialog, rows, float, 16);
+       ATTRIB(XonoticFirstRunDialog, columns, float, 6);
+       ATTRIB(XonoticFirstRunDialog, name, string, "FirstRun");
+       ATTRIB(XonoticFirstRunDialog, playerNameLabel, entity);
+       ATTRIB(XonoticFirstRunDialog, playerNameLabelAlpha, float, 0);
 
-       ATTRIB(XonoticFirstRunDialog, closable, float, 0)
+       ATTRIB(XonoticFirstRunDialog, closable, float, 0);
 ENDCLASS(XonoticFirstRunDialog)
index 237bcbbd152c923f700ce01952b95a68ece3e97c..9113a02794b1b08f810b009dd491c06fd8be7ab6 100644 (file)
@@ -3,11 +3,11 @@
 #include "rootdialog.qh"
 CLASS(XonoticHUDAmmoDialog, XonoticRootDialog)
        METHOD(XonoticHUDAmmoDialog, fill, void(entity));
-       ATTRIB(XonoticHUDAmmoDialog, title, string, _("Ammo Panel"))
-       ATTRIB(XonoticHUDAmmoDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT)
-       ATTRIB(XonoticHUDAmmoDialog, intendedWidth, float, 0.4)
-       ATTRIB(XonoticHUDAmmoDialog, rows, float, 15)
-       ATTRIB(XonoticHUDAmmoDialog, columns, float, 4)
-       ATTRIB(XonoticHUDAmmoDialog, name, string, "HUDammo")
-       ATTRIB(XonoticHUDAmmoDialog, requiresConnection, float, true)
+       ATTRIB(XonoticHUDAmmoDialog, title, string, _("Ammo Panel"));
+       ATTRIB(XonoticHUDAmmoDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT);
+       ATTRIB(XonoticHUDAmmoDialog, intendedWidth, float, 0.4);
+       ATTRIB(XonoticHUDAmmoDialog, rows, float, 15);
+       ATTRIB(XonoticHUDAmmoDialog, columns, float, 4);
+       ATTRIB(XonoticHUDAmmoDialog, name, string, "HUDammo");
+       ATTRIB(XonoticHUDAmmoDialog, requiresConnection, float, true);
 ENDCLASS(XonoticHUDAmmoDialog)
index 370dbe4eb84d098ad4a21dab582f4c5164d3b74e..9fc6846eb9a0d5d044a27ed4c99937190ab3137c 100644 (file)
@@ -3,11 +3,11 @@
 #include "rootdialog.qh"
 CLASS(XonoticHUDCenterprintDialog, XonoticRootDialog)
        METHOD(XonoticHUDCenterprintDialog, fill, void(entity));
-       ATTRIB(XonoticHUDCenterprintDialog, title, string, _("Centerprint Panel"))
-       ATTRIB(XonoticHUDCenterprintDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT)
-       ATTRIB(XonoticHUDCenterprintDialog, intendedWidth, float, 0.4)
-       ATTRIB(XonoticHUDCenterprintDialog, rows, float, 15)
-       ATTRIB(XonoticHUDCenterprintDialog, columns, float, 4)
-       ATTRIB(XonoticHUDCenterprintDialog, name, string, "HUDcenterprint")
-       ATTRIB(XonoticHUDCenterprintDialog, requiresConnection, float, true)
+       ATTRIB(XonoticHUDCenterprintDialog, title, string, _("Centerprint Panel"));
+       ATTRIB(XonoticHUDCenterprintDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT);
+       ATTRIB(XonoticHUDCenterprintDialog, intendedWidth, float, 0.4);
+       ATTRIB(XonoticHUDCenterprintDialog, rows, float, 15);
+       ATTRIB(XonoticHUDCenterprintDialog, columns, float, 4);
+       ATTRIB(XonoticHUDCenterprintDialog, name, string, "HUDcenterprint");
+       ATTRIB(XonoticHUDCenterprintDialog, requiresConnection, float, true);
 ENDCLASS(XonoticHUDCenterprintDialog)
index b30ea9fb2cc435bc616e8bfe49e06632b1bc11a6..570c2d616cde334e7402acc4d061ccad7c299d5d 100644 (file)
@@ -3,11 +3,11 @@
 #include "rootdialog.qh"
 CLASS(XonoticHUDChatDialog, XonoticRootDialog)
        METHOD(XonoticHUDChatDialog, fill, void(entity));
-       ATTRIB(XonoticHUDChatDialog, title, string, _("Chat Panel"))
-       ATTRIB(XonoticHUDChatDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT)
-       ATTRIB(XonoticHUDChatDialog, intendedWidth, float, 0.4)
-       ATTRIB(XonoticHUDChatDialog, rows, float, 15)
-       ATTRIB(XonoticHUDChatDialog, columns, float, 4)
-       ATTRIB(XonoticHUDChatDialog, name, string, "HUDchat")
-       ATTRIB(XonoticHUDChatDialog, requiresConnection, float, true)
+       ATTRIB(XonoticHUDChatDialog, title, string, _("Chat Panel"));
+       ATTRIB(XonoticHUDChatDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT);
+       ATTRIB(XonoticHUDChatDialog, intendedWidth, float, 0.4);
+       ATTRIB(XonoticHUDChatDialog, rows, float, 15);
+       ATTRIB(XonoticHUDChatDialog, columns, float, 4);
+       ATTRIB(XonoticHUDChatDialog, name, string, "HUDchat");
+       ATTRIB(XonoticHUDChatDialog, requiresConnection, float, true);
 ENDCLASS(XonoticHUDChatDialog)
index a28897d8c526f6e581ec7b7d0a80a8d8c7b757ef..b741465024d78a9917639aedabd61c209ae026ca 100644 (file)
@@ -3,11 +3,11 @@
 #include "rootdialog.qh"
 CLASS(XonoticHUDEngineInfoDialog, XonoticRootDialog)
        METHOD(XonoticHUDEngineInfoDialog, fill, void(entity));
-       ATTRIB(XonoticHUDEngineInfoDialog, title, string, _("Engine Info Panel"))
-       ATTRIB(XonoticHUDEngineInfoDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT)
-       ATTRIB(XonoticHUDEngineInfoDialog, intendedWidth, float, 0.4)
-       ATTRIB(XonoticHUDEngineInfoDialog, rows, float, 15)
-       ATTRIB(XonoticHUDEngineInfoDialog, columns, float, 4)
-       ATTRIB(XonoticHUDEngineInfoDialog, name, string, "HUDengineinfo")
-       ATTRIB(XonoticHUDEngineInfoDialog, requiresConnection, float, true)
+       ATTRIB(XonoticHUDEngineInfoDialog, title, string, _("Engine Info Panel"));
+       ATTRIB(XonoticHUDEngineInfoDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT);
+       ATTRIB(XonoticHUDEngineInfoDialog, intendedWidth, float, 0.4);
+       ATTRIB(XonoticHUDEngineInfoDialog, rows, float, 15);
+       ATTRIB(XonoticHUDEngineInfoDialog, columns, float, 4);
+       ATTRIB(XonoticHUDEngineInfoDialog, name, string, "HUDengineinfo");
+       ATTRIB(XonoticHUDEngineInfoDialog, requiresConnection, float, true);
 ENDCLASS(XonoticHUDEngineInfoDialog)
index 495047c5fca1788ff6cb4e21b338fd0c8b0e9878..b37f41b76ef5f1ecf91a8d2056d2fe8cab68a98e 100644 (file)
@@ -3,11 +3,11 @@
 #include "rootdialog.qh"
 CLASS(XonoticHUDHealthArmorDialog, XonoticRootDialog)
        METHOD(XonoticHUDHealthArmorDialog, fill, void(entity));
-       ATTRIB(XonoticHUDHealthArmorDialog, title, string, _("Health/Armor Panel"))
-       ATTRIB(XonoticHUDHealthArmorDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT)
-       ATTRIB(XonoticHUDHealthArmorDialog, intendedWidth, float, 0.4)
-       ATTRIB(XonoticHUDHealthArmorDialog, rows, float, 16)
-       ATTRIB(XonoticHUDHealthArmorDialog, columns, float, 4)
-       ATTRIB(XonoticHUDHealthArmorDialog, name, string, "HUDhealtharmor")
-       ATTRIB(XonoticHUDHealthArmorDialog, requiresConnection, float, true)
+       ATTRIB(XonoticHUDHealthArmorDialog, title, string, _("Health/Armor Panel"));
+       ATTRIB(XonoticHUDHealthArmorDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT);
+       ATTRIB(XonoticHUDHealthArmorDialog, intendedWidth, float, 0.4);
+       ATTRIB(XonoticHUDHealthArmorDialog, rows, float, 16);
+       ATTRIB(XonoticHUDHealthArmorDialog, columns, float, 4);
+       ATTRIB(XonoticHUDHealthArmorDialog, name, string, "HUDhealtharmor");
+       ATTRIB(XonoticHUDHealthArmorDialog, requiresConnection, float, true);
 ENDCLASS(XonoticHUDHealthArmorDialog)
index 093bc00dfdf522c4ce0f2d0f266e352f51cd08ab..5d9032ffb0fdf3e307190fd5a77353b425b5a099 100644 (file)
@@ -3,11 +3,11 @@
 #include "rootdialog.qh"
 CLASS(XonoticHUDInfoMessagesDialog, XonoticRootDialog)
        METHOD(XonoticHUDInfoMessagesDialog, fill, void(entity));
-       ATTRIB(XonoticHUDInfoMessagesDialog, title, string, _("Info Messages Panel"))
-       ATTRIB(XonoticHUDInfoMessagesDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT)
-       ATTRIB(XonoticHUDInfoMessagesDialog, intendedWidth, float, 0.4)
-       ATTRIB(XonoticHUDInfoMessagesDialog, rows, float, 15)
-       ATTRIB(XonoticHUDInfoMessagesDialog, columns, float, 4)
-       ATTRIB(XonoticHUDInfoMessagesDialog, name, string, "HUDinfomessages")
-       ATTRIB(XonoticHUDInfoMessagesDialog, requiresConnection, float, true)
+       ATTRIB(XonoticHUDInfoMessagesDialog, title, string, _("Info Messages Panel"));
+       ATTRIB(XonoticHUDInfoMessagesDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT);
+       ATTRIB(XonoticHUDInfoMessagesDialog, intendedWidth, float, 0.4);
+       ATTRIB(XonoticHUDInfoMessagesDialog, rows, float, 15);
+       ATTRIB(XonoticHUDInfoMessagesDialog, columns, float, 4);
+       ATTRIB(XonoticHUDInfoMessagesDialog, name, string, "HUDinfomessages");
+       ATTRIB(XonoticHUDInfoMessagesDialog, requiresConnection, float, true);
 ENDCLASS(XonoticHUDInfoMessagesDialog)
index 71b53e6909aa43c5a504207adc57ecc274e4e608..507dedb7c95cc068adc2d478cf4a83795c72e620 100644 (file)
@@ -3,10 +3,10 @@
 #include "rootdialog.qh"
 CLASS(XonoticHUDItemsTimeDialog, XonoticRootDialog)
        METHOD(XonoticHUDItemsTimeDialog, fill, void(entity));
-       ATTRIB(XonoticHUDItemsTimeDialog, title, string, _("Items Time Panel"))
-       ATTRIB(XonoticHUDItemsTimeDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT)
-       ATTRIB(XonoticHUDItemsTimeDialog, intendedWidth, float, 0.4)
-       ATTRIB(XonoticHUDItemsTimeDialog, rows, float, 15)
-       ATTRIB(XonoticHUDItemsTimeDialog, columns, float, 4)
-       ATTRIB(XonoticHUDItemsTimeDialog, name, string, "HUDitemstime")
+       ATTRIB(XonoticHUDItemsTimeDialog, title, string, _("Items Time Panel"));
+       ATTRIB(XonoticHUDItemsTimeDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT);
+       ATTRIB(XonoticHUDItemsTimeDialog, intendedWidth, float, 0.4);
+       ATTRIB(XonoticHUDItemsTimeDialog, rows, float, 15);
+       ATTRIB(XonoticHUDItemsTimeDialog, columns, float, 4);
+       ATTRIB(XonoticHUDItemsTimeDialog, name, string, "HUDitemstime");
 ENDCLASS(XonoticHUDItemsTimeDialog)
index feb36e206cb3765d15c8479b8e0fe1fad5f8c8c8..3a3b72f6c9989df94d4695b135ed30f96f6186e5 100644 (file)
@@ -3,11 +3,11 @@
 #include "rootdialog.qh"
 CLASS(XonoticHUDModIconsDialog, XonoticRootDialog)
        METHOD(XonoticHUDModIconsDialog, fill, void(entity));
-       ATTRIB(XonoticHUDModIconsDialog, title, string, _("Mod Icons Panel"))
-       ATTRIB(XonoticHUDModIconsDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT)
-       ATTRIB(XonoticHUDModIconsDialog, intendedWidth, float, 0.4)
-       ATTRIB(XonoticHUDModIconsDialog, rows, float, 15)
-       ATTRIB(XonoticHUDModIconsDialog, columns, float, 4)
-       ATTRIB(XonoticHUDModIconsDialog, name, string, "HUDmodicons")
-       ATTRIB(XonoticHUDModIconsDialog, requiresConnection, float, true)
+       ATTRIB(XonoticHUDModIconsDialog, title, string, _("Mod Icons Panel"));
+       ATTRIB(XonoticHUDModIconsDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT);
+       ATTRIB(XonoticHUDModIconsDialog, intendedWidth, float, 0.4);
+       ATTRIB(XonoticHUDModIconsDialog, rows, float, 15);
+       ATTRIB(XonoticHUDModIconsDialog, columns, float, 4);
+       ATTRIB(XonoticHUDModIconsDialog, name, string, "HUDmodicons");
+       ATTRIB(XonoticHUDModIconsDialog, requiresConnection, float, true);
 ENDCLASS(XonoticHUDModIconsDialog)
index ad150076d04f936f0fda499222480d07c3c949d5..f816e4ffe042fd9d6f6f6ba84c46cecbdddc97b6 100644 (file)
@@ -3,11 +3,11 @@
 #include "rootdialog.qh"
 CLASS(XonoticHUDNotificationDialog, XonoticRootDialog)
        METHOD(XonoticHUDNotificationDialog, fill, void(entity));
-       ATTRIB(XonoticHUDNotificationDialog, title, string, _("Notification Panel"))
-       ATTRIB(XonoticHUDNotificationDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT)
-       ATTRIB(XonoticHUDNotificationDialog, intendedWidth, float, 0.4)
-       ATTRIB(XonoticHUDNotificationDialog, rows, float, 15)
-       ATTRIB(XonoticHUDNotificationDialog, columns, float, 4)
-       ATTRIB(XonoticHUDNotificationDialog, name, string, "HUDnotify")
-       ATTRIB(XonoticHUDNotificationDialog, requiresConnection, float, true)
+       ATTRIB(XonoticHUDNotificationDialog, title, string, _("Notification Panel"));
+       ATTRIB(XonoticHUDNotificationDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT);
+       ATTRIB(XonoticHUDNotificationDialog, intendedWidth, float, 0.4);
+       ATTRIB(XonoticHUDNotificationDialog, rows, float, 15);
+       ATTRIB(XonoticHUDNotificationDialog, columns, float, 4);
+       ATTRIB(XonoticHUDNotificationDialog, name, string, "HUDnotify");
+       ATTRIB(XonoticHUDNotificationDialog, requiresConnection, float, true);
 ENDCLASS(XonoticHUDNotificationDialog)
index 1d9c29289c285325cdf78c685dcd69d403995e82..f6f19135d1f7a257d001d4af567bd01d50d03adc 100644 (file)
@@ -3,12 +3,12 @@
 #include "rootdialog.qh"
 CLASS(XonoticHUDPhysicsDialog, XonoticRootDialog)
        METHOD(XonoticHUDPhysicsDialog, fill, void(entity));
-       ATTRIB(XonoticHUDPhysicsDialog, title, string, _("Physics Panel"))
-       ATTRIB(XonoticHUDPhysicsDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT)
-       ATTRIB(XonoticHUDPhysicsDialog, intendedWidth, float, 0.4)
-       ATTRIB(XonoticHUDPhysicsDialog, rows, float, 15)
-       ATTRIB(XonoticHUDPhysicsDialog, columns, float, 4)
-       ATTRIB(XonoticHUDPhysicsDialog, name, string, "HUDphysics")
-       ATTRIB(XonoticHUDPhysicsDialog, sliderTopspeedTime, entity, NULL)
-       ATTRIB(XonoticHUDPhysicsDialog, requiresConnection, float, true)
+       ATTRIB(XonoticHUDPhysicsDialog, title, string, _("Physics Panel"));
+       ATTRIB(XonoticHUDPhysicsDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT);
+       ATTRIB(XonoticHUDPhysicsDialog, intendedWidth, float, 0.4);
+       ATTRIB(XonoticHUDPhysicsDialog, rows, float, 15);
+       ATTRIB(XonoticHUDPhysicsDialog, columns, float, 4);
+       ATTRIB(XonoticHUDPhysicsDialog, name, string, "HUDphysics");
+       ATTRIB(XonoticHUDPhysicsDialog, sliderTopspeedTime, entity);
+       ATTRIB(XonoticHUDPhysicsDialog, requiresConnection, float, true);
 ENDCLASS(XonoticHUDPhysicsDialog)
index ebb09b0ba5cf7118fb0d7bdc52f7c2470421adfb..7f67fa6007b6f2423dfd54158ead5a20f038f36d 100644 (file)
@@ -3,11 +3,11 @@
 #include "rootdialog.qh"
 CLASS(XonoticHUDPowerupsDialog, XonoticRootDialog)
        METHOD(XonoticHUDPowerupsDialog, fill, void(entity));
-       ATTRIB(XonoticHUDPowerupsDialog, title, string, _("Powerups Panel"))
-       ATTRIB(XonoticHUDPowerupsDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT)
-       ATTRIB(XonoticHUDPowerupsDialog, intendedWidth, float, 0.4)
-       ATTRIB(XonoticHUDPowerupsDialog, rows, float, 14)
-       ATTRIB(XonoticHUDPowerupsDialog, columns, float, 4)
-       ATTRIB(XonoticHUDPowerupsDialog, name, string, "HUDpowerups")
-       ATTRIB(XonoticHUDPowerupsDialog, requiresConnection, float, true)
+       ATTRIB(XonoticHUDPowerupsDialog, title, string, _("Powerups Panel"));
+       ATTRIB(XonoticHUDPowerupsDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT);
+       ATTRIB(XonoticHUDPowerupsDialog, intendedWidth, float, 0.4);
+       ATTRIB(XonoticHUDPowerupsDialog, rows, float, 14);
+       ATTRIB(XonoticHUDPowerupsDialog, columns, float, 4);
+       ATTRIB(XonoticHUDPowerupsDialog, name, string, "HUDpowerups");
+       ATTRIB(XonoticHUDPowerupsDialog, requiresConnection, float, true);
 ENDCLASS(XonoticHUDPowerupsDialog)
index c4b7a90969b10498b62cc0b99137c814e86fef02..cc82959e6443af3c3ffc594da63504f66cf399dd 100644 (file)
@@ -3,11 +3,11 @@
 #include "rootdialog.qh"
 CLASS(XonoticHUDPressedKeysDialog, XonoticRootDialog)
        METHOD(XonoticHUDPressedKeysDialog, fill, void(entity));
-       ATTRIB(XonoticHUDPressedKeysDialog, title, string, _("Pressed Keys Panel"))
-       ATTRIB(XonoticHUDPressedKeysDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT)
-       ATTRIB(XonoticHUDPressedKeysDialog, intendedWidth, float, 0.4)
-       ATTRIB(XonoticHUDPressedKeysDialog, rows, float, 15)
-       ATTRIB(XonoticHUDPressedKeysDialog, columns, float, 4)
-       ATTRIB(XonoticHUDPressedKeysDialog, name, string, "HUDpressedkeys")
-       ATTRIB(XonoticHUDPressedKeysDialog, requiresConnection, float, true)
+       ATTRIB(XonoticHUDPressedKeysDialog, title, string, _("Pressed Keys Panel"));
+       ATTRIB(XonoticHUDPressedKeysDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT);
+       ATTRIB(XonoticHUDPressedKeysDialog, intendedWidth, float, 0.4);
+       ATTRIB(XonoticHUDPressedKeysDialog, rows, float, 15);
+       ATTRIB(XonoticHUDPressedKeysDialog, columns, float, 4);
+       ATTRIB(XonoticHUDPressedKeysDialog, name, string, "HUDpressedkeys");
+       ATTRIB(XonoticHUDPressedKeysDialog, requiresConnection, float, true);
 ENDCLASS(XonoticHUDPressedKeysDialog)
index 396f62b2638579ece5c2e21cccf89c3b0f9b775a..16f93c13d584579397f754ca3a78ec9dcdba7de4 100644 (file)
@@ -3,10 +3,10 @@
 #include "rootdialog.qh"
 CLASS(XonoticHUDQuickMenuDialog, XonoticRootDialog)
        METHOD(XonoticHUDQuickMenuDialog, fill, void(entity));
-       ATTRIB(XonoticHUDQuickMenuDialog, title, string, _("Quick Menu Panel"))
-       ATTRIB(XonoticHUDQuickMenuDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT)
-       ATTRIB(XonoticHUDQuickMenuDialog, intendedWidth, float, 0.4)
-       ATTRIB(XonoticHUDQuickMenuDialog, rows, float, 15)
-       ATTRIB(XonoticHUDQuickMenuDialog, columns, float, 4)
-       ATTRIB(XonoticHUDQuickMenuDialog, name, string, "HUDquickmenu")
+       ATTRIB(XonoticHUDQuickMenuDialog, title, string, _("Quick Menu Panel"));
+       ATTRIB(XonoticHUDQuickMenuDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT);
+       ATTRIB(XonoticHUDQuickMenuDialog, intendedWidth, float, 0.4);
+       ATTRIB(XonoticHUDQuickMenuDialog, rows, float, 15);
+       ATTRIB(XonoticHUDQuickMenuDialog, columns, float, 4);
+       ATTRIB(XonoticHUDQuickMenuDialog, name, string, "HUDquickmenu");
 ENDCLASS(XonoticHUDQuickMenuDialog)
index 81dca5126162f20b85c66deef4828c4dc6ca8d2a..7c814e3823e3586d7a2c9d14edb9a2a688f67cd0 100644 (file)
@@ -3,11 +3,11 @@
 #include "rootdialog.qh"
 CLASS(XonoticHUDRaceTimerDialog, XonoticRootDialog)
        METHOD(XonoticHUDRaceTimerDialog, fill, void(entity));
-       ATTRIB(XonoticHUDRaceTimerDialog, title, string, _("Race Timer Panel"))
-       ATTRIB(XonoticHUDRaceTimerDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT)
-       ATTRIB(XonoticHUDRaceTimerDialog, intendedWidth, float, 0.4)
-       ATTRIB(XonoticHUDRaceTimerDialog, rows, float, 15)
-       ATTRIB(XonoticHUDRaceTimerDialog, columns, float, 4)
-       ATTRIB(XonoticHUDRaceTimerDialog, name, string, "HUDracetimer")
-       ATTRIB(XonoticHUDRaceTimerDialog, requiresConnection, float, true)
+       ATTRIB(XonoticHUDRaceTimerDialog, title, string, _("Race Timer Panel"));
+       ATTRIB(XonoticHUDRaceTimerDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT);
+       ATTRIB(XonoticHUDRaceTimerDialog, intendedWidth, float, 0.4);
+       ATTRIB(XonoticHUDRaceTimerDialog, rows, float, 15);
+       ATTRIB(XonoticHUDRaceTimerDialog, columns, float, 4);
+       ATTRIB(XonoticHUDRaceTimerDialog, name, string, "HUDracetimer");
+       ATTRIB(XonoticHUDRaceTimerDialog, requiresConnection, float, true);
 ENDCLASS(XonoticHUDRaceTimerDialog)
index 6744e22741e4837fdb5c8d04272297ab775cfab9..04617b677f4c04a7444cf5de08444c1c67532f25 100644 (file)
@@ -3,11 +3,11 @@
 #include "rootdialog.qh"
 CLASS(XonoticHUDRadarDialog, XonoticRootDialog)
        METHOD(XonoticHUDRadarDialog, fill, void(entity));
-       ATTRIB(XonoticHUDRadarDialog, title, string, _("Radar Panel"))
-       ATTRIB(XonoticHUDRadarDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT)
-       ATTRIB(XonoticHUDRadarDialog, intendedWidth, float, 0.4)
-       ATTRIB(XonoticHUDRadarDialog, rows, float, 15)
-       ATTRIB(XonoticHUDRadarDialog, columns, float, 4)
-       ATTRIB(XonoticHUDRadarDialog, name, string, "HUDradar")
-       ATTRIB(XonoticHUDRadarDialog, requiresConnection, float, true)
+       ATTRIB(XonoticHUDRadarDialog, title, string, _("Radar Panel"));
+       ATTRIB(XonoticHUDRadarDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT);
+       ATTRIB(XonoticHUDRadarDialog, intendedWidth, float, 0.4);
+       ATTRIB(XonoticHUDRadarDialog, rows, float, 15);
+       ATTRIB(XonoticHUDRadarDialog, columns, float, 4);
+       ATTRIB(XonoticHUDRadarDialog, name, string, "HUDradar");
+       ATTRIB(XonoticHUDRadarDialog, requiresConnection, float, true);
 ENDCLASS(XonoticHUDRadarDialog)
index 68015eaa648d7abcc48894fb91965bb80e6c4eed..d97787404e921121ce3453be7f8a42bfd1a940fb 100644 (file)
@@ -3,11 +3,11 @@
 #include "rootdialog.qh"
 CLASS(XonoticHUDScoreDialog, XonoticRootDialog)
        METHOD(XonoticHUDScoreDialog, fill, void(entity));
-       ATTRIB(XonoticHUDScoreDialog, title, string, _("Score Panel"))
-       ATTRIB(XonoticHUDScoreDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT)
-       ATTRIB(XonoticHUDScoreDialog, intendedWidth, float, 0.4)
-       ATTRIB(XonoticHUDScoreDialog, rows, float, 15)
-       ATTRIB(XonoticHUDScoreDialog, columns, float, 4)
-       ATTRIB(XonoticHUDScoreDialog, name, string, "HUDscore")
-       ATTRIB(XonoticHUDScoreDialog, requiresConnection, float, true)
+       ATTRIB(XonoticHUDScoreDialog, title, string, _("Score Panel"));
+       ATTRIB(XonoticHUDScoreDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT);
+       ATTRIB(XonoticHUDScoreDialog, intendedWidth, float, 0.4);
+       ATTRIB(XonoticHUDScoreDialog, rows, float, 15);
+       ATTRIB(XonoticHUDScoreDialog, columns, float, 4);
+       ATTRIB(XonoticHUDScoreDialog, name, string, "HUDscore");
+       ATTRIB(XonoticHUDScoreDialog, requiresConnection, float, true);
 ENDCLASS(XonoticHUDScoreDialog)
index 7f750971312ba5069c2b44da2e33b7ed781414eb..61955495edd4c7ac985ee989c39fe2d23b27cf3c 100644 (file)
@@ -3,11 +3,11 @@
 #include "rootdialog.qh"
 CLASS(XonoticHUDTimerDialog, XonoticRootDialog)
        METHOD(XonoticHUDTimerDialog, fill, void(entity));
-       ATTRIB(XonoticHUDTimerDialog, title, string, _("Timer Panel"))
-       ATTRIB(XonoticHUDTimerDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT)
-       ATTRIB(XonoticHUDTimerDialog, intendedWidth, float, 0.4)
-       ATTRIB(XonoticHUDTimerDialog, rows, float, 15)
-       ATTRIB(XonoticHUDTimerDialog, columns, float, 4)
-       ATTRIB(XonoticHUDTimerDialog, name, string, "HUDtimer")
-       ATTRIB(XonoticHUDTimerDialog, requiresConnection, float, true)
+       ATTRIB(XonoticHUDTimerDialog, title, string, _("Timer Panel"));
+       ATTRIB(XonoticHUDTimerDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT);
+       ATTRIB(XonoticHUDTimerDialog, intendedWidth, float, 0.4);
+       ATTRIB(XonoticHUDTimerDialog, rows, float, 15);
+       ATTRIB(XonoticHUDTimerDialog, columns, float, 4);
+       ATTRIB(XonoticHUDTimerDialog, name, string, "HUDtimer");
+       ATTRIB(XonoticHUDTimerDialog, requiresConnection, float, true);
 ENDCLASS(XonoticHUDTimerDialog)
index 1ee05a2f882708a7a3c2940431bc18fa4bcc325b..061c69e56c4797b3d904739b0adcedfe97d79bba 100644 (file)
@@ -3,11 +3,11 @@
 #include "rootdialog.qh"
 CLASS(XonoticHUDVoteDialog, XonoticRootDialog)
        METHOD(XonoticHUDVoteDialog, fill, void(entity));
-       ATTRIB(XonoticHUDVoteDialog, title, string, _("Vote Panel"))
-       ATTRIB(XonoticHUDVoteDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT)
-       ATTRIB(XonoticHUDVoteDialog, intendedWidth, float, 0.4)
-       ATTRIB(XonoticHUDVoteDialog, rows, float, 15)
-       ATTRIB(XonoticHUDVoteDialog, columns, float, 4)
-       ATTRIB(XonoticHUDVoteDialog, name, string, "HUDvote")
-       ATTRIB(XonoticHUDVoteDialog, requiresConnection, float, true)
+       ATTRIB(XonoticHUDVoteDialog, title, string, _("Vote Panel"));
+       ATTRIB(XonoticHUDVoteDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT);
+       ATTRIB(XonoticHUDVoteDialog, intendedWidth, float, 0.4);
+       ATTRIB(XonoticHUDVoteDialog, rows, float, 15);
+       ATTRIB(XonoticHUDVoteDialog, columns, float, 4);
+       ATTRIB(XonoticHUDVoteDialog, name, string, "HUDvote");
+       ATTRIB(XonoticHUDVoteDialog, requiresConnection, float, true);
 ENDCLASS(XonoticHUDVoteDialog)
index 649f7ddd1c1e5dea99df638b5b5e43a3e45544cc..fad14749e6f4665f00b4c460c238a018811d0f37 100644 (file)
@@ -3,11 +3,11 @@
 #include "rootdialog.qh"
 CLASS(XonoticHUDWeaponsDialog, XonoticRootDialog)
        METHOD(XonoticHUDWeaponsDialog, fill, void(entity));
-       ATTRIB(XonoticHUDWeaponsDialog, title, string, _("Weapons Panel"))
-       ATTRIB(XonoticHUDWeaponsDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT)
-       ATTRIB(XonoticHUDWeaponsDialog, intendedWidth, float, 0.4)
-       ATTRIB(XonoticHUDWeaponsDialog, rows, float, 21)
-       ATTRIB(XonoticHUDWeaponsDialog, columns, float, 4)
-       ATTRIB(XonoticHUDWeaponsDialog, name, string, "HUDweapons")
-       ATTRIB(XonoticHUDWeaponsDialog, requiresConnection, float, true)
+       ATTRIB(XonoticHUDWeaponsDialog, title, string, _("Weapons Panel"));
+       ATTRIB(XonoticHUDWeaponsDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT);
+       ATTRIB(XonoticHUDWeaponsDialog, intendedWidth, float, 0.4);
+       ATTRIB(XonoticHUDWeaponsDialog, rows, float, 21);
+       ATTRIB(XonoticHUDWeaponsDialog, columns, float, 4);
+       ATTRIB(XonoticHUDWeaponsDialog, name, string, "HUDweapons");
+       ATTRIB(XonoticHUDWeaponsDialog, requiresConnection, float, true);
 ENDCLASS(XonoticHUDWeaponsDialog)
index e26cfad9b649b607ba467d55ad28880902e8b4ad..8a4479c6f88cc0ce8ed71e8880fa63602fb3c64a 100644 (file)
@@ -3,11 +3,11 @@
 #include "rootdialog.qh"
 CLASS(XonoticHUDExitDialog, XonoticRootDialog)
        METHOD(XonoticHUDExitDialog, fill, void(entity));
-       ATTRIB(XonoticHUDExitDialog, title, string, _("Panel HUD Setup"))
-       ATTRIB(XonoticHUDExitDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT)
-       ATTRIB(XonoticHUDExitDialog, intendedWidth, float, 0.8)
-       ATTRIB(XonoticHUDExitDialog, rows, float, 18)
-       ATTRIB(XonoticHUDExitDialog, columns, float, 8.2)
-       ATTRIB(XonoticHUDExitDialog, name, string, "HUDExit")
-       ATTRIB(XonoticHUDExitDialog, requiresConnection, float, true)
+       ATTRIB(XonoticHUDExitDialog, title, string, _("Panel HUD Setup"));
+       ATTRIB(XonoticHUDExitDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT);
+       ATTRIB(XonoticHUDExitDialog, intendedWidth, float, 0.8);
+       ATTRIB(XonoticHUDExitDialog, rows, float, 18);
+       ATTRIB(XonoticHUDExitDialog, columns, float, 8.2);
+       ATTRIB(XonoticHUDExitDialog, name, string, "HUDExit");
+       ATTRIB(XonoticHUDExitDialog, requiresConnection, float, true);
 ENDCLASS(XonoticHUDExitDialog)
index 2b6f8b44da22eae4aa39be869ff9b4e0a8df6e15..1a6b3388abf4db6cd6003e4cddefe15fa9ce2501 100644 (file)
@@ -3,10 +3,10 @@
 #include "rootdialog.qh"
 CLASS(XonoticMonsterToolsDialog, XonoticRootDialog)
        METHOD(XonoticMonsterToolsDialog, fill, void(entity));
-       ATTRIB(XonoticMonsterToolsDialog, title, string, _("Monster Tools"))
-       ATTRIB(XonoticMonsterToolsDialog, color, vector, SKINCOLOR_DIALOG_SANDBOXTOOLS)
-       ATTRIB(XonoticMonsterToolsDialog, intendedWidth, float, 0.8)
-       ATTRIB(XonoticMonsterToolsDialog, rows, float, 16)
-       ATTRIB(XonoticMonsterToolsDialog, columns, float, 4)
-       ATTRIB(XonoticMonsterToolsDialog, name, string, "MonsterTools")
+       ATTRIB(XonoticMonsterToolsDialog, title, string, _("Monster Tools"));
+       ATTRIB(XonoticMonsterToolsDialog, color, vector, SKINCOLOR_DIALOG_SANDBOXTOOLS);
+       ATTRIB(XonoticMonsterToolsDialog, intendedWidth, float, 0.8);
+       ATTRIB(XonoticMonsterToolsDialog, rows, float, 16);
+       ATTRIB(XonoticMonsterToolsDialog, columns, float, 4);
+       ATTRIB(XonoticMonsterToolsDialog, name, string, "MonsterTools");
 ENDCLASS(XonoticMonsterToolsDialog)
index b18ca55607085d5bd3390eceb6ab9e52535cd87f..74b5285942c18238c3c72c3483dde736c64c1e4f 100644 (file)
@@ -3,10 +3,10 @@
 #include "dialog.qh"
 CLASS(XonoticMultiplayerDialog, XonoticDialog)
        METHOD(XonoticMultiplayerDialog, fill, void(entity));
-       ATTRIB(XonoticMultiplayerDialog, title, string, _("Multiplayer"))
-       ATTRIB(XonoticMultiplayerDialog, tooltip, string, _("Play online, against your friends in LAN, view demos or change player settings"))
-       ATTRIB(XonoticMultiplayerDialog, color, vector, SKINCOLOR_DIALOG_MULTIPLAYER)
-       ATTRIB(XonoticMultiplayerDialog, intendedWidth, float, 0.96)
-       ATTRIB(XonoticMultiplayerDialog, rows, float, 24)
-       ATTRIB(XonoticMultiplayerDialog, columns, float, 4)
+       ATTRIB(XonoticMultiplayerDialog, title, string, _("Multiplayer"));
+       ATTRIB(XonoticMultiplayerDialog, tooltip, string, _("Play online, against your friends in LAN, view demos or change player settings"));
+       ATTRIB(XonoticMultiplayerDialog, color, vector, SKINCOLOR_DIALOG_MULTIPLAYER);
+       ATTRIB(XonoticMultiplayerDialog, intendedWidth, float, 0.96);
+       ATTRIB(XonoticMultiplayerDialog, rows, float, 24);
+       ATTRIB(XonoticMultiplayerDialog, columns, float, 4);
 ENDCLASS(XonoticMultiplayerDialog)
index 5a747a94530c041a7f630500dc61d02de8a954bb..e275522864a84ee9af820e0cb6f55f7323df9efb 100644 (file)
@@ -5,15 +5,15 @@ CLASS(XonoticServerCreateTab, XonoticTab)
        METHOD(XonoticServerCreateTab, fill, void(entity));
        METHOD(XonoticServerCreateTab, gameTypeChangeNotify, void(entity));
        METHOD(XonoticServerCreateTab, gameTypeSelectNotify, void(entity));
-       ATTRIB(XonoticServerCreateTab, intendedWidth, float, 0.9)
-       ATTRIB(XonoticServerCreateTab, rows, float, 23)
-       ATTRIB(XonoticServerCreateTab, columns, float, 6.2)  // added extra .2 for center space
+       ATTRIB(XonoticServerCreateTab, intendedWidth, float, 0.9);
+       ATTRIB(XonoticServerCreateTab, rows, float, 23);
+       ATTRIB(XonoticServerCreateTab, columns, float, 6.2);  // added extra .2 for center space
 
-       ATTRIB(XonoticServerCreateTab, mapListBox, entity, NULL)
-       ATTRIB(XonoticServerCreateTab, sliderFraglimit, entity, NULL)
-       ATTRIB(XonoticServerCreateTab, sliderTeams, entity, NULL)
-       ATTRIB(XonoticServerCreateTab, sliderTimelimit, entity, NULL)
-       ATTRIB(XonoticServerCreateTab, labelFraglimit, entity, NULL)
-       ATTRIB(XonoticServerCreateTab, labelTeams, entity, NULL)
+       ATTRIB(XonoticServerCreateTab, mapListBox, entity);
+       ATTRIB(XonoticServerCreateTab, sliderFraglimit, entity);
+       ATTRIB(XonoticServerCreateTab, sliderTeams, entity);
+       ATTRIB(XonoticServerCreateTab, sliderTimelimit, entity);
+       ATTRIB(XonoticServerCreateTab, labelFraglimit, entity);
+       ATTRIB(XonoticServerCreateTab, labelTeams, entity);
 ENDCLASS(XonoticServerCreateTab)
 entity makeXonoticServerCreateTab();
index 9bc82ebc28754bb8bf5ebbb87c697a3d50b7f813..8fcb975eab6764c5b43d44061102d4ff0132b7b3 100644 (file)
@@ -39,7 +39,7 @@ void XonoticMapInfoDialog_loadMapInfo(entity me, int i, entity mlb)
        {
                entity e;
                e = me.(typeLabels[i]);
-               e.disabled = !(MapInfo_Map_supportedGametypes & GameType_GetID(i));
+               e.disabled = !(MapInfo_Map_supportedGametypes & GameType_GetID(i).m_flags);
        }
 
        MapInfo_ClearTemps();
index 13acfcc777b744066d82ab074942091bef85ee40..b2efb97619c8c8b7d7ea1d47482e669e1deabb6a 100644 (file)
@@ -4,24 +4,24 @@
 CLASS(XonoticMapInfoDialog, XonoticDialog)
        METHOD(XonoticMapInfoDialog, fill, void(entity));
        METHOD(XonoticMapInfoDialog, loadMapInfo, void(entity, float, entity));
-       ATTRIB(XonoticMapInfoDialog, title, string, _("Map Information"))
-       ATTRIB(XonoticMapInfoDialog, color, vector, SKINCOLOR_DIALOG_MAPINFO)
-       ATTRIB(XonoticMapInfoDialog, intendedWidth, float, 1.0)
-       ATTRIB(XonoticMapInfoDialog, rows, float, 11)
-       ATTRIB(XonoticMapInfoDialog, columns, float, 10)
+       ATTRIB(XonoticMapInfoDialog, title, string, _("Map Information"));
+       ATTRIB(XonoticMapInfoDialog, color, vector, SKINCOLOR_DIALOG_MAPINFO);
+       ATTRIB(XonoticMapInfoDialog, intendedWidth, float, 1.0);
+       ATTRIB(XonoticMapInfoDialog, rows, float, 11);
+       ATTRIB(XonoticMapInfoDialog, columns, float, 10);
 
-       ATTRIB(XonoticMapInfoDialog, previewImage, entity, NULL)
-       ATTRIB(XonoticMapInfoDialog, titleLabel, entity, NULL)
-       ATTRIB(XonoticMapInfoDialog, authorLabel, entity, NULL)
-       ATTRIB(XonoticMapInfoDialog, descriptionLabel, entity, NULL)
-       ATTRIB(XonoticMapInfoDialog, featuresLabel, entity, NULL)
+       ATTRIB(XonoticMapInfoDialog, previewImage, entity);
+       ATTRIB(XonoticMapInfoDialog, titleLabel, entity);
+       ATTRIB(XonoticMapInfoDialog, authorLabel, entity);
+       ATTRIB(XonoticMapInfoDialog, descriptionLabel, entity);
+       ATTRIB(XonoticMapInfoDialog, featuresLabel, entity);
 
-       ATTRIBARRAY(XonoticMapInfoDialog, typeLabels, entity, 24)
+       ATTRIBARRAY(XonoticMapInfoDialog, typeLabels, entity, 24);
 
-       ATTRIB(XonoticMapInfoDialog, currentMapIndex, float, 0)
-       ATTRIB(XonoticMapInfoDialog, currentMapBSPName, string, string_null)
-       ATTRIB(XonoticMapInfoDialog, currentMapTitle, string, string_null)
-       ATTRIB(XonoticMapInfoDialog, currentMapAuthor, string, string_null)
-       ATTRIB(XonoticMapInfoDialog, currentMapDescription, string, string_null)
-       ATTRIB(XonoticMapInfoDialog, currentMapPreviewImage, string, string_null)
+       ATTRIB(XonoticMapInfoDialog, currentMapIndex, float, 0);
+       ATTRIB(XonoticMapInfoDialog, currentMapBSPName, string);
+       ATTRIB(XonoticMapInfoDialog, currentMapTitle, string);
+       ATTRIB(XonoticMapInfoDialog, currentMapAuthor, string);
+       ATTRIB(XonoticMapInfoDialog, currentMapDescription, string);
+       ATTRIB(XonoticMapInfoDialog, currentMapPreviewImage, string);
 ENDCLASS(XonoticMapInfoDialog)
index ede8f4cb1fcdab15a2cfe91b3282093b774cc142..48ccc6b48ea0ca853e7710efcf18210af2662ef4 100644 (file)
@@ -6,10 +6,10 @@ CLASS(XonoticMutatorsDialog, XonoticDialog)
        METHOD(XonoticMutatorsDialog, fill, void(entity));
        METHOD(XonoticMutatorsDialog, showNotify, void(entity));
        METHOD(XonoticMutatorsDialog, close, void(entity));
-       ATTRIB(XonoticMutatorsDialog, title, string, _("Mutators"))
-       ATTRIB(XonoticMutatorsDialog, color, vector, SKINCOLOR_DIALOG_MUTATORS)
-       ATTRIB(XonoticMutatorsDialog, intendedWidth, float, 0.9)
-       ATTRIB(XonoticMutatorsDialog, rows, float, 20)
-       ATTRIB(XonoticMutatorsDialog, columns, float, 6)
-       ATTRIB(XonoticMutatorsDialog, refilterEntity, entity, NULL)
+       ATTRIB(XonoticMutatorsDialog, title, string, _("Mutators"));
+       ATTRIB(XonoticMutatorsDialog, color, vector, SKINCOLOR_DIALOG_MUTATORS);
+       ATTRIB(XonoticMutatorsDialog, intendedWidth, float, 0.9);
+       ATTRIB(XonoticMutatorsDialog, rows, float, 20);
+       ATTRIB(XonoticMutatorsDialog, columns, float, 6);
+       ATTRIB(XonoticMutatorsDialog, refilterEntity, entity);
 ENDCLASS(XonoticMutatorsDialog)
index f387f429b651f62895b974dc3550aa58b295bf8a..a34d0d80a1cb12a9e713efb213d147b5f272226d 100644 (file)
@@ -14,6 +14,13 @@ entity makeXonoticServerListTab()
        me.configureDialog(me);
        return me;
 }
+
+void XonoticServerListTab_refresh(entity this, entity slist)
+{
+    bool clear = false;
+    slist.refreshServerList(slist, clear ? REFRESHSERVERLIST_RESET : REFRESHSERVERLIST_ASK);
+}
+
 void XonoticServerListTab_fill(entity me)
 {
        entity e, slist;
@@ -21,13 +28,13 @@ void XonoticServerListTab_fill(entity me)
        slist  = makeXonoticServerList();
 
        me.gotoRC(me, 0.5, 0);
-               me.TD(me, 1, 0.6, e = makeXonoticTextLabel(1, _("Filter:")));
-               me.TD(me, 1, 2.8, e = makeXonoticInputBox(0, string_null));
+               me.TD(me, 1, 0.5, e = makeXonoticTextLabel(1, _("Filter:")));
+               me.TD(me, 1, 2, e = makeXonoticInputBox(0, string_null));
                        e.onChange = ServerList_Filter_Change;
                        e.onChangeEntity = slist;
                        slist.controlledTextbox = e;
 
-       me.gotoRC(me, 0.5, 3.6);
+       me.gotoRC(me, 0.5, 2.6);
                me.TD(me, 1, 0.9, e = makeXonoticCheckBox(0, "menu_slist_categories", ZCTX(_("SRVS^Categories"))));
                        e.onClickEntity = slist;
                        e.onClick = ServerList_Categories_Click;
@@ -43,6 +50,9 @@ void XonoticServerListTab_fill(entity me)
                        e.onClick = ServerList_ShowFull_Click;
                me.TD(me, 1, 0.6, e = makeXonoticCheckBox_T(0, "net_slist_pause", _("Pause"),
                        _("Pause updating the server list to prevent servers from \"jumping around\"")));
+               me.TD(me, 1, 1, e = makeXonoticButton_T(_("Refresh"), '0 0 0', _("Reload the server list")));
+                       e.onClick = XonoticServerListTab_refresh;
+                       e.onClickEntity = slist;
 
        me.gotoRC(me, 2, 0);
                me.TD(me, 1, 1, slist.sortButton1 = makeXonoticButton(string_null, '0 0 0'));
index 7fa837976cfb506f2303cbed9c0ef856f65e4b06..a663eb527be116ba9e0b75bf953e6aba47f2dc2c 100644 (file)
@@ -3,8 +3,8 @@
 #include "tab.qh"
 CLASS(XonoticServerListTab, XonoticTab)
        METHOD(XonoticServerListTab, fill, void(entity));
-       ATTRIB(XonoticServerListTab, intendedWidth, float, 0.9)
-       ATTRIB(XonoticServerListTab, rows, float, 23)
-       ATTRIB(XonoticServerListTab, columns, float, 6.5)
+       ATTRIB(XonoticServerListTab, intendedWidth, float, 0.9);
+       ATTRIB(XonoticServerListTab, rows, float, 23);
+       ATTRIB(XonoticServerListTab, columns, float, 6.5);
 ENDCLASS(XonoticServerListTab)
 entity makeXonoticServerListTab();
index d5532bcd92319757be8e3eea5b9f6ce7a13f39e8..2f37eb7e2b665c260d6e5174797eaaec3d58cda4 100644 (file)
@@ -10,7 +10,7 @@
 void XonoticServerInfoDialog_loadServerInfo(entity me, float i)
 {
        bool pure_available;
-       float m, pure_violations, freeslots, j, numh, maxp, numb, sflags;
+       float m, pure_violations, freeslots, numh, maxp, numb, sflags;
        string s, typestr, versionstr, k, v, modname;
 
        // ====================================
@@ -96,7 +96,7 @@ void XonoticServerInfoDialog_loadServerInfo(entity me, float i)
        freeslots = -1;
        sflags = -1;
        modname = "";
-       for(j = 2; j < m; ++j)
+       for(int j = 2; j < m; ++j)
        {
                if(argv(j) == "")
                        break;
@@ -124,7 +124,7 @@ void XonoticServerInfoDialog_loadServerInfo(entity me, float i)
        if(s != "data")
                modname = sprintf("%s (%s)", modname, s);
 
-       j = MapInfo_Type_FromString(typestr); // try and get the real name of the game type
+       Gametype j = MapInfo_Type_FromString(typestr); // try and get the real name of the game type
        if(j) { typestr = MapInfo_Type_ToText(j); } // only set it if we actually found it
 
        me.currentServerType = strzone(typestr);
index 201f737e9125c80f80b93b66775e215386634fad..68f5ab8ca0c08cc95084715202fbb9ec5e442f36 100644 (file)
@@ -4,42 +4,42 @@
 CLASS(XonoticServerInfoDialog, XonoticDialog)
        METHOD(XonoticServerInfoDialog, fill, void(entity));
        METHOD(XonoticServerInfoDialog, loadServerInfo, void(entity, float));
-       ATTRIB(XonoticServerInfoDialog, title, string, _("Server Information"))
-       ATTRIB(XonoticServerInfoDialog, color, vector, SKINCOLOR_DIALOG_SERVERINFO)
-       ATTRIB(XonoticServerInfoDialog, intendedWidth, float, 0.8)
-       ATTRIB(XonoticServerInfoDialog, rows, float, 18)
-       ATTRIB(XonoticServerInfoDialog, columns, float, 6.2)
+       ATTRIB(XonoticServerInfoDialog, title, string, _("Server Information"));
+       ATTRIB(XonoticServerInfoDialog, color, vector, SKINCOLOR_DIALOG_SERVERINFO);
+       ATTRIB(XonoticServerInfoDialog, intendedWidth, float, 0.8);
+       ATTRIB(XonoticServerInfoDialog, rows, float, 18);
+       ATTRIB(XonoticServerInfoDialog, columns, float, 6.2);
 
-       ATTRIB(XonoticServerInfoDialog, currentServerName, string, string_null)
-       ATTRIB(XonoticServerInfoDialog, currentServerCName, string, string_null)
-       ATTRIB(XonoticServerInfoDialog, currentServerType, string, string_null)
-       ATTRIB(XonoticServerInfoDialog, currentServerMap, string, string_null)
-       ATTRIB(XonoticServerInfoDialog, currentServerPlayers, string, string_null)
-       ATTRIB(XonoticServerInfoDialog, currentServerNumPlayers, string, string_null)
-       ATTRIB(XonoticServerInfoDialog, currentServerNumBots, string, string_null)
-       ATTRIB(XonoticServerInfoDialog, currentServerNumFreeSlots, string, string_null)
-       ATTRIB(XonoticServerInfoDialog, currentServerMod, string, string_null)
-       ATTRIB(XonoticServerInfoDialog, currentServerVersion, string, string_null)
-       ATTRIB(XonoticServerInfoDialog, currentServerKey, string, string_null)
-       ATTRIB(XonoticServerInfoDialog, currentServerID, string, string_null)
-       ATTRIB(XonoticServerInfoDialog, currentServerEncrypt, string, string_null)
-       ATTRIB(XonoticServerInfoDialog, currentServerPure, string, string_null)
+       ATTRIB(XonoticServerInfoDialog, currentServerName, string);
+       ATTRIB(XonoticServerInfoDialog, currentServerCName, string);
+       ATTRIB(XonoticServerInfoDialog, currentServerType, string);
+       ATTRIB(XonoticServerInfoDialog, currentServerMap, string);
+       ATTRIB(XonoticServerInfoDialog, currentServerPlayers, string);
+       ATTRIB(XonoticServerInfoDialog, currentServerNumPlayers, string);
+       ATTRIB(XonoticServerInfoDialog, currentServerNumBots, string);
+       ATTRIB(XonoticServerInfoDialog, currentServerNumFreeSlots, string);
+       ATTRIB(XonoticServerInfoDialog, currentServerMod, string);
+       ATTRIB(XonoticServerInfoDialog, currentServerVersion, string);
+       ATTRIB(XonoticServerInfoDialog, currentServerKey, string);
+       ATTRIB(XonoticServerInfoDialog, currentServerID, string);
+       ATTRIB(XonoticServerInfoDialog, currentServerEncrypt, string);
+       ATTRIB(XonoticServerInfoDialog, currentServerPure, string);
 
-       ATTRIB(XonoticServerInfoDialog, nameLabel, entity, NULL)
-       ATTRIB(XonoticServerInfoDialog, cnameLabel, entity, NULL)
-       ATTRIB(XonoticServerInfoDialog, typeLabel, entity, NULL)
-       ATTRIB(XonoticServerInfoDialog, mapLabel, entity, NULL)
-       ATTRIB(XonoticServerInfoDialog, rawPlayerList, entity, NULL)
-       ATTRIB(XonoticServerInfoDialog, numPlayersLabel, entity, NULL)
-       ATTRIB(XonoticServerInfoDialog, numBotsLabel, entity, NULL)
-       ATTRIB(XonoticServerInfoDialog, numFreeSlotsLabel, entity, NULL)
-       ATTRIB(XonoticServerInfoDialog, modLabel, entity, NULL)
-       ATTRIB(XonoticServerInfoDialog, versionLabel, entity, NULL)
-       ATTRIB(XonoticServerInfoDialog, keyLabel, entity, NULL)
-       ATTRIB(XonoticServerInfoDialog, idLabel, entity, NULL)
-       ATTRIB(XonoticServerInfoDialog, encryptLabel, entity, NULL)
-       ATTRIB(XonoticServerInfoDialog, canConnectLabel, entity, NULL)
-       ATTRIB(XonoticServerInfoDialog, pureLabel, entity, NULL)
+       ATTRIB(XonoticServerInfoDialog, nameLabel, entity);
+       ATTRIB(XonoticServerInfoDialog, cnameLabel, entity);
+       ATTRIB(XonoticServerInfoDialog, typeLabel, entity);
+       ATTRIB(XonoticServerInfoDialog, mapLabel, entity);
+       ATTRIB(XonoticServerInfoDialog, rawPlayerList, entity);
+       ATTRIB(XonoticServerInfoDialog, numPlayersLabel, entity);
+       ATTRIB(XonoticServerInfoDialog, numBotsLabel, entity);
+       ATTRIB(XonoticServerInfoDialog, numFreeSlotsLabel, entity);
+       ATTRIB(XonoticServerInfoDialog, modLabel, entity);
+       ATTRIB(XonoticServerInfoDialog, versionLabel, entity);
+       ATTRIB(XonoticServerInfoDialog, keyLabel, entity);
+       ATTRIB(XonoticServerInfoDialog, idLabel, entity);
+       ATTRIB(XonoticServerInfoDialog, encryptLabel, entity);
+       ATTRIB(XonoticServerInfoDialog, canConnectLabel, entity);
+       ATTRIB(XonoticServerInfoDialog, pureLabel, entity);
 ENDCLASS(XonoticServerInfoDialog)
 
 void Join_Click(entity btn, entity me);
index 96c1aeb75dd74a4aac9d279557fb582ac7bcca91..9713e82c2da595fc6833dc287021a00cae5f7f00 100644 (file)
@@ -3,9 +3,9 @@
 #include "tab.qh"
 CLASS(XonoticMediaTab, XonoticTab)
        METHOD(XonoticMediaTab, fill, void(entity));
-       ATTRIB(XonoticMediaTab, intendedWidth, float, 0.9)
-       ATTRIB(XonoticMediaTab, rows, float, 23)
-       ATTRIB(XonoticMediaTab, columns, float, 3)
-       ATTRIB(XonoticMediaTab, name, string, "Media")
+       ATTRIB(XonoticMediaTab, intendedWidth, float, 0.9);
+       ATTRIB(XonoticMediaTab, rows, float, 23);
+       ATTRIB(XonoticMediaTab, columns, float, 3);
+       ATTRIB(XonoticMediaTab, name, string, "Media");
 ENDCLASS(XonoticMediaTab)
 entity makeXonoticMediaTab();
index f41bb9e812f31ef0567bc655b478c551429057d5..cf3548d77409e791fecf40d9bf1caec2cab8371d 100644 (file)
@@ -3,10 +3,10 @@
 #include "tab.qh"
 CLASS(XonoticDemoBrowserTab, XonoticTab)
        METHOD(XonoticDemoBrowserTab, fill, void(entity));
-       ATTRIB(XonoticDemoBrowserTab, intendedWidth, float, 0.9)
-       ATTRIB(XonoticDemoBrowserTab, rows, float, 21)
-       ATTRIB(XonoticDemoBrowserTab, columns, float, 6.5)
-       ATTRIB(XonoticDemoBrowserTab, name, string, "DemoBrowser")
-       ATTRIB(XonoticDemoBrowserTab, democlicktype, float, 0)
+       ATTRIB(XonoticDemoBrowserTab, intendedWidth, float, 0.9);
+       ATTRIB(XonoticDemoBrowserTab, rows, float, 21);
+       ATTRIB(XonoticDemoBrowserTab, columns, float, 6.5);
+       ATTRIB(XonoticDemoBrowserTab, name, string, "DemoBrowser");
+       ATTRIB(XonoticDemoBrowserTab, democlicktype, float, 0);
 ENDCLASS(XonoticDemoBrowserTab)
 entity makeXonoticDemoBrowserTab();
index 598dd5503f8f918f333a14a42d665ce26b8c23f6..934490f755ece18731820912a21228671fec5109 100644 (file)
@@ -3,9 +3,9 @@
 #include "dialog.qh"
 CLASS(XonoticDemoStartConfirmDialog, XonoticDialog)
        METHOD(XonoticDemoStartConfirmDialog, fill, void(entity));
-       ATTRIB(XonoticDemoStartConfirmDialog, title, string, _("Disconnect"))
-       ATTRIB(XonoticDemoStartConfirmDialog, color, vector, SKINCOLOR_DIALOG_HUDCONFIRM)
-       ATTRIB(XonoticDemoStartConfirmDialog, intendedWidth, float, 0.5)
-       ATTRIB(XonoticDemoStartConfirmDialog, rows, float, 4)
-       ATTRIB(XonoticDemoStartConfirmDialog, columns, float, 2)
+       ATTRIB(XonoticDemoStartConfirmDialog, title, string, _("Disconnect"));
+       ATTRIB(XonoticDemoStartConfirmDialog, color, vector, SKINCOLOR_DIALOG_HUDCONFIRM);
+       ATTRIB(XonoticDemoStartConfirmDialog, intendedWidth, float, 0.5);
+       ATTRIB(XonoticDemoStartConfirmDialog, rows, float, 4);
+       ATTRIB(XonoticDemoStartConfirmDialog, columns, float, 2);
 ENDCLASS(XonoticDemoStartConfirmDialog)
index 96e2d631036698fa71441f70f3618e632da72ef1..80c2766de2e4047b20f6df735863d823efc22439 100644 (file)
@@ -3,9 +3,9 @@
 #include "dialog.qh"
 CLASS(XonoticDemoTimeConfirmDialog, XonoticDialog)
        METHOD(XonoticDemoTimeConfirmDialog, fill, void(entity));
-       ATTRIB(XonoticDemoTimeConfirmDialog, title, string, _("Disconnect"))
-       ATTRIB(XonoticDemoTimeConfirmDialog, color, vector, SKINCOLOR_DIALOG_HUDCONFIRM)
-       ATTRIB(XonoticDemoTimeConfirmDialog, intendedWidth, float, 0.5)
-       ATTRIB(XonoticDemoTimeConfirmDialog, rows, float, 4)
-       ATTRIB(XonoticDemoTimeConfirmDialog, columns, float, 2)
+       ATTRIB(XonoticDemoTimeConfirmDialog, title, string, _("Disconnect"));
+       ATTRIB(XonoticDemoTimeConfirmDialog, color, vector, SKINCOLOR_DIALOG_HUDCONFIRM);
+       ATTRIB(XonoticDemoTimeConfirmDialog, intendedWidth, float, 0.5);
+       ATTRIB(XonoticDemoTimeConfirmDialog, rows, float, 4);
+       ATTRIB(XonoticDemoTimeConfirmDialog, columns, float, 2);
 ENDCLASS(XonoticDemoTimeConfirmDialog)
index 4d98f6ec17ba051ae165a2ee0e6995e7fe583460..6172dae03cbff4bffadab55e694ab68fd9859c72 100644 (file)
@@ -3,9 +3,9 @@
 #include "tab.qh"
 CLASS(XonoticMusicPlayerTab, XonoticTab)
        METHOD(XonoticMusicPlayerTab, fill, void(entity));
-       ATTRIB(XonoticMusicPlayerTab, intendedWidth, float, 0.9)
-       ATTRIB(XonoticMusicPlayerTab, rows, float, 21)
-       ATTRIB(XonoticMusicPlayerTab, columns, float, 6.5)
-       ATTRIB(XonoticMusicPlayerTab, name, string, "MusicPlayer")
+       ATTRIB(XonoticMusicPlayerTab, intendedWidth, float, 0.9);
+       ATTRIB(XonoticMusicPlayerTab, rows, float, 21);
+       ATTRIB(XonoticMusicPlayerTab, columns, float, 6.5);
+       ATTRIB(XonoticMusicPlayerTab, name, string, "MusicPlayer");
 ENDCLASS(XonoticMusicPlayerTab)
 entity makeXonoticMusicPlayerTab();
index 62ea8438a069a65cc5e1cdb70c6f8f30f1079f61..66dc3cf077fac5591b20881fcb52d70cf53b8575 100644 (file)
@@ -3,13 +3,13 @@
 #include "tab.qh"
 CLASS(XonoticScreenshotBrowserTab, XonoticTab)
        METHOD(XonoticScreenshotBrowserTab, fill, void(entity));
-       ATTRIB(XonoticScreenshotBrowserTab, intendedWidth, float, 1)
-       ATTRIB(XonoticScreenshotBrowserTab, rows, float, 21)
-       ATTRIB(XonoticScreenshotBrowserTab, columns, float, 6.5)
-       ATTRIB(XonoticScreenshotBrowserTab, name, string, "ScreenshotBrowser")
+       ATTRIB(XonoticScreenshotBrowserTab, intendedWidth, float, 1);
+       ATTRIB(XonoticScreenshotBrowserTab, rows, float, 21);
+       ATTRIB(XonoticScreenshotBrowserTab, columns, float, 6.5);
+       ATTRIB(XonoticScreenshotBrowserTab, name, string, "ScreenshotBrowser");
 
        METHOD(XonoticScreenshotBrowserTab, loadPreviewScreenshot, void(entity, string));
-       ATTRIB(XonoticScreenshotBrowserTab, screenshotImage, entity, NULL)
-       ATTRIB(XonoticScreenshotBrowserTab, currentScrPath, string, string_null)
+       ATTRIB(XonoticScreenshotBrowserTab, screenshotImage, entity);
+       ATTRIB(XonoticScreenshotBrowserTab, currentScrPath, string);
 ENDCLASS(XonoticScreenshotBrowserTab)
 entity makeXonoticScreenshotBrowserTab();
index c4f7e61262eca64c609e94d117853a91ad566a27..ad1656e4f71555e28b268adcf5a1316fcd0aa3f0 100644 (file)
@@ -9,14 +9,14 @@ CLASS(XonoticScreenshotViewerDialog, XonoticDialog)
        METHOD(XonoticScreenshotViewerDialog, keyDown, float(entity, float, float, float));
        METHOD(XonoticScreenshotViewerDialog, loadScreenshot, void(entity, string));
        METHOD(XonoticScreenshotViewerDialog, close, void(entity));
-       ATTRIB(XonoticScreenshotViewerDialog, title, string, "Screenshot Viewer")
-       ATTRIB(XonoticScreenshotViewerDialog, name, string, "ScreenshotViewer")
-       ATTRIB(XonoticScreenshotViewerDialog, intendedWidth, float, 1)
-       ATTRIB(XonoticScreenshotViewerDialog, rows, float, 25)
-       ATTRIB(XonoticScreenshotViewerDialog, columns, float, 4)
-       ATTRIB(XonoticScreenshotViewerDialog, color, vector, SKINCOLOR_DIALOG_SCREENSHOTVIEWER)
-       ATTRIB(XonoticScreenshotViewerDialog, scrList, entity, NULL)
-       ATTRIB(XonoticScreenshotViewerDialog, screenshotImage, entity, NULL)
-       ATTRIB(XonoticScreenshotViewerDialog, slideShowButton, entity, NULL)
-       ATTRIB(XonoticScreenshotViewerDialog, currentScrPath, string, string_null)
+       ATTRIB(XonoticScreenshotViewerDialog, title, string, "Screenshot Viewer");
+       ATTRIB(XonoticScreenshotViewerDialog, name, string, "ScreenshotViewer");
+       ATTRIB(XonoticScreenshotViewerDialog, intendedWidth, float, 1);
+       ATTRIB(XonoticScreenshotViewerDialog, rows, float, 25);
+       ATTRIB(XonoticScreenshotViewerDialog, columns, float, 4);
+       ATTRIB(XonoticScreenshotViewerDialog, color, vector, SKINCOLOR_DIALOG_SCREENSHOTVIEWER);
+       ATTRIB(XonoticScreenshotViewerDialog, scrList, entity);
+       ATTRIB(XonoticScreenshotViewerDialog, screenshotImage, entity);
+       ATTRIB(XonoticScreenshotViewerDialog, slideShowButton, entity);
+       ATTRIB(XonoticScreenshotViewerDialog, currentScrPath, string);
 ENDCLASS(XonoticScreenshotViewerDialog)
index f60e9e0bb3450b59a28a8a5e3725654506a86a63..2285efcafa370cb6a2da6e8a0cc6c895176b96b6 100644 (file)
@@ -4,10 +4,10 @@
 CLASS(XonoticProfileTab, XonoticTab)
        METHOD(XonoticProfileTab, fill, void(entity));
        METHOD(XonoticProfileTab, draw, void(entity));
-       ATTRIB(XonoticProfileTab, intendedWidth, float, 0.9)
-       ATTRIB(XonoticProfileTab, rows, float, 23)
-       ATTRIB(XonoticProfileTab, columns, float, 6.1)  // added extra .2 for center space
-       ATTRIB(XonoticProfileTab, playerNameLabel, entity, NULL)
-       ATTRIB(XonoticProfileTab, playerNameLabelAlpha, float, SKINALPHA_HEADER)
+       ATTRIB(XonoticProfileTab, intendedWidth, float, 0.9);
+       ATTRIB(XonoticProfileTab, rows, float, 23);
+       ATTRIB(XonoticProfileTab, columns, float, 6.1);  // added extra .2 for center space
+       ATTRIB(XonoticProfileTab, playerNameLabel, entity);
+       ATTRIB(XonoticProfileTab, playerNameLabelAlpha, float, SKINALPHA_HEADER);
 ENDCLASS(XonoticProfileTab)
 entity makeXonoticProfileTab();
index 0b06c30d6a41e236db274c220dbf7906b675801d..6e8c9fea9a9748d7346f6969f4be0ace5b4fe635 100644 (file)
@@ -3,11 +3,11 @@
 #include "dialog.qh"
 CLASS(XonoticQuitDialog, XonoticDialog)
        METHOD(XonoticQuitDialog, fill, void(entity));
-       ATTRIB(XonoticQuitDialog, title, string, _("Quit"))
-       ATTRIB(XonoticQuitDialog, tooltip, string, _("Quit the game"))
-       ATTRIB(XonoticQuitDialog, color, vector, SKINCOLOR_DIALOG_QUIT)
-       ATTRIB(XonoticQuitDialog, intendedWidth, float, 0.5)
-       ATTRIB(XonoticQuitDialog, rows, float, 3)
-       ATTRIB(XonoticQuitDialog, columns, float, 2)
-       ATTRIB(XonoticQuitDialog, name, string, "Quit")
+       ATTRIB(XonoticQuitDialog, title, string, _("Quit"));
+       ATTRIB(XonoticQuitDialog, tooltip, string, _("Quit the game"));
+       ATTRIB(XonoticQuitDialog, color, vector, SKINCOLOR_DIALOG_QUIT);
+       ATTRIB(XonoticQuitDialog, intendedWidth, float, 0.5);
+       ATTRIB(XonoticQuitDialog, rows, float, 3);
+       ATTRIB(XonoticQuitDialog, columns, float, 2);
+       ATTRIB(XonoticQuitDialog, name, string, "Quit");
 ENDCLASS(XonoticQuitDialog)
index ab49ec867d688a694b62df1aaaad1ac545c2b6b2..2ef0d797390a218dcf2e4b6d0c46be595f4cc947 100644 (file)
@@ -3,11 +3,11 @@
 #include "rootdialog.qh"
 CLASS(XonoticSandboxToolsDialog, XonoticRootDialog)
        METHOD(XonoticSandboxToolsDialog, fill, void(entity));
-       ATTRIB(XonoticSandboxToolsDialog, title, string, _("Sandbox Tools"))
-       ATTRIB(XonoticSandboxToolsDialog, color, vector, SKINCOLOR_DIALOG_SANDBOXTOOLS)
-       ATTRIB(XonoticSandboxToolsDialog, intendedWidth, float, 0.8)
-       ATTRIB(XonoticSandboxToolsDialog, rows, float, 16)
-       ATTRIB(XonoticSandboxToolsDialog, columns, float, 4)
-       ATTRIB(XonoticSandboxToolsDialog, name, string, "SandboxTools")
-       ATTRIB(XonoticSandboxToolsDialog, requiresConnection, float, true)
+       ATTRIB(XonoticSandboxToolsDialog, title, string, _("Sandbox Tools"));
+       ATTRIB(XonoticSandboxToolsDialog, color, vector, SKINCOLOR_DIALOG_SANDBOXTOOLS);
+       ATTRIB(XonoticSandboxToolsDialog, intendedWidth, float, 0.8);
+       ATTRIB(XonoticSandboxToolsDialog, rows, float, 16);
+       ATTRIB(XonoticSandboxToolsDialog, columns, float, 4);
+       ATTRIB(XonoticSandboxToolsDialog, name, string, "SandboxTools");
+       ATTRIB(XonoticSandboxToolsDialog, requiresConnection, float, true);
 ENDCLASS(XonoticSandboxToolsDialog)
index 6c7eacb7ca42328fb5ff5236a981f78139bc559d..3564a02e87dd5bb9140f60d7216198992cd6969e 100644 (file)
@@ -3,10 +3,10 @@
 #include "dialog.qh"
 CLASS(XonoticSettingsDialog, XonoticDialog)
        METHOD(XonoticSettingsDialog, fill, void(entity));
-       ATTRIB(XonoticSettingsDialog, title, string, _("Settings"))
-       ATTRIB(XonoticSettingsDialog, tooltip, string, _("Change the game settings"))
-       ATTRIB(XonoticSettingsDialog, color, vector, SKINCOLOR_DIALOG_SETTINGS)
-       ATTRIB(XonoticSettingsDialog, intendedWidth, float, 0.96)
-       ATTRIB(XonoticSettingsDialog, rows, float, 18)
-       ATTRIB(XonoticSettingsDialog, columns, float, 6)
+       ATTRIB(XonoticSettingsDialog, title, string, _("Settings"));
+       ATTRIB(XonoticSettingsDialog, tooltip, string, _("Change the game settings"));
+       ATTRIB(XonoticSettingsDialog, color, vector, SKINCOLOR_DIALOG_SETTINGS);
+       ATTRIB(XonoticSettingsDialog, intendedWidth, float, 0.96);
+       ATTRIB(XonoticSettingsDialog, rows, float, 18);
+       ATTRIB(XonoticSettingsDialog, columns, float, 6);
 ENDCLASS(XonoticSettingsDialog)
index a3e8a8c532d8566a65d5a66cd217d6995ec7b0a2..5794a70ccfb8e1852b59dc15b226d24fbdf846e0 100644 (file)
@@ -3,9 +3,9 @@
 #include "tab.qh"
 CLASS(XonoticAudioSettingsTab, XonoticTab)
        METHOD(XonoticAudioSettingsTab, fill, void(entity));
-       ATTRIB(XonoticAudioSettingsTab, intendedWidth, float, 0.9)
-       ATTRIB(XonoticAudioSettingsTab, rows, float, 15.5)
-       ATTRIB(XonoticAudioSettingsTab, columns, float, 6.2)  // added extra .2 for center space
-       ATTRIB(XonoticAudioSettingsTab, hiddenMenuSoundsSlider, entity, NULL)
+       ATTRIB(XonoticAudioSettingsTab, intendedWidth, float, 0.9);
+       ATTRIB(XonoticAudioSettingsTab, rows, float, 15.5);
+       ATTRIB(XonoticAudioSettingsTab, columns, float, 6.2);  // added extra .2 for center space
+       ATTRIB(XonoticAudioSettingsTab, hiddenMenuSoundsSlider, entity);
 ENDCLASS(XonoticAudioSettingsTab)
 entity makeXonoticAudioSettingsTab();
index 97f3854fbba89c73f07321951ffa6b5964a51411..369c68d9132932d434315e3b630098b57807fbfb 100644 (file)
@@ -3,8 +3,8 @@
 #include "tab.qh"
 CLASS(XonoticEffectsSettingsTab, XonoticTab)
        METHOD(XonoticEffectsSettingsTab, fill, void(entity));
-       ATTRIB(XonoticEffectsSettingsTab, intendedWidth, float, 0.9)
-       ATTRIB(XonoticEffectsSettingsTab, rows, float, 15.5)
-       ATTRIB(XonoticEffectsSettingsTab, columns, float, 6.2)  // added extra .2 for center space
+       ATTRIB(XonoticEffectsSettingsTab, intendedWidth, float, 0.9);
+       ATTRIB(XonoticEffectsSettingsTab, rows, float, 15.5);
+       ATTRIB(XonoticEffectsSettingsTab, columns, float, 6.2);  // added extra .2 for center space
 ENDCLASS(XonoticEffectsSettingsTab)
 entity makeXonoticEffectsSettingsTab();
index c415e96732cee4c6c796ae4d8cc64bde5006be3c..b9231642b18e9b016afb5277531a6e15fe1bea84 100644 (file)
@@ -9,19 +9,19 @@ ENDCLASS(SettingSource)
 
 #include "listbox.qh"
 CLASS(XonoticRegisteredSettingsList, XonoticListBox)
-       ATTRIB(XonoticRegisteredSettingsList, alphaBG, float, 0)
-       ATTRIB(XonoticRegisteredSettingsList, itemAbsSize, vector, '0 0 0')
-       ATTRIB(XonoticRegisteredSettingsList, origin, vector, '0 0 0')
-       ATTRIB(XonoticRegisteredSettingsList, realFontSize, vector, '0 0 0')
-       ATTRIB(XonoticRegisteredSettingsList, realUpperMargin, float, 0)
-       ATTRIB(XonoticRegisteredSettingsList, rowsPerItem, float, 2)
-       ATTRIB(XonoticRegisteredSettingsList, stringFilterBox, entity, NULL)
-       ATTRIB(XonoticRegisteredSettingsList, stringFilter, string, string_null)
-       ATTRIB(XonoticRegisteredSettingsList, typeToSearchString, string, string_null)
-       ATTRIB(XonoticRegisteredSettingsList, typeToSearchTime, float, 0)
-       ATTRIB(XonoticRegisteredSettingsList, source, DataSource, NULL)
-       ATTRIB(XonoticRegisteredSettingsList, onChange, void(entity, entity), func_null)
-       ATTRIB(XonoticRegisteredSettingsList, onChangeEntity, entity, NULL)
+       ATTRIB(XonoticRegisteredSettingsList, alphaBG, float, 0);
+       ATTRIB(XonoticRegisteredSettingsList, itemAbsSize, vector, '0 0 0');
+       ATTRIB(XonoticRegisteredSettingsList, origin, vector, '0 0 0');
+       ATTRIB(XonoticRegisteredSettingsList, realFontSize, vector, '0 0 0');
+       ATTRIB(XonoticRegisteredSettingsList, realUpperMargin, float, 0);
+       ATTRIB(XonoticRegisteredSettingsList, rowsPerItem, float, 2);
+       ATTRIB(XonoticRegisteredSettingsList, stringFilterBox, entity);
+       ATTRIB(XonoticRegisteredSettingsList, stringFilter, string);
+       ATTRIB(XonoticRegisteredSettingsList, typeToSearchString, string);
+       ATTRIB(XonoticRegisteredSettingsList, typeToSearchTime, float, 0);
+       ATTRIB(XonoticRegisteredSettingsList, source, DataSource);
+       ATTRIB(XonoticRegisteredSettingsList, onChange, void(entity, entity));
+       ATTRIB(XonoticRegisteredSettingsList, onChangeEntity, entity);
        METHOD(XonoticRegisteredSettingsList, focusedItemChangeNotify, void(entity));
        METHOD(XonoticRegisteredSettingsList, drawListBoxItem, void(entity this, int i, vector absSize, bool isSelected, bool isFocused));
        METHOD(XonoticRegisteredSettingsList, focusedItemChangeNotify, void(entity this));
@@ -33,13 +33,13 @@ ENDCLASS(XonoticRegisteredSettingsList)
 
 #include "tab.qh"
 CLASS(XonoticGameSettingsTab, XonoticTab)
-       ATTRIB(XonoticGameSettingsTab, intendedWidth, float, 0.9)
-       ATTRIB(XonoticGameSettingsTab, rows, float, 15.5)
-       ATTRIB(XonoticGameSettingsTab, columns, float, 6.5)
-       ATTRIB(XonoticGameSettingsTab, source, DataSource, NEW(SettingSource))
-       ATTRIB(XonoticGameSettingsTab, topicList, entity, NEW(XonoticRegisteredSettingsList, this.source))
-       ATTRIB(XonoticGameSettingsTab, currentPanel, entity, NEW(XonoticTab))
-       ATTRIB(XonoticGameSettingsTab, currentItem, entity, NULL)
+       ATTRIB(XonoticGameSettingsTab, intendedWidth, float, 0.9);
+       ATTRIB(XonoticGameSettingsTab, rows, float, 15.5);
+       ATTRIB(XonoticGameSettingsTab, columns, float, 6.5);
+       ATTRIB(XonoticGameSettingsTab, source, DataSource, NEW(SettingSource));
+       ATTRIB(XonoticGameSettingsTab, topicList, entity, NEW(XonoticRegisteredSettingsList, this.source));
+       ATTRIB(XonoticGameSettingsTab, currentPanel, entity, NEW(XonoticTab));
+       ATTRIB(XonoticGameSettingsTab, currentItem, entity);
        METHOD(XonoticGameSettingsTab, topicChangeNotify, void(entity, entity this));
        METHOD(XonoticGameSettingsTab, fill, void(entity this));
        INIT(XonoticGameSettingsTab)
index 3e1222056143917af19b0d8f2c1299407a639260..33576a3ec0a3ffdd0a5bd5ce7f59f4b07afb51fa 100644 (file)
@@ -4,10 +4,10 @@
 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, 15.5)
-       ATTRIB(XonoticGameCrosshairSettingsTab, columns, float, 6.2)
+       ATTRIB(XonoticGameCrosshairSettingsTab, title, string, _("Crosshair"));
+       ATTRIB(XonoticGameCrosshairSettingsTab, intendedWidth, float, 0.9);
+       ATTRIB(XonoticGameCrosshairSettingsTab, rows, float, 15.5);
+       ATTRIB(XonoticGameCrosshairSettingsTab, columns, float, 6.2);
 ENDCLASS(XonoticGameCrosshairSettingsTab)
 entity makeXonoticGameCrosshairSettingsTab();
 
index 6525e2779c5139f1e80b278eeff797dd85d09976..e16693675b91cafa32da4601b4436a30e0698626 100644 (file)
@@ -43,20 +43,18 @@ void XonoticGameHUDSettingsTab_fill(entity me)
                me.TD(me, 1, 3, e = makeXonoticHeaderLabel(_("Scoreboard")));
        me.TR(me);
        me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Alpha:")));
-       me.TD(me, 1, 2, e = makeXonoticSlider(0, 1, 0.05, "scoreboard_alpha_bg"));
+       me.TD(me, 1, 2, e = makeXonoticSlider(0, 1, 0.05, "hud_panel_scoreboard_bg_alpha"));
        me.TR(me);
                me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Fading speed:")));
                me.TD(me, 1, 2, e = makeXonoticScoreboardFadeTimeSlider());
        me.TR(me);
-               me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Side padding:")));
-               me.TD(me, 1, 2, e = makeXonoticSlider(0.05, 0.3, 0.01, "scoreboard_offset_left"));
-                       makeMulti(e, "scoreboard_offset_right");
+               me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "hud_panel_scoreboard_table_highlight", _("Enable rows / columns highlighting")));
 
        me.TR(me);
        //me.TR(me);
-               me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "scoreboard_respawntime_decimals", _("Show decimals in respawn countdown")));
+               me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "hud_panel_scoreboard_respawntime_decimals", _("Show decimals in respawn countdown")));
        me.TR(me);
-               me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "scoreboard_accuracy", _("Show accuracy underneath scoreboard")));
+               me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "hud_panel_scoreboard_accuracy", _("Show accuracy underneath scoreboard")));
 
        me.TR(me);
        me.TR(me);
index 1db5890be8d0e013ea6f086e206cf8d482f62129..a9851dc63414255e95a64b301797ee9c8d9c0462 100644 (file)
@@ -4,10 +4,10 @@
 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, 15.5)
-       ATTRIB(XonoticGameHUDSettingsTab, columns, float, 6.2)
+       ATTRIB(XonoticGameHUDSettingsTab, title, string, _("HUD"));
+       ATTRIB(XonoticGameHUDSettingsTab, intendedWidth, float, 0.9);
+       ATTRIB(XonoticGameHUDSettingsTab, rows, float, 15.5);
+       ATTRIB(XonoticGameHUDSettingsTab, columns, float, 6.2);
 ENDCLASS(XonoticGameHUDSettingsTab)
 entity makeXonoticGameHUDSettingsTab();
 void HUDSetup_Start(entity me, entity btn);
index 6e8421eecd0877d444742cc99af40cd49701713f..bef13432ecf44b87b5fbfda5e22d4f274fd60272 100644 (file)
@@ -3,9 +3,9 @@
 #include "dialog.qh"
 CLASS(XonoticHUDConfirmDialog, XonoticDialog)
        METHOD(XonoticHUDConfirmDialog, fill, void(entity));
-       ATTRIB(XonoticHUDConfirmDialog, title, string, _("Enter HUD editor"))
-       ATTRIB(XonoticHUDConfirmDialog, color, vector, SKINCOLOR_DIALOG_HUDCONFIRM)
-       ATTRIB(XonoticHUDConfirmDialog, intendedWidth, float, 0.5)
-       ATTRIB(XonoticHUDConfirmDialog, rows, float, 4)
-       ATTRIB(XonoticHUDConfirmDialog, columns, float, 2)
+       ATTRIB(XonoticHUDConfirmDialog, title, string, _("Enter HUD editor"));
+       ATTRIB(XonoticHUDConfirmDialog, color, vector, SKINCOLOR_DIALOG_HUDCONFIRM);
+       ATTRIB(XonoticHUDConfirmDialog, intendedWidth, float, 0.5);
+       ATTRIB(XonoticHUDConfirmDialog, rows, float, 4);
+       ATTRIB(XonoticHUDConfirmDialog, columns, float, 2);
 ENDCLASS(XonoticHUDConfirmDialog)
index 56d13bcb960e4d6dfe8011f2119358e28be9c9b6..28a7698626368175b407ae3b2e2accc7c26084e8 100644 (file)
@@ -4,11 +4,11 @@
 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, 15.5)
-       ATTRIB(XonoticGameMessageSettingsTab, columns, float, 6)
-       ATTRIB(XonoticGameMessageSettingsTab, weaponsList, entity, NULL)
+       ATTRIB(XonoticGameMessageSettingsTab, title, string, _("Messages"));
+       ATTRIB(XonoticGameMessageSettingsTab, intendedWidth, float, 0.9);
+       ATTRIB(XonoticGameMessageSettingsTab, rows, float, 15.5);
+       ATTRIB(XonoticGameMessageSettingsTab, columns, float, 6);
+       ATTRIB(XonoticGameMessageSettingsTab, weaponsList, entity);
 ENDCLASS(XonoticGameMessageSettingsTab)
 entity makeXonoticGameMessageSettingsTab();
 #include "../gamesettings.qh"
index 8dd6eaecb321cbb50f490e9de0c7b25d6c4f0ada..c3caabee724b3f4a4c7bc620a0e09f1e7f55d93b 100644 (file)
@@ -4,11 +4,11 @@
 CLASS(XonoticGameModelSettingsTab, XonoticTab)
        METHOD(XonoticGameModelSettingsTab, fill, void(entity));
        METHOD(XonoticGameModelSettingsTab, showNotify, void(entity));
-       ATTRIB(XonoticGameModelSettingsTab, title, string, _("Models"))
-       ATTRIB(XonoticGameModelSettingsTab, titleTooltip, string, _("Customize how players and items are displayed in game"))
-       ATTRIB(XonoticGameModelSettingsTab, intendedWidth, float, 0.9)
-       ATTRIB(XonoticGameModelSettingsTab, rows, float, 15.5)
-       ATTRIB(XonoticGameModelSettingsTab, columns, float, 5)
+       ATTRIB(XonoticGameModelSettingsTab, title, string, _("Models"));
+       ATTRIB(XonoticGameModelSettingsTab, titleTooltip, string, _("Customize how players and items are displayed in game"));
+       ATTRIB(XonoticGameModelSettingsTab, intendedWidth, float, 0.9);
+       ATTRIB(XonoticGameModelSettingsTab, rows, float, 15.5);
+       ATTRIB(XonoticGameModelSettingsTab, columns, float, 5);
 ENDCLASS(XonoticGameModelSettingsTab)
 entity makeXonoticGameModelSettingsTab();
 #include "../gamesettings.qh"
index 7ec4c79366b9ffcb2cddad2f29b49a44c83a9a63..f9d6001199b740f6555230112c19fd616fc22971 100644 (file)
@@ -4,10 +4,10 @@
 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, 15.5)
-       ATTRIB(XonoticGameViewSettingsTab, columns, float, 6.2)
+       ATTRIB(XonoticGameViewSettingsTab, title, string, _("View"));
+       ATTRIB(XonoticGameViewSettingsTab, intendedWidth, float, 0.9);
+       ATTRIB(XonoticGameViewSettingsTab, rows, float, 15.5);
+       ATTRIB(XonoticGameViewSettingsTab, columns, float, 6.2);
 ENDCLASS(XonoticGameViewSettingsTab)
 entity makeXonoticGameViewSettingsTab();
 #include "../gamesettings.qh"
index 73ee66fb27e42138e926ffeb15127130a7000242..ded41a5abdeb25963cccdef129ba591642df879a 100644 (file)
@@ -4,11 +4,11 @@
 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, 15.5)
-       ATTRIB(XonoticGameWeaponsSettingsTab, columns, float, 6)
-       ATTRIB(XonoticGameWeaponsSettingsTab, weaponsList, entity, NULL)
+       ATTRIB(XonoticGameWeaponsSettingsTab, title, string, _("Weapons"));
+       ATTRIB(XonoticGameWeaponsSettingsTab, intendedWidth, float, 0.9);
+       ATTRIB(XonoticGameWeaponsSettingsTab, rows, float, 15.5);
+       ATTRIB(XonoticGameWeaponsSettingsTab, columns, float, 6);
+       ATTRIB(XonoticGameWeaponsSettingsTab, weaponsList, entity);
 ENDCLASS(XonoticGameWeaponsSettingsTab)
 entity makeXonoticGameWeaponsSettingsTab();
 #include "../gamesettings.qh"
index f8e6feda6c9489f080da7db1d3451b5dcdf6b432..040908298976dd5784f3b7708ba6af6ae2d9e530 100644 (file)
@@ -3,8 +3,8 @@
 #include "tab.qh"
 CLASS(XonoticInputSettingsTab, XonoticTab)
        METHOD(XonoticInputSettingsTab, fill, void(entity));
-       ATTRIB(XonoticInputSettingsTab, intendedWidth, float, 0.9)
-       ATTRIB(XonoticInputSettingsTab, rows, float, 15.5)
-       ATTRIB(XonoticInputSettingsTab, columns, float, 6.2)  // added extra .2 for center space
+       ATTRIB(XonoticInputSettingsTab, intendedWidth, float, 0.9);
+       ATTRIB(XonoticInputSettingsTab, rows, float, 15.5);
+       ATTRIB(XonoticInputSettingsTab, columns, float, 6.2);  // added extra .2 for center space
 ENDCLASS(XonoticInputSettingsTab)
 entity makeXonoticInputSettingsTab();
index 5ff3a2e0bcc2edbce1936036fbc7c2423cf91223..561a04b32b2326f0a9a9226df550a1b8d2790a5c 100644 (file)
@@ -4,14 +4,14 @@
 CLASS(XonoticUserbindEditDialog, XonoticDialog)
        METHOD(XonoticUserbindEditDialog, loadUserBind, void(entity, string, string, string));
        METHOD(XonoticUserbindEditDialog, fill, void(entity));
-       ATTRIB(XonoticUserbindEditDialog, title, string, _("User defined key bind"))
-       ATTRIB(XonoticUserbindEditDialog, color, vector, SKINCOLOR_DIALOG_USERBIND)
-       ATTRIB(XonoticUserbindEditDialog, intendedWidth, float, 0.7)
-       ATTRIB(XonoticUserbindEditDialog, rows, float, 4)
-       ATTRIB(XonoticUserbindEditDialog, columns, float, 3)
-       ATTRIB(XonoticUserbindEditDialog, keybindBox, entity, NULL)
+       ATTRIB(XonoticUserbindEditDialog, title, string, _("User defined key bind"));
+       ATTRIB(XonoticUserbindEditDialog, color, vector, SKINCOLOR_DIALOG_USERBIND);
+       ATTRIB(XonoticUserbindEditDialog, intendedWidth, float, 0.7);
+       ATTRIB(XonoticUserbindEditDialog, rows, float, 4);
+       ATTRIB(XonoticUserbindEditDialog, columns, float, 3);
+       ATTRIB(XonoticUserbindEditDialog, keybindBox, entity);
 
-       ATTRIB(XonoticUserbindEditDialog, nameBox, entity, NULL)
-       ATTRIB(XonoticUserbindEditDialog, commandPressBox, entity, NULL)
-       ATTRIB(XonoticUserbindEditDialog, commandReleaseBox, entity, NULL)
+       ATTRIB(XonoticUserbindEditDialog, nameBox, entity);
+       ATTRIB(XonoticUserbindEditDialog, commandPressBox, entity);
+       ATTRIB(XonoticUserbindEditDialog, commandReleaseBox, entity);
 ENDCLASS(XonoticUserbindEditDialog)
index f3f367e686626a8b8b9f2dd30ff856d5126e41d7..a2a86b7e1fb956adbbb750f090168cbe8df3650d 100644 (file)
@@ -3,8 +3,8 @@
 #include "tab.qh"
 CLASS(XonoticMiscSettingsTab, XonoticTab)
        METHOD(XonoticMiscSettingsTab, fill, void(entity));
-       ATTRIB(XonoticMiscSettingsTab, intendedWidth, float, 0.9)
-       ATTRIB(XonoticMiscSettingsTab, rows, float, 15.5)
-       ATTRIB(XonoticMiscSettingsTab, columns, float, 6.2)
+       ATTRIB(XonoticMiscSettingsTab, intendedWidth, float, 0.9);
+       ATTRIB(XonoticMiscSettingsTab, rows, float, 15.5);
+       ATTRIB(XonoticMiscSettingsTab, columns, float, 6.2);
 ENDCLASS(XonoticMiscSettingsTab)
 entity makeXonoticMiscSettingsTab();
index f5011f77170e5a14a02421b83ab34425df3d7d12..4fddf65867ce4a9f808eac3fba2cdc912835fec0 100644 (file)
@@ -4,9 +4,9 @@
 CLASS(XonoticCvarsDialog, XonoticDialog)
        METHOD(XonoticCvarsDialog, fill, void(entity));
        METHOD(XonoticCvarsDialog, showNotify, void(entity));
-       ATTRIB(XonoticCvarsDialog, title, string, _("Advanced settings"))
-       ATTRIB(XonoticCvarsDialog, color, vector, SKINCOLOR_DIALOG_CVARS)
-       ATTRIB(XonoticCvarsDialog, intendedWidth, float, 0.8)
-       ATTRIB(XonoticCvarsDialog, rows, float, 24)
-       ATTRIB(XonoticCvarsDialog, columns, float, 6)
+       ATTRIB(XonoticCvarsDialog, title, string, _("Advanced settings"));
+       ATTRIB(XonoticCvarsDialog, color, vector, SKINCOLOR_DIALOG_CVARS);
+       ATTRIB(XonoticCvarsDialog, intendedWidth, float, 0.8);
+       ATTRIB(XonoticCvarsDialog, rows, float, 24);
+       ATTRIB(XonoticCvarsDialog, columns, float, 6);
 ENDCLASS(XonoticCvarsDialog)
index 1cbc7773ab9091016ba1a978bf03f9545ce36164..f1d02ff90917365cb050a5d84b8fcb93f502e2bf 100644 (file)
@@ -3,10 +3,10 @@
 #include "dialog.qh"
 CLASS(XonoticResetDialog, XonoticDialog)
        METHOD(XonoticResetDialog, fill, void(entity));
-       ATTRIB(XonoticResetDialog, title, string, _("Factory reset"))
-       ATTRIB(XonoticResetDialog, color, vector, SKINCOLOR_DIALOG_QUIT)
-       ATTRIB(XonoticResetDialog, intendedWidth, float, 0.5)
-       ATTRIB(XonoticResetDialog, rows, float, 4)
-       ATTRIB(XonoticResetDialog, columns, float, 2)
-       ATTRIB(XonoticResetDialog, name, string, "Factory reset")
+       ATTRIB(XonoticResetDialog, title, string, _("Factory reset"));
+       ATTRIB(XonoticResetDialog, color, vector, SKINCOLOR_DIALOG_QUIT);
+       ATTRIB(XonoticResetDialog, intendedWidth, float, 0.5);
+       ATTRIB(XonoticResetDialog, rows, float, 4);
+       ATTRIB(XonoticResetDialog, columns, float, 2);
+       ATTRIB(XonoticResetDialog, name, string, "Factory reset");
 ENDCLASS(XonoticResetDialog)
index 3a5ccc3b652a79a7bc9cac35f5b0b03a40a2382b..22f84d0f0b7c024b5247f17a28c46efa9848bfab 100644 (file)
@@ -3,8 +3,8 @@
 #include "tab.qh"
 CLASS(XonoticUserSettingsTab, XonoticTab)
        METHOD(XonoticUserSettingsTab, fill, void(entity));
-       ATTRIB(XonoticUserSettingsTab, intendedWidth, float, 0.9)
-       ATTRIB(XonoticUserSettingsTab, rows, float, 15.5)
-       ATTRIB(XonoticUserSettingsTab, columns, float, 6)
+       ATTRIB(XonoticUserSettingsTab, intendedWidth, float, 0.9);
+       ATTRIB(XonoticUserSettingsTab, rows, float, 15.5);
+       ATTRIB(XonoticUserSettingsTab, columns, float, 6);
 ENDCLASS(XonoticUserSettingsTab)
 entity makeXonoticUserSettingsTab();
index 6028a441cae0b65c5acbc3e2f08f033f0a3db944..ba5c8a5d1c0bc0f129e006da2a5f06ce5e23aa8f 100644 (file)
@@ -3,9 +3,9 @@
 #include "dialog.qh"
 CLASS(XonoticLanguageWarningDialog, XonoticDialog)
        METHOD(XonoticLanguageWarningDialog, fill, void(entity));
-       ATTRIB(XonoticLanguageWarningDialog, title, string, _("Warning"))
-       ATTRIB(XonoticLanguageWarningDialog, color, vector, SKINCOLOR_DIALOG_HUDCONFIRM)
-       ATTRIB(XonoticLanguageWarningDialog, intendedWidth, float, 0.6)
-       ATTRIB(XonoticLanguageWarningDialog, rows, float, 5)
-       ATTRIB(XonoticLanguageWarningDialog, columns, float, 4)
+       ATTRIB(XonoticLanguageWarningDialog, title, string, _("Warning"));
+       ATTRIB(XonoticLanguageWarningDialog, color, vector, SKINCOLOR_DIALOG_HUDCONFIRM);
+       ATTRIB(XonoticLanguageWarningDialog, intendedWidth, float, 0.6);
+       ATTRIB(XonoticLanguageWarningDialog, rows, float, 5);
+       ATTRIB(XonoticLanguageWarningDialog, columns, float, 4);
 ENDCLASS(XonoticLanguageWarningDialog)
index 0abe322c38da0a3ccf3b47fd0f04345f198a08ee..61d8a368e0e67edd06003e6b6966fb9525f298fa 100644 (file)
@@ -3,9 +3,9 @@
 #include "tab.qh"
 CLASS(XonoticVideoSettingsTab, XonoticTab)
        METHOD(XonoticVideoSettingsTab, fill, void(entity));
-       ATTRIB(XonoticVideoSettingsTab, intendedWidth, float, 0.9)
-       ATTRIB(XonoticVideoSettingsTab, rows, float, 15.5)
-       ATTRIB(XonoticVideoSettingsTab, columns, float, 6.2)  // added extra .2 for center space
-       ATTRIB(XonoticVideoSettingsTab, name, string, "videosettings")
+       ATTRIB(XonoticVideoSettingsTab, intendedWidth, float, 0.9);
+       ATTRIB(XonoticVideoSettingsTab, rows, float, 15.5);
+       ATTRIB(XonoticVideoSettingsTab, columns, float, 6.2);  // added extra .2 for center space
+       ATTRIB(XonoticVideoSettingsTab, name, string, "videosettings");
 ENDCLASS(XonoticVideoSettingsTab)
 entity makeXonoticVideoSettingsTab();
index b3dabaf6ce160ee59c3852bec89c8492b4b04e6f..c7691fbba4e16ba81eb483b8c0f748c9e6d4f2ba 100644 (file)
@@ -3,11 +3,11 @@
 #include "dialog.qh"
 CLASS(XonoticSingleplayerDialog, XonoticDialog)
        METHOD(XonoticSingleplayerDialog, fill, void(entity));
-       ATTRIB(XonoticSingleplayerDialog, title, string, _("Singleplayer"))
-       ATTRIB(XonoticSingleplayerDialog, tooltip, string, _("Play the singleplayer campaign or instant action matches against bots"))
-       ATTRIB(XonoticSingleplayerDialog, color, vector, SKINCOLOR_DIALOG_SINGLEPLAYER)
-       ATTRIB(XonoticSingleplayerDialog, intendedWidth, float, 0.80)
-       ATTRIB(XonoticSingleplayerDialog, rows, float, 24)
-       ATTRIB(XonoticSingleplayerDialog, columns, float, 5)
-       ATTRIB(XonoticSingleplayerDialog, campaignBox, entity, NULL)
+       ATTRIB(XonoticSingleplayerDialog, title, string, _("Singleplayer"));
+       ATTRIB(XonoticSingleplayerDialog, tooltip, string, _("Play the singleplayer campaign or instant action matches against bots"));
+       ATTRIB(XonoticSingleplayerDialog, color, vector, SKINCOLOR_DIALOG_SINGLEPLAYER);
+       ATTRIB(XonoticSingleplayerDialog, intendedWidth, float, 0.80);
+       ATTRIB(XonoticSingleplayerDialog, rows, float, 24);
+       ATTRIB(XonoticSingleplayerDialog, columns, float, 5);
+       ATTRIB(XonoticSingleplayerDialog, campaignBox, entity);
 ENDCLASS(XonoticSingleplayerDialog)
index 1de958b8b7ebe6103ad72e6bd11d3feffb45b7b8..6a6b2d37bf7988956fb66de009dec5b79550a943 100644 (file)
@@ -4,9 +4,9 @@
 CLASS(XonoticWinnerDialog, XonoticDialog)
        METHOD(XonoticWinnerDialog, fill, void(entity));
        METHOD(XonoticWinnerDialog, focusEnter, void(entity));
-       ATTRIB(XonoticWinnerDialog, title, string, _("Winner"))
-       ATTRIB(XonoticWinnerDialog, color, vector, SKINCOLOR_DIALOG_SINGLEPLAYER)
-       ATTRIB(XonoticWinnerDialog, intendedWidth, float, 0.32)
-       ATTRIB(XonoticWinnerDialog, rows, float, 12)
-       ATTRIB(XonoticWinnerDialog, columns, float, 3)
+       ATTRIB(XonoticWinnerDialog, title, string, _("Winner"));
+       ATTRIB(XonoticWinnerDialog, color, vector, SKINCOLOR_DIALOG_SINGLEPLAYER);
+       ATTRIB(XonoticWinnerDialog, intendedWidth, float, 0.32);
+       ATTRIB(XonoticWinnerDialog, rows, float, 12);
+       ATTRIB(XonoticWinnerDialog, columns, float, 3);
 ENDCLASS(XonoticWinnerDialog)
index b4056bb3b1947c936566e6120ece605d562eff4b..0bb0c306e388e35e8f30d5069957e631277db572 100644 (file)
@@ -4,15 +4,15 @@
 CLASS(XonoticTeamSelectDialog, XonoticRootDialog)
        METHOD(XonoticTeamSelectDialog, fill, void(entity));
        METHOD(XonoticTeamSelectDialog, showNotify, void(entity));
-       ATTRIB(XonoticTeamSelectDialog, title, string, _("Team Selection"))
-       ATTRIB(XonoticTeamSelectDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT)
-       ATTRIB(XonoticTeamSelectDialog, intendedWidth, float, 0.4)
-       ATTRIB(XonoticTeamSelectDialog, rows, float, 5)
-       ATTRIB(XonoticTeamSelectDialog, columns, float, 4)
-       ATTRIB(XonoticTeamSelectDialog, name, string, "TeamSelect")
-       ATTRIB(XonoticTeamSelectDialog, team1, entity, NULL)
-       ATTRIB(XonoticTeamSelectDialog, team2, entity, NULL)
-       ATTRIB(XonoticTeamSelectDialog, team3, entity, NULL)
-       ATTRIB(XonoticTeamSelectDialog, team4, entity, NULL)
-       ATTRIB(XonoticTeamSelectDialog, requiresConnection, float, true)
+       ATTRIB(XonoticTeamSelectDialog, title, string, _("Team Selection"));
+       ATTRIB(XonoticTeamSelectDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT);
+       ATTRIB(XonoticTeamSelectDialog, intendedWidth, float, 0.4);
+       ATTRIB(XonoticTeamSelectDialog, rows, float, 5);
+       ATTRIB(XonoticTeamSelectDialog, columns, float, 4);
+       ATTRIB(XonoticTeamSelectDialog, name, string, "TeamSelect");
+       ATTRIB(XonoticTeamSelectDialog, team1, entity);
+       ATTRIB(XonoticTeamSelectDialog, team2, entity);
+       ATTRIB(XonoticTeamSelectDialog, team3, entity);
+       ATTRIB(XonoticTeamSelectDialog, team4, entity);
+       ATTRIB(XonoticTeamSelectDialog, requiresConnection, float, true);
 ENDCLASS(XonoticTeamSelectDialog)
index 4bec3d1f9c0c2a4e434cef390a6724875ba663da..7b5f23b694ba6991ebf52b1512376d227345188e 100644 (file)
@@ -3,11 +3,11 @@
 #include "rootdialog.qh"
 CLASS(XonoticUid2NameDialog, XonoticRootDialog)
        METHOD(XonoticUid2NameDialog, fill, void(entity));
-       ATTRIB(XonoticUid2NameDialog, title, string, string_null)
-       ATTRIB(XonoticUid2NameDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT)
-       ATTRIB(XonoticUid2NameDialog, intendedWidth, float, 0.5)
-       ATTRIB(XonoticUid2NameDialog, rows, float, 4)
-       ATTRIB(XonoticUid2NameDialog, columns, float, 2)
-       ATTRIB(XonoticUid2NameDialog, name, string, "Uid2Name")
-       ATTRIB(XonoticUid2NameDialog, closable, float, 0)
+       ATTRIB(XonoticUid2NameDialog, title, string);
+       ATTRIB(XonoticUid2NameDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT);
+       ATTRIB(XonoticUid2NameDialog, intendedWidth, float, 0.5);
+       ATTRIB(XonoticUid2NameDialog, rows, float, 4);
+       ATTRIB(XonoticUid2NameDialog, columns, float, 2);
+       ATTRIB(XonoticUid2NameDialog, name, string, "Uid2Name");
+       ATTRIB(XonoticUid2NameDialog, closable, float, 0);
 ENDCLASS(XonoticUid2NameDialog)
index 193f8336838acb793ed261da5566bd9cb2bddf8c..254f1c0012563edf052503b74a6a7cc819c75dc9 100644 (file)
@@ -30,8 +30,7 @@ void XonoticGametypeList_setSelected(entity me, float i)
 }
 void XonoticGametypeList_loadCvars(entity me)
 {
-       float t;
-       t = MapInfo_CurrentGametype();
+       Gametype t = MapInfo_CurrentGametype();
        float i;
        for(i = 0; i < GameType_GetCount(); ++i)
                if(t == GameType_GetID(i))
@@ -49,7 +48,7 @@ void XonoticGametypeList_loadCvars(entity me)
 }
 void XonoticGametypeList_saveCvars(entity me)
 {
-       int t = GameType_GetID(me.selectedItem);
+       Gametype t = GameType_GetID(me.selectedItem);
        if (t == MapInfo_CurrentGametype()) {
                return;
        }
index 9e17c5c85523e5008d275f80687688951cf19448..bbc50aba4357baed2496662563891d07a3eb2136 100644 (file)
@@ -3,7 +3,7 @@
 #include "listbox.qh"
 CLASS(XonoticGametypeList, XonoticListBox)
        METHOD(XonoticGametypeList, configureXonoticGametypeList, void(entity));
-       ATTRIB(XonoticGametypeList, rowsPerItem, float, 2)
+       ATTRIB(XonoticGametypeList, rowsPerItem, float, 2);
        METHOD(XonoticGametypeList, draw, void(entity));
        METHOD(XonoticGametypeList, drawListBoxItem, void(entity, int, vector, bool, bool));
        METHOD(XonoticGametypeList, resizeNotify, void(entity, vector, vector, vector, vector));
@@ -14,11 +14,11 @@ CLASS(XonoticGametypeList, XonoticListBox)
        METHOD(XonoticGametypeList, clickListBoxItem, void(entity, float, vector));
        METHOD(XonoticGametypeList, focusedItemChangeNotify, void(entity));
 
-       ATTRIB(XonoticGametypeList, realFontSize, vector, '0 0 0')
-       ATTRIB(XonoticGametypeList, realUpperMargin, float, 0)
-       ATTRIB(XonoticGametypeList, columnIconOrigin, float, 0)
-       ATTRIB(XonoticGametypeList, columnIconSize, float, 0)
-       ATTRIB(XonoticGametypeList, columnNameOrigin, float, 0)
-       ATTRIB(XonoticGametypeList, columnNameSize, float, 0)
+       ATTRIB(XonoticGametypeList, realFontSize, vector, '0 0 0');
+       ATTRIB(XonoticGametypeList, realUpperMargin, float, 0);
+       ATTRIB(XonoticGametypeList, columnIconOrigin, float, 0);
+       ATTRIB(XonoticGametypeList, columnIconSize, float, 0);
+       ATTRIB(XonoticGametypeList, columnNameOrigin, float, 0);
+       ATTRIB(XonoticGametypeList, columnNameSize, float, 0);
 ENDCLASS(XonoticGametypeList)
 entity makeXonoticGametypeList();
index f5808698cce5885254ff02bb1b4f0536b0d83b72..557f2e165c6c4d823c6ca81798eaf49b95e0e01a 100644 (file)
@@ -3,7 +3,7 @@
 #include "listbox.qh"
 CLASS(XonoticHUDSkinList, XonoticListBox)
        METHOD(XonoticHUDSkinList, configureXonoticHUDSkinList, void(entity));
-       ATTRIB(XonoticHUDSkinList, rowsPerItem, float, 1)
+       ATTRIB(XonoticHUDSkinList, rowsPerItem, float, 1);
        METHOD(XonoticHUDSkinList, resizeNotify, void(entity, vector, vector, vector, vector));
        METHOD(XonoticHUDSkinList, draw, void(entity));
        METHOD(XonoticHUDSkinList, drawListBoxItem, void(entity, int, vector, bool, bool));
@@ -18,17 +18,17 @@ CLASS(XonoticHUDSkinList, XonoticListBox)
        METHOD(XonoticHUDSkinList, destroy, void(entity));
        METHOD(XonoticHUDSkinList, showNotify, void(entity));
 
-       ATTRIB(XonoticHUDSkinList, listHUDSkin, float, -1)
-       ATTRIB(XonoticHUDSkinList, realFontSize, vector, '0 0 0')
-       ATTRIB(XonoticHUDSkinList, columnNameOrigin, float, 0)
-       ATTRIB(XonoticHUDSkinList, columnNameSize, float, 0)
-       ATTRIB(XonoticHUDSkinList, realUpperMargin, float, 0)
-       ATTRIB(XonoticHUDSkinList, origin, vector, '0 0 0')
-       ATTRIB(XonoticHUDSkinList, itemAbsSize, vector, '0 0 0')
+       ATTRIB(XonoticHUDSkinList, listHUDSkin, float, -1);
+       ATTRIB(XonoticHUDSkinList, realFontSize, vector, '0 0 0');
+       ATTRIB(XonoticHUDSkinList, columnNameOrigin, float, 0);
+       ATTRIB(XonoticHUDSkinList, columnNameSize, float, 0);
+       ATTRIB(XonoticHUDSkinList, realUpperMargin, float, 0);
+       ATTRIB(XonoticHUDSkinList, origin, vector, '0 0 0');
+       ATTRIB(XonoticHUDSkinList, itemAbsSize, vector, '0 0 0');
 
-       ATTRIB(XonoticHUDSkinList, filterString, string, string_null)
-       ATTRIB(XonoticHUDSkinList, delayedRefreshTime, float, 0)
-       ATTRIB(XonoticHUDSkinList, savedName, string, string_null)
+       ATTRIB(XonoticHUDSkinList, filterString, string);
+       ATTRIB(XonoticHUDSkinList, delayedRefreshTime, float, 0);
+       ATTRIB(XonoticHUDSkinList, savedName, string);
 ENDCLASS(XonoticHUDSkinList)
 entity hudskinlist;
 entity makeXonoticHUDSkinList();
index c09817943b31cbb7748db9a7cf2d0200aee59519..7be855cd9d4667c2f42d05d44561e51e63b14623 100644 (file)
@@ -6,32 +6,32 @@ CLASS(XonoticInputBox, InputBox)
        METHOD(XonoticInputBox, focusLeave, void(entity));
        METHOD(XonoticInputBox, setText, void(entity, string));
        METHOD(XonoticInputBox, keyDown, float(entity, float, float, float));
-       ATTRIB(XonoticInputBox, fontSize, float, SKINFONTSIZE_NORMAL)
-       ATTRIB(XonoticInputBox, image, string, SKINGFX_INPUTBOX)
-       ATTRIB(XonoticInputBox, onChange, void(entity, entity), func_null)
-       ATTRIB(XonoticInputBox, onChangeEntity, entity, NULL)
-       ATTRIB(XonoticInputBox, onEnter, void(entity, entity), func_null)
-       ATTRIB(XonoticInputBox, onEnterEntity, entity, NULL)
-       ATTRIB(XonoticInputBox, marginLeft, float, SKINMARGIN_INPUTBOX_CHARS)
-       ATTRIB(XonoticInputBox, marginRight, float, SKINMARGIN_INPUTBOX_CHARS)
-       ATTRIB(XonoticInputBox, color, vector, SKINCOLOR_INPUTBOX_N)
-       ATTRIB(XonoticInputBox, colorF, vector, SKINCOLOR_INPUTBOX_F)
+       ATTRIB(XonoticInputBox, fontSize, float, SKINFONTSIZE_NORMAL);
+       ATTRIB(XonoticInputBox, image, string, SKINGFX_INPUTBOX);
+       ATTRIB(XonoticInputBox, onChange, void(entity, entity));
+       ATTRIB(XonoticInputBox, onChangeEntity, entity);
+       ATTRIB(XonoticInputBox, onEnter, void(entity, entity));
+       ATTRIB(XonoticInputBox, onEnterEntity, entity);
+       ATTRIB(XonoticInputBox, marginLeft, float, SKINMARGIN_INPUTBOX_CHARS);
+       ATTRIB(XonoticInputBox, marginRight, float, SKINMARGIN_INPUTBOX_CHARS);
+       ATTRIB(XonoticInputBox, color, vector, SKINCOLOR_INPUTBOX_N);
+       ATTRIB(XonoticInputBox, colorF, vector, SKINCOLOR_INPUTBOX_F);
 
-       ATTRIB(XonoticInputBox, alpha, float, SKINALPHA_TEXT)
+       ATTRIB(XonoticInputBox, alpha, float, SKINALPHA_TEXT);
 
        // Clear button attributes
-       ATTRIB(XonoticInputBox, cb_offset, float, SKINOFFSET_CLEARBUTTON)  // bound to range -1, 0
-       ATTRIB(XonoticInputBox, cb_src, string, SKINGFX_CLEARBUTTON)
-       ATTRIB(XonoticInputBox, cb_color, vector, SKINCOLOR_CLEARBUTTON_N)
-       ATTRIB(XonoticInputBox, cb_colorF, vector, SKINCOLOR_CLEARBUTTON_F)
-       ATTRIB(XonoticInputBox, cb_colorC, vector, SKINCOLOR_CLEARBUTTON_C)
+       ATTRIB(XonoticInputBox, cb_offset, float, SKINOFFSET_CLEARBUTTON);  // bound to range -1, 0
+       ATTRIB(XonoticInputBox, cb_src, string, SKINGFX_CLEARBUTTON);
+       ATTRIB(XonoticInputBox, cb_color, vector, SKINCOLOR_CLEARBUTTON_N);
+       ATTRIB(XonoticInputBox, cb_colorF, vector, SKINCOLOR_CLEARBUTTON_F);
+       ATTRIB(XonoticInputBox, cb_colorC, vector, SKINCOLOR_CLEARBUTTON_C);
 
-       ATTRIB(XonoticInputBox, cvarName, string, string_null)
+       ATTRIB(XonoticInputBox, cvarName, string);
        METHOD(XonoticInputBox, loadCvars, void(entity));
        METHOD(XonoticInputBox, saveCvars, void(entity));
-       ATTRIB(XonoticInputBox, sendCvars, float, 0)
+       ATTRIB(XonoticInputBox, sendCvars, float, 0);
 
-       ATTRIB(XonoticInputBox, saveImmediately, float, 0)
+       ATTRIB(XonoticInputBox, saveImmediately, float, 0);
 ENDCLASS(XonoticInputBox)
 entity makeXonoticInputBox_T(float, string, string theTooltip);
 entity makeXonoticInputBox(float, string);
index ca2db83573d02a468f7077cb5474f331979fc00d..27e488164be5065733501571283131907c86a012 100644 (file)
@@ -41,10 +41,10 @@ void Xonotic_KeyBinds_Read()
        KEYBIND_DEF("+fire2"                                , _("secondary fire"));
        KEYBIND_DEF(""                                      , "");
        KEYBIND_DEF(""                                      , _("Weapon switching"));
-       KEYBIND_DEF("weapprev"                              , _("previous"));
-       KEYBIND_DEF("weapnext"                              , _("next"));
-       KEYBIND_DEF("weaplast"                              , _("previously used"));
-       KEYBIND_DEF("weapbest"                              , _("best"));
+       KEYBIND_DEF("weapprev"                              , CTX(_("WEAPON^previous")));
+       KEYBIND_DEF("weapnext"                              , CTX(_("WEAPON^next")));
+       KEYBIND_DEF("weaplast"                              , CTX(_("WEAPON^previously used")));
+       KEYBIND_DEF("weapbest"                              , CTX(_("WEAPON^best")));
        KEYBIND_DEF("reload"                                , _("reload"));
 
        int i;
index 4d0482dd9dfcbf9e1e0770ebd393a31327853185..764059f768df6d8feffedd929d164fa4d182a9e0 100644 (file)
@@ -3,7 +3,7 @@
 #include "listbox.qh"
 CLASS(XonoticKeyBinder, XonoticListBox)
        METHOD(XonoticKeyBinder, configureXonoticKeyBinder, void(entity));
-       ATTRIB(XonoticKeyBinder, rowsPerItem, int, 1)
+       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));
@@ -13,20 +13,20 @@ CLASS(XonoticKeyBinder, XonoticListBox)
        METHOD(XonoticKeyBinder, keyGrabbed, void(entity, float, float));
        METHOD(XonoticKeyBinder, destroy, void(entity));
 
-       ATTRIB(XonoticKeyBinder, realFontSize, vector, '0 0 0')
-       ATTRIB(XonoticKeyBinder, realUpperMargin, float, 0)
-       ATTRIB(XonoticKeyBinder, columnFunctionOrigin, float, 0)
-       ATTRIB(XonoticKeyBinder, columnFunctionSize, float, 0)
-       ATTRIB(XonoticKeyBinder, columnKeysOrigin, float, 0)
-       ATTRIB(XonoticKeyBinder, columnKeysSize, float, 0)
+       ATTRIB(XonoticKeyBinder, realFontSize, vector, '0 0 0');
+       ATTRIB(XonoticKeyBinder, realUpperMargin, float, 0);
+       ATTRIB(XonoticKeyBinder, columnFunctionOrigin, float, 0);
+       ATTRIB(XonoticKeyBinder, columnFunctionSize, float, 0);
+       ATTRIB(XonoticKeyBinder, columnKeysOrigin, float, 0);
+       ATTRIB(XonoticKeyBinder, columnKeysSize, float, 0);
 
        METHOD(XonoticKeyBinder, loadKeyBinds, void(entity));
-       ATTRIB(XonoticKeyBinder, previouslySelected, int, -1)
-       ATTRIB(XonoticKeyBinder, inMouseHandler, float, 0)
-       ATTRIB(XonoticKeyBinder, userbindEditButton, entity, NULL)
-       ATTRIB(XonoticKeyBinder, keyGrabButton, entity, NULL)
-       ATTRIB(XonoticKeyBinder, clearButton, entity, NULL)
-       ATTRIB(XonoticKeyBinder, userbindEditDialog, entity, NULL)
+       ATTRIB(XonoticKeyBinder, previouslySelected, int, -1);
+       ATTRIB(XonoticKeyBinder, inMouseHandler, float, 0);
+       ATTRIB(XonoticKeyBinder, userbindEditButton, entity);
+       ATTRIB(XonoticKeyBinder, keyGrabButton, entity);
+       ATTRIB(XonoticKeyBinder, clearButton, entity);
+       ATTRIB(XonoticKeyBinder, userbindEditDialog, entity);
        METHOD(XonoticKeyBinder, editUserbind, void(entity, string, string, string));
 ENDCLASS(XonoticKeyBinder)
 entity makeXonoticKeyBinder();
index 8febd646781e4a1e8e94414c1048d88e7de721b9..daf249e450069f22f6a184c27bab04781dab4f9c 100644 (file)
@@ -3,31 +3,31 @@
 #include "listbox.qh"
 CLASS(XonoticLanguageList, XonoticListBox)
        METHOD(XonoticLanguageList, configureXonoticLanguageList, void(entity));
-       ATTRIB(XonoticLanguageList, rowsPerItem, float, 1)
+       ATTRIB(XonoticLanguageList, rowsPerItem, float, 1);
        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));
        METHOD(XonoticLanguageList, saveCvars, void(entity));
 
-       ATTRIB(XonoticLanguageList, realFontSize, vector, '0 0 0')
-       ATTRIB(XonoticLanguageList, realUpperMargin, float, 0)
-       ATTRIB(XonoticLanguageList, columnNameOrigin, float, 0)
-       ATTRIB(XonoticLanguageList, columnNameSize, float, 0)
-       ATTRIB(XonoticLanguageList, columnPercentageOrigin, float, 0)
-       ATTRIB(XonoticLanguageList, columnPercentageSize, float, 0)
+       ATTRIB(XonoticLanguageList, realFontSize, vector, '0 0 0');
+       ATTRIB(XonoticLanguageList, realUpperMargin, float, 0);
+       ATTRIB(XonoticLanguageList, columnNameOrigin, float, 0);
+       ATTRIB(XonoticLanguageList, columnNameSize, float, 0);
+       ATTRIB(XonoticLanguageList, columnPercentageOrigin, float, 0);
+       ATTRIB(XonoticLanguageList, columnPercentageSize, float, 0);
 
        METHOD(XonoticLanguageList, doubleClickListBoxItem, void(entity, float, vector));
        METHOD(XonoticLanguageList, keyDown, float(entity, float, float, float));  // enter handling
 
        METHOD(XonoticLanguageList, destroy, void(entity));
 
-       ATTRIB(XonoticLanguageList, languagelist, float, -1)
+       ATTRIB(XonoticLanguageList, languagelist, float, -1);
        METHOD(XonoticLanguageList, getLanguages, void(entity));
        METHOD(XonoticLanguageList, setLanguage, void(entity));
        METHOD(XonoticLanguageList, languageParameter, string(entity, float, float));
 
-       ATTRIB(XonoticLanguageList, name, string, "languageselector")  // change this to make it noninteractive (for first run dialog)
+       ATTRIB(XonoticLanguageList, name, string, "languageselector");  // change this to make it noninteractive (for first run dialog);
 ENDCLASS(XonoticLanguageList)
 
 entity makeXonoticLanguageList();
index 3e789e772dd1b2372bee4fad53f0ccf7fa332758..14272cb19ba9f8e6db66f2a309daf000430adc10 100644 (file)
@@ -3,17 +3,17 @@
 #include "../item/listbox.qh"
 CLASS(XonoticListBox, ListBox)
        METHOD(XonoticListBox, configureXonoticListBox, void(entity));
-       ATTRIB(XonoticListBox, fontSize, float, SKINFONTSIZE_NORMAL)
-       ATTRIB(XonoticListBox, scrollbarWidth, float, SKINWIDTH_SCROLLBAR)
-       ATTRIB(XonoticListBox, src, string, SKINGFX_SCROLLBAR)
-       ATTRIB(XonoticListBox, tolerance, vector, SKINTOLERANCE_SLIDER)
-       ATTRIB(XonoticListBox, rowsPerItem, float, 1)
+       ATTRIB(XonoticListBox, fontSize, float, SKINFONTSIZE_NORMAL);
+       ATTRIB(XonoticListBox, scrollbarWidth, float, SKINWIDTH_SCROLLBAR);
+       ATTRIB(XonoticListBox, src, string, SKINGFX_SCROLLBAR);
+       ATTRIB(XonoticListBox, tolerance, vector, SKINTOLERANCE_SLIDER);
+       ATTRIB(XonoticListBox, rowsPerItem, float, 1);
        METHOD(XonoticListBox, resizeNotify, void(entity, vector, vector, vector, vector));
-       ATTRIB(XonoticListBox, color, vector, SKINCOLOR_SCROLLBAR_N)
-       ATTRIB(XonoticListBox, colorF, vector, SKINCOLOR_SCROLLBAR_F)
-       ATTRIB(XonoticListBox, color2, vector, SKINCOLOR_SCROLLBAR_S)
-       ATTRIB(XonoticListBox, colorC, vector, SKINCOLOR_SCROLLBAR_C)
-       ATTRIB(XonoticListBox, colorBG, vector, SKINCOLOR_LISTBOX_BACKGROUND)
-       ATTRIB(XonoticListBox, alphaBG, float, SKINALPHA_LISTBOX_BACKGROUND)
+       ATTRIB(XonoticListBox, color, vector, SKINCOLOR_SCROLLBAR_N);
+       ATTRIB(XonoticListBox, colorF, vector, SKINCOLOR_SCROLLBAR_F);
+       ATTRIB(XonoticListBox, color2, vector, SKINCOLOR_SCROLLBAR_S);
+       ATTRIB(XonoticListBox, colorC, vector, SKINCOLOR_SCROLLBAR_C);
+       ATTRIB(XonoticListBox, colorBG, vector, SKINCOLOR_LISTBOX_BACKGROUND);
+       ATTRIB(XonoticListBox, alphaBG, float, SKINALPHA_LISTBOX_BACKGROUND);
 ENDCLASS(XonoticListBox)
 entity makeXonoticListBox();
index daf5e0571cf4616af7fd4c9c3d1e476686612d8b..2397d41431605a6d59b36df2b996ded9d56bed65 100644 (file)
@@ -5,22 +5,22 @@
 CLASS(MainWindow, ModalController)
        METHOD(MainWindow, configureMainWindow, void(entity));
        METHOD(MainWindow, draw, void(entity));
-       ATTRIB(MainWindow, firstRunDialog, entity, NULL)
-       ATTRIB(MainWindow, advancedDialog, entity, NULL)
-       ATTRIB(MainWindow, mutatorsDialog, entity, NULL)
-       ATTRIB(MainWindow, mapInfoDialog, entity, NULL)
-       ATTRIB(MainWindow, userbindEditDialog, entity, NULL)
-       ATTRIB(MainWindow, winnerDialog, entity, NULL)
-       ATTRIB(MainWindow, serverInfoDialog, entity, NULL)
-       ATTRIB(MainWindow, cvarsDialog, entity, NULL)
-       ATTRIB(MainWindow, screenshotViewerDialog, entity, NULL)
-       ATTRIB(MainWindow, viewDialog, entity, NULL)
-       ATTRIB(MainWindow, hudconfirmDialog, entity, NULL)
-       ATTRIB(MainWindow, languageWarningDialog, entity, NULL)
-       ATTRIB(MainWindow, mainNexposee, entity, NULL)
-       ATTRIB(MainWindow, fadedAlpha, float, SKINALPHA_BEHIND)
-       ATTRIB(MainWindow, dialogToShow, entity, NULL)
-       ATTRIB(MainWindow, demostartconfirmDialog, entity, NULL)
-       ATTRIB(MainWindow, demotimeconfirmDialog, entity, NULL)
-       ATTRIB(MainWindow, resetDialog, entity, NULL)
+       ATTRIB(MainWindow, firstRunDialog, entity);
+       ATTRIB(MainWindow, advancedDialog, entity);
+       ATTRIB(MainWindow, mutatorsDialog, entity);
+       ATTRIB(MainWindow, mapInfoDialog, entity);
+       ATTRIB(MainWindow, userbindEditDialog, entity);
+       ATTRIB(MainWindow, winnerDialog, entity);
+       ATTRIB(MainWindow, serverInfoDialog, entity);
+       ATTRIB(MainWindow, cvarsDialog, entity);
+       ATTRIB(MainWindow, screenshotViewerDialog, entity);
+       ATTRIB(MainWindow, viewDialog, entity);
+       ATTRIB(MainWindow, hudconfirmDialog, entity);
+       ATTRIB(MainWindow, languageWarningDialog, entity);
+       ATTRIB(MainWindow, mainNexposee, entity);
+       ATTRIB(MainWindow, fadedAlpha, float, SKINALPHA_BEHIND);
+       ATTRIB(MainWindow, dialogToShow, entity);
+       ATTRIB(MainWindow, demostartconfirmDialog, entity);
+       ATTRIB(MainWindow, demotimeconfirmDialog, entity);
+       ATTRIB(MainWindow, resetDialog, entity);
 ENDCLASS(MainWindow)
index 4b41f5bd3be6eb514600614e290c834df62f3a49..8feee96ed7a05a7ac74ef8a97a8eae709a503c2e 100644 (file)
@@ -172,9 +172,8 @@ void XonoticMapList_refilter(entity me)
 {
        float i, j, n;
        string s;
-       float gt, f;
-       gt = MapInfo_CurrentGametype();
-       f = MapInfo_CurrentFeatures();
+       Gametype gt = MapInfo_CurrentGametype();
+       int f = MapInfo_CurrentFeatures();
        MapInfo_FilterGametype(gt, f, MapInfo_RequiredFlags(), MapInfo_ForbiddenFlags(), 0);
        if (me.stringFilter)
                MapInfo_FilterString(me.stringFilter);
@@ -256,7 +255,7 @@ void MapList_Add_All(entity btn, entity me)
 {
        float i;
        string s;
-       MapInfo_FilterGametype(MAPINFO_TYPE_ALL, 0, 0, MapInfo_ForbiddenFlags(), 0); // all
+       _MapInfo_FilterGametype(MAPINFO_TYPE_ALL, 0, 0, MapInfo_ForbiddenFlags(), 0); // all
        s = "";
        for(i = 0; i < MapInfo_count; ++i)
                s = strcat(s, " ", MapInfo_BSPName_ByID(i));
index de9d7e28a314d5fb13072cf7dd8b2aa48a95fdbe..ae6f6185e54e79dd2aa30c708f1054c8adecb813 100644 (file)
@@ -3,7 +3,7 @@
 #include "listbox.qh"
 CLASS(XonoticMapList, XonoticListBox)
        METHOD(XonoticMapList, configureXonoticMapList, void(entity));
-       ATTRIB(XonoticMapList, rowsPerItem, float, 4)
+       ATTRIB(XonoticMapList, rowsPerItem, float, 4);
        METHOD(XonoticMapList, draw, void(entity));
        METHOD(XonoticMapList, drawListBoxItem, void(entity, int, vector, bool, bool));
        METHOD(XonoticMapList, clickListBoxItem, void(entity, float, vector));
@@ -13,39 +13,39 @@ CLASS(XonoticMapList, XonoticListBox)
        METHOD(XonoticMapList, refilterCallback, void(entity, entity));
        METHOD(XonoticMapList, keyDown, float(entity, float, float, float));
 
-       ATTRIB(XonoticMapList, realFontSize, vector, '0 0 0')
-       ATTRIB(XonoticMapList, columnPreviewOrigin, float, 0)
-       ATTRIB(XonoticMapList, columnPreviewSize, float, 0)
-       ATTRIB(XonoticMapList, columnNameOrigin, float, 0)
-       ATTRIB(XonoticMapList, columnNameSize, float, 0)
-       ATTRIB(XonoticMapList, checkMarkOrigin, vector, '0 0 0')
-       ATTRIB(XonoticMapList, checkMarkSize, vector, '0 0 0')
-       ATTRIB(XonoticMapList, realUpperMargin1, float, 0)
-       ATTRIB(XonoticMapList, realUpperMargin2, float, 0)
+       ATTRIB(XonoticMapList, realFontSize, vector, '0 0 0');
+       ATTRIB(XonoticMapList, columnPreviewOrigin, float, 0);
+       ATTRIB(XonoticMapList, columnPreviewSize, float, 0);
+       ATTRIB(XonoticMapList, columnNameOrigin, float, 0);
+       ATTRIB(XonoticMapList, columnNameSize, float, 0);
+       ATTRIB(XonoticMapList, checkMarkOrigin, vector, '0 0 0');
+       ATTRIB(XonoticMapList, checkMarkSize, vector, '0 0 0');
+       ATTRIB(XonoticMapList, realUpperMargin1, float, 0);
+       ATTRIB(XonoticMapList, realUpperMargin2, float, 0);
 
-       ATTRIB(XonoticMapList, lastGametype, float, 0)
-       ATTRIB(XonoticMapList, lastFeatures, float, 0)
+       ATTRIB(XonoticMapList, lastGametype, entity);
+       ATTRIB(XonoticMapList, lastFeatures, float, 0);
 
-       ATTRIB(XonoticMapList, origin, vector, '0 0 0')
-       ATTRIB(XonoticMapList, itemAbsSize, vector, '0 0 0')
+       ATTRIB(XonoticMapList, origin, vector, '0 0 0');
+       ATTRIB(XonoticMapList, itemAbsSize, vector, '0 0 0');
 
-       ATTRIB(XonoticMapList, g_maplistCache, string, string_null)
+       ATTRIB(XonoticMapList, g_maplistCache, string);
        METHOD(XonoticMapList, g_maplistCacheToggle, void(entity, float));
        METHOD(XonoticMapList, g_maplistCacheQuery, float(entity, float));
 
-       ATTRIB(XonoticMapList, stringFilter, string, string_null)
-       ATTRIB(XonoticMapList, stringFilterBox, entity, NULL)
+       ATTRIB(XonoticMapList, stringFilter, string);
+       ATTRIB(XonoticMapList, stringFilterBox, entity);
 
-       ATTRIB(XonoticMapList, startButton, entity, NULL)
+       ATTRIB(XonoticMapList, startButton, entity);
 
        METHOD(XonoticMapList, loadCvars, void(entity));
 
-       ATTRIB(XonoticMapList, typeToSearchString, string, string_null)
-       ATTRIB(XonoticMapList, typeToSearchTime, float, 0)
+       ATTRIB(XonoticMapList, typeToSearchString, string);
+       ATTRIB(XonoticMapList, typeToSearchTime, float, 0);
 
        METHOD(XonoticMapList, destroy, void(entity));
 
-       ATTRIB(XonoticMapList, alphaBG, float, 0)
+       ATTRIB(XonoticMapList, alphaBG, float, 0);
 ENDCLASS(XonoticMapList)
 entity makeXonoticMapList();
 void MapList_StringFilterBox_Change(entity box, entity me);
index c530c7ca9cda274a197448aab1085ad1187d3e50..b8e19cf19ebaedf19a3fcb0f440f877ae3006012 100644 (file)
@@ -9,23 +9,23 @@ CLASS(XonoticPicker, Item)
        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, 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)
+       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')
+       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();
index 8474b9140d8f1d86f9b579f5fc44fce2dc73d68e..a35ed966d9360d22dcf9b62505cccd97450ddc53 100644 (file)
@@ -2,21 +2,21 @@
 
 #include "listbox.qh"
 CLASS(XonoticPlayerList, XonoticListBox)
-       ATTRIB(XonoticPlayerList, rowsPerItem, float, 1)
+       ATTRIB(XonoticPlayerList, rowsPerItem, float, 1);
        METHOD(XonoticPlayerList, resizeNotify, void(entity, vector, vector, vector, vector));
        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)
-       ATTRIB(XonoticPlayerList, columnNameSize, float, 0)
-       ATTRIB(XonoticPlayerList, columnScoreOrigin, float, 0)
-       ATTRIB(XonoticPlayerList, columnScoreSize, float, 0)
-       ATTRIB(XonoticPlayerList, realUpperMargin, float, 0)
-       ATTRIB(XonoticPlayerList, origin, vector, '0 0 0')
-       ATTRIB(XonoticPlayerList, itemAbsSize, vector, '0 0 0')
+       ATTRIB(XonoticPlayerList, allowFocusSound, float, 0);
+       ATTRIB(XonoticPlayerList, realFontSize, vector, '0 0 0');
+       ATTRIB(XonoticPlayerList, columnNameOrigin, float, 0);
+       ATTRIB(XonoticPlayerList, columnNameSize, float, 0);
+       ATTRIB(XonoticPlayerList, columnScoreOrigin, float, 0);
+       ATTRIB(XonoticPlayerList, columnScoreSize, float, 0);
+       ATTRIB(XonoticPlayerList, realUpperMargin, float, 0);
+       ATTRIB(XonoticPlayerList, origin, vector, '0 0 0');
+       ATTRIB(XonoticPlayerList, itemAbsSize, vector, '0 0 0');
        METHOD(XonoticPlayerList, setPlayerList, void(entity, string));
        METHOD(XonoticPlayerList, getPlayerList, string(entity, float, float));
-       ATTRIB(XonoticPlayerList, playerList, float, -1)
-       ATTRIB(XonoticPlayerList, selectionDoesntMatter, bool, true)
+       ATTRIB(XonoticPlayerList, playerList, float, -1);
+       ATTRIB(XonoticPlayerList, selectionDoesntMatter, bool, true);
 ENDCLASS(XonoticPlayerList)
 entity makeXonoticPlayerList();
index 664f22c7c0e2c9d3970e94c9f7403ddfdab49ca0..4635c6ccdb65b438edffe6d28d71b2a492765445 100644 (file)
@@ -9,21 +9,21 @@ CLASS(XonoticPlayerModelSelector, XonoticImage)
        METHOD(XonoticPlayerModelSelector, draw, void(entity));
        METHOD(XonoticPlayerModelSelector, resizeNotify, void(entity, vector, vector, vector, vector));
        METHOD(XonoticPlayerModelSelector, showNotify, void(entity));
-       ATTRIB(XonoticPlayerModelSelector, currentModel, string, string_null)
-       ATTRIB(XonoticPlayerModelSelector, currentSkin, float, 0)
-       ATTRIB(XonoticPlayerModelSelector, currentModelImage, string, string_null)
-       ATTRIB(XonoticPlayerModelSelector, currentModelTitle, string, string_null)
-       ATTRIB(XonoticPlayerModelSelector, currentModelDescription, string, string_null)
+       ATTRIB(XonoticPlayerModelSelector, currentModel, string);
+       ATTRIB(XonoticPlayerModelSelector, currentSkin, float, 0);
+       ATTRIB(XonoticPlayerModelSelector, currentModelImage, string);
+       ATTRIB(XonoticPlayerModelSelector, currentModelTitle, string);
+       ATTRIB(XonoticPlayerModelSelector, currentModelDescription, string);
        METHOD(XonoticPlayerModelSelector, go, void(entity, float));
        METHOD(XonoticPlayerModelSelector, destroy, void(entity));
-       ATTRIB(XonoticPlayerModelSelector, origin, vector, '0 0 0')
-       ATTRIB(XonoticPlayerModelSelector, size, vector, '0 0 0')
-       ATTRIB(XonoticPlayerModelSelector, realFontSize, vector, '0 0 0')
-       ATTRIB(XonoticPlayerModelSelector, fontSize, float, SKINFONTSIZE_NORMAL)
-       ATTRIB(XonoticPlayerModelSelector, titleFontSize, float, SKINFONTSIZE_TITLE)
-       ATTRIB(XonoticPlayerModelSelector, bufModels, float, -1)
-       ATTRIB(XonoticPlayerModelSelector, numModels, float, -1)
-       ATTRIB(XonoticPlayerModelSelector, idxModels, float, -1)
+       ATTRIB(XonoticPlayerModelSelector, origin, vector, '0 0 0');
+       ATTRIB(XonoticPlayerModelSelector, size, vector, '0 0 0');
+       ATTRIB(XonoticPlayerModelSelector, realFontSize, vector, '0 0 0');
+       ATTRIB(XonoticPlayerModelSelector, fontSize, float, SKINFONTSIZE_NORMAL);
+       ATTRIB(XonoticPlayerModelSelector, titleFontSize, float, SKINFONTSIZE_TITLE);
+       ATTRIB(XonoticPlayerModelSelector, bufModels, float, -1);
+       ATTRIB(XonoticPlayerModelSelector, numModels, float, -1);
+       ATTRIB(XonoticPlayerModelSelector, idxModels, float, -1);
 ENDCLASS(XonoticPlayerModelSelector)
 entity makeXonoticPlayerModelSelector();
 void PlayerModelSelector_Next_Click(entity btn, entity me);
index 6bee05bbc88f3961ba6bce22bbe50613b4177d09..bd9f71988fdc59e12dcf51cf43231a158795bff4 100644 (file)
@@ -3,7 +3,7 @@
 #include "listbox.qh"
 CLASS(XonoticPlayList, XonoticListBox)
        METHOD(XonoticPlayList, configureXonoticPlayList, void(entity));
-       ATTRIB(XonoticPlayList, rowsPerItem, float, 1)
+       ATTRIB(XonoticPlayList, rowsPerItem, float, 1);
        METHOD(XonoticPlayList, resizeNotify, void(entity, vector, vector, vector, vector));
        METHOD(XonoticPlayList, draw, void(entity));
        METHOD(XonoticPlayList, drawListBoxItem, void(entity, int, vector, bool, bool));
@@ -17,16 +17,16 @@ CLASS(XonoticPlayList, XonoticListBox)
 
        METHOD(XonoticPlayList, addToPlayList, void(entity, string));
        METHOD(XonoticPlayList, removeSelectedFromPlayList, void(entity));
-       ATTRIB(XonoticPlayList, playingTrack, float, -1)
+       ATTRIB(XonoticPlayList, playingTrack, float, -1);
 
-       ATTRIB(XonoticPlayList, realFontSize, vector, '0 0 0')
-       ATTRIB(XonoticPlayList, columnNameOrigin, float, 0)
-       ATTRIB(XonoticPlayList, columnNameSize, float, 0)
-       ATTRIB(XonoticPlayList, columnNumberOrigin, float, 0)
-       ATTRIB(XonoticPlayList, columnNumberSize, float, 0)
-       ATTRIB(XonoticPlayList, realUpperMargin, float, 0)
-       ATTRIB(XonoticPlayList, origin, vector, '0 0 0')
-       ATTRIB(XonoticPlayList, itemAbsSize, vector, '0 0 0')
+       ATTRIB(XonoticPlayList, realFontSize, vector, '0 0 0');
+       ATTRIB(XonoticPlayList, columnNameOrigin, float, 0);
+       ATTRIB(XonoticPlayList, columnNameSize, float, 0);
+       ATTRIB(XonoticPlayList, columnNumberOrigin, float, 0);
+       ATTRIB(XonoticPlayList, columnNumberSize, float, 0);
+       ATTRIB(XonoticPlayList, realUpperMargin, float, 0);
+       ATTRIB(XonoticPlayList, origin, vector, '0 0 0');
+       ATTRIB(XonoticPlayList, itemAbsSize, vector, '0 0 0');
 ENDCLASS(XonoticPlayList)
 
 entity makeXonoticPlayList();
index 36c228fcf41ae8202e86d20d953443ca90a729ce..cd671a338f296f73ee8a8eb124f03aa1dd50872c 100644 (file)
@@ -5,22 +5,22 @@ CLASS(XonoticRadioButton, RadioButton)
        METHOD(XonoticRadioButton, configureXonoticRadioButton, void(entity, float, string, string, string, string));
        METHOD(XonoticRadioButton, draw, void(entity));
        METHOD(XonoticRadioButton, setChecked, void(entity, float));
-       ATTRIB(XonoticRadioButton, fontSize, float, SKINFONTSIZE_NORMAL)
-       ATTRIB(XonoticRadioButton, image, string, SKINGFX_RADIOBUTTON)
-       ATTRIB(XonoticRadioButton, color, vector, SKINCOLOR_RADIOBUTTON_N)
-       ATTRIB(XonoticRadioButton, colorC, vector, SKINCOLOR_RADIOBUTTON_C)
-       ATTRIB(XonoticRadioButton, colorF, vector, SKINCOLOR_RADIOBUTTON_F)
-       ATTRIB(XonoticRadioButton, colorD, vector, SKINCOLOR_RADIOBUTTON_D)
+       ATTRIB(XonoticRadioButton, fontSize, float, SKINFONTSIZE_NORMAL);
+       ATTRIB(XonoticRadioButton, image, string, SKINGFX_RADIOBUTTON);
+       ATTRIB(XonoticRadioButton, color, vector, SKINCOLOR_RADIOBUTTON_N);
+       ATTRIB(XonoticRadioButton, colorC, vector, SKINCOLOR_RADIOBUTTON_C);
+       ATTRIB(XonoticRadioButton, colorF, vector, SKINCOLOR_RADIOBUTTON_F);
+       ATTRIB(XonoticRadioButton, colorD, vector, SKINCOLOR_RADIOBUTTON_D);
 
-       ATTRIB(XonoticRadioButton, cvarName, string, string_null)
-       ATTRIB(XonoticRadioButton, cvarValue, string, string_null)
-       ATTRIB(XonoticRadioButton, cvarOffValue, string, string_null)
-       ATTRIB(XonoticRadioButton, cvarValueIsAnotherCvar, float, 0)
+       ATTRIB(XonoticRadioButton, cvarName, string);
+       ATTRIB(XonoticRadioButton, cvarValue, string);
+       ATTRIB(XonoticRadioButton, cvarOffValue, string);
+       ATTRIB(XonoticRadioButton, cvarValueIsAnotherCvar, float, 0);
        METHOD(XonoticRadioButton, loadCvars, void(entity));
        METHOD(XonoticRadioButton, saveCvars, void(entity));
 
-       ATTRIB(XonoticRadioButton, alpha, float, SKINALPHA_TEXT)
-       ATTRIB(XonoticRadioButton, disabledAlpha, float, SKINALPHA_DISABLED)
+       ATTRIB(XonoticRadioButton, alpha, float, SKINALPHA_TEXT);
+       ATTRIB(XonoticRadioButton, disabledAlpha, float, SKINALPHA_DISABLED);
 ENDCLASS(XonoticRadioButton)
 entity makeXonoticRadioButton_T(float, string, string, string, string theTooltip);
 entity makeXonoticRadioButton(float, string, string, string);
index 0bfd3364cbd801c62c8e8fa3617d8dc4fdf54e35..a2efa672e9174c9f733113b7765e937237380f0b 100644 (file)
@@ -4,12 +4,12 @@
 CLASS(XonoticRootDialog, XonoticDialog)
        // still to be customized by user
        /*
-       ATTRIB(XonoticDialog, closable, float, 1)
-       ATTRIB(XonoticDialog, title, string, _("Form1")) // ;)
-       ATTRIB(XonoticDialog, color, vector, '1 0.5 1')
-       ATTRIB(XonoticDialog, intendedWidth, float, 0)
-       ATTRIB(XonoticDialog, rows, float, 3)
-       ATTRIB(XonoticDialog, columns, float, 2)
+       ATTRIB(XonoticDialog, closable, float, 1);
+       ATTRIB(XonoticDialog, title, string, _("Form1")); // ;);
+       ATTRIB(XonoticDialog, color, vector, '1 0.5 1');
+       ATTRIB(XonoticDialog, intendedWidth, float, 0);
+       ATTRIB(XonoticDialog, rows, float, 3);
+       ATTRIB(XonoticDialog, columns, float, 2);
        */
        METHOD(XonoticRootDialog, close, void(entity));
 ENDCLASS(XonoticRootDialog)
index eb20c73a243a2d2691c8fee4bd5317a68e458188..8920bed287f50fceed2527f56646d36a8599f812 100644 (file)
@@ -5,15 +5,15 @@ CLASS(XonoticScreenshotImage, XonoticImage)
        METHOD(XonoticScreenshotImage, configureXonoticScreenshotImage, void(entity));
        METHOD(XonoticScreenshotImage, load, void(entity, string));
        METHOD(XonoticScreenshotImage, draw, void(entity));
-       ATTRIB(XonoticScreenshotImage, focusable, float, 1)  // mousePress and mouseDrag work only if focusable is set
+       ATTRIB(XonoticScreenshotImage, focusable, float, 1);  // mousePress and mouseDrag work only if focusable is set
        METHOD(XonoticScreenshotImage, mousePress, float(entity, vector));
        METHOD(XonoticScreenshotImage, mouseDrag, float(entity, vector));
        METHOD(XonoticScreenshotImage, mouseMove, float(entity, vector));
        METHOD(XonoticScreenshotImage, resizeNotify, void(entity, vector, vector, vector, vector));
-       ATTRIB(XonoticScreenshotImage, realFontSize, vector, '0 0 0')
-       ATTRIB(XonoticScreenshotImage, fontSize, float, SKINFONTSIZE_NORMAL)
-       ATTRIB(XonoticScreenshotImage, showTitle, float, 1)
-       ATTRIB(XonoticScreenshotImage, screenshotTime, float, 0)
-       ATTRIB(XonoticScreenshotImage, screenshotTitle, string, string_null)
+       ATTRIB(XonoticScreenshotImage, realFontSize, vector, '0 0 0');
+       ATTRIB(XonoticScreenshotImage, fontSize, float, SKINFONTSIZE_NORMAL);
+       ATTRIB(XonoticScreenshotImage, showTitle, float, 1);
+       ATTRIB(XonoticScreenshotImage, screenshotTime, float, 0);
+       ATTRIB(XonoticScreenshotImage, screenshotTitle, string);
 ENDCLASS(XonoticScreenshotImage)
 entity makeXonoticScreenshotImage();
index 1279c4ad9cf6de503d576127d700a5517c84637e..63071fc74081a92434d234599e80992e4189ed11 100644 (file)
@@ -3,7 +3,7 @@
 #include "listbox.qh"
 CLASS(XonoticScreenshotList, XonoticListBox)
        METHOD(XonoticScreenshotList, configureXonoticScreenshotList, void(entity));
-       ATTRIB(XonoticScreenshotList, rowsPerItem, float, 1)
+       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));
@@ -16,23 +16,23 @@ CLASS(XonoticScreenshotList, XonoticListBox)
        METHOD(XonoticScreenshotList, keyDown, float(entity, float, float, float));
        METHOD(XonoticScreenshotList, destroy, void(entity));
        METHOD(XonoticScreenshotList, showNotify, void(entity));
-       ATTRIB(XonoticScreenshotList, listScreenshot, float, -1)
-       ATTRIB(XonoticScreenshotList, realFontSize, vector, '0 0 0')
-       ATTRIB(XonoticScreenshotList, columnNameOrigin, float, 0)
-       ATTRIB(XonoticScreenshotList, columnNameSize, float, 0)
-       ATTRIB(XonoticScreenshotList, realUpperMargin, float, 0)
-       ATTRIB(XonoticScreenshotList, origin, vector, '0 0 0')
-       ATTRIB(XonoticScreenshotList, itemAbsSize, vector, '0 0 0')
-       ATTRIB(XonoticScreenshotList, filterString, string, string_null)
-       ATTRIB(XonoticScreenshotList, filterBox, entity, NULL)
-       ATTRIB(XonoticScreenshotList, filterTime, float, 0)
+       ATTRIB(XonoticScreenshotList, listScreenshot, float, -1);
+       ATTRIB(XonoticScreenshotList, realFontSize, vector, '0 0 0');
+       ATTRIB(XonoticScreenshotList, columnNameOrigin, float, 0);
+       ATTRIB(XonoticScreenshotList, columnNameSize, float, 0);
+       ATTRIB(XonoticScreenshotList, realUpperMargin, float, 0);
+       ATTRIB(XonoticScreenshotList, origin, vector, '0 0 0');
+       ATTRIB(XonoticScreenshotList, itemAbsSize, vector, '0 0 0');
+       ATTRIB(XonoticScreenshotList, filterString, string);
+       ATTRIB(XonoticScreenshotList, filterBox, entity);
+       ATTRIB(XonoticScreenshotList, filterTime, float, 0);
 
-       ATTRIB(XonoticScreenshotList, newScreenshotTime, float, 0)
-       ATTRIB(XonoticScreenshotList, newSlideShowScreenshotTime, float, 0)
+       ATTRIB(XonoticScreenshotList, newScreenshotTime, float, 0);
+       ATTRIB(XonoticScreenshotList, newSlideShowScreenshotTime, float, 0);
 
-       ATTRIB(XonoticScreenshotList, screenshotBrowserDialog, entity, NULL)
-       ATTRIB(XonoticScreenshotList, screenshotPreview, entity, NULL)
-       ATTRIB(XonoticScreenshotList, screenshotViewerDialog, entity, NULL)
+       ATTRIB(XonoticScreenshotList, screenshotBrowserDialog, entity);
+       ATTRIB(XonoticScreenshotList, screenshotPreview, entity);
+       ATTRIB(XonoticScreenshotList, screenshotViewerDialog, entity);
        METHOD(XonoticScreenshotList, goScreenshot, void(entity, float));
        METHOD(XonoticScreenshotList, startSlideShow, void(entity));
        METHOD(XonoticScreenshotList, stopSlideShow, void(entity));
index 46506dcfa0f71a8627a99b6cecd36037ce2fb8fa..c8346fff80dbcc5c7ca09ff05d81ef7198ec0b8d 100644 (file)
@@ -212,7 +212,7 @@ int CheckCategoryForEntry(int entry)
                        case "cts":
                        case "xdf": { return CAT_DEFRAG; }
 
-                       default: { LOG_TRACEF("Found strange mod type: %s\n", modtype); return CAT_MODIFIED; }
+                       default: { LOG_TRACEF("Found strange mod type: %s", modtype); return CAT_MODIFIED; }
                }
        }
 
@@ -630,10 +630,8 @@ void ServerList_PlayerSort_Click(entity btn, entity me)
 }
 void ServerList_TypeSort_Click(entity btn, entity me)
 {
-       string s, t;
-       float i, m;
-       s = me.filterString;
-       m = strstrofs(s, ":", 0);
+       string s = me.filterString;
+       int m = strstrofs(s, ":", 0);
        if(m >= 0)
        {
                s = substring(s, 0, m);
@@ -643,30 +641,23 @@ void ServerList_TypeSort_Click(entity btn, entity me)
        else
                s = "";
 
-       for(i = 1; ; i *= 2) // 20 modes ought to be enough for anyone
-       {
-               t = MapInfo_Type_ToString(i);
-               if(i > 1)
-                       if(t == "") // it repeats (default case)
-                       {
-                               // no type was found
-                               // choose the first one
-                               s = MapInfo_Type_ToString(1);
-                               break;
-                       }
-               if(s == t)
-               {
-                       // the type was found
-                       // choose the next one
-                       s = MapInfo_Type_ToString(i * 2);
-                       if(s == "")
-                               s = MapInfo_Type_ToString(1);
-                       break;
-               }
+       Gametype first = NULL; FOREACH(Gametypes, !first, first = it; break);
+       bool flag = false;
+       FOREACH(Gametypes, s == MapInfo_Type_ToString(it), {
+               // the type was found
+               // choose the next one
+               flag = true;
+               s = MapInfo_Type_ToString(Gametypes_from(it.m_id + 1));
+               if (s == "") s = MapInfo_Type_ToString(first);
+               break;
+       });
+       if (!flag) {
+               // no type was found
+               // choose the first one
+               s = MapInfo_Type_ToString(first);
        }
 
-       if(s != "")
-               s = strcat(s, ":");
+       if(s != "") s = strcat(s, ":");
        s = strcat(s, substring(me.filterString, m+1, strlen(me.filterString) - m - 1));
 
        me.controlledTextbox.setText(me.controlledTextbox, s);
index ac726b222ad055e16b0bf6b2ffd5cb37d1aed751..50c766e69051527be55929f7b4524c22ab228f14 100644 (file)
@@ -3,7 +3,7 @@
 #include "listbox.qh"
 CLASS(XonoticServerList, XonoticListBox)
        METHOD(XonoticServerList, configureXonoticServerList, void(entity));
-       ATTRIB(XonoticServerList, rowsPerItem, float, 1)
+       ATTRIB(XonoticServerList, rowsPerItem, float, 1);
        METHOD(XonoticServerList, draw, void(entity));
        METHOD(XonoticServerList, drawListBoxItem, void(entity, int, vector, bool, bool));
        METHOD(XonoticServerList, doubleClickListBoxItem, void(entity, float, vector));
@@ -11,56 +11,56 @@ CLASS(XonoticServerList, XonoticListBox)
        METHOD(XonoticServerList, keyDown, float(entity, float, float, float));
        METHOD(XonoticServerList, toggleFavorite, void(entity, string));
 
-       ATTRIB(XonoticServerList, iconsSizeFactor, float, 0.85)
+       ATTRIB(XonoticServerList, iconsSizeFactor, float, 0.85);
        METHOD(XonoticServerList, mouseMove, float(entity, vector));
-       ATTRIB(XonoticServerList, mouseOverIcons, bool, false)
+       ATTRIB(XonoticServerList, mouseOverIcons, bool, false);
        METHOD(XonoticServerList, focusedItemChangeNotify, void(entity));
 
-       ATTRIB(XonoticServerList, realFontSize, vector, '0 0 0')
-       ATTRIB(XonoticServerList, realUpperMargin, float, 0)
-       ATTRIB(XonoticServerList, columnIconsOrigin, float, 0)
-       ATTRIB(XonoticServerList, columnIconsSize, float, 0)
-       ATTRIB(XonoticServerList, columnPingOrigin, float, 0)
-       ATTRIB(XonoticServerList, columnPingSize, float, 0)
-       ATTRIB(XonoticServerList, columnNameOrigin, float, 0)
-       ATTRIB(XonoticServerList, columnNameSize, float, 0)
-       ATTRIB(XonoticServerList, columnMapOrigin, float, 0)
-       ATTRIB(XonoticServerList, columnMapSize, float, 0)
-       ATTRIB(XonoticServerList, columnTypeOrigin, float, 0)
-       ATTRIB(XonoticServerList, columnTypeSize, float, 0)
-       ATTRIB(XonoticServerList, columnPlayersOrigin, float, 0)
-       ATTRIB(XonoticServerList, columnPlayersSize, float, 0)
-       ATTRIB(XonoticServerList, lockedSelectedItem, bool, true)      // initially keep selected the first item of the list, avoiding an unwanted scrolling
-
-       ATTRIB(XonoticServerList, selectedServer, string, string_null) // to restore selected server when needed
+       ATTRIB(XonoticServerList, realFontSize, vector, '0 0 0');
+       ATTRIB(XonoticServerList, realUpperMargin, float, 0);
+       ATTRIB(XonoticServerList, columnIconsOrigin, float, 0);
+       ATTRIB(XonoticServerList, columnIconsSize, float, 0);
+       ATTRIB(XonoticServerList, columnPingOrigin, float, 0);
+       ATTRIB(XonoticServerList, columnPingSize, float, 0);
+       ATTRIB(XonoticServerList, columnNameOrigin, float, 0);
+       ATTRIB(XonoticServerList, columnNameSize, float, 0);
+       ATTRIB(XonoticServerList, columnMapOrigin, float, 0);
+       ATTRIB(XonoticServerList, columnMapSize, float, 0);
+       ATTRIB(XonoticServerList, columnTypeOrigin, float, 0);
+       ATTRIB(XonoticServerList, columnTypeSize, float, 0);
+       ATTRIB(XonoticServerList, columnPlayersOrigin, float, 0);
+       ATTRIB(XonoticServerList, columnPlayersSize, float, 0);
+       ATTRIB(XonoticServerList, lockedSelectedItem, bool, true);      // initially keep selected the first item of the list, avoiding an unwanted scrolling
+
+       ATTRIB(XonoticServerList, selectedServer, string); // to restore selected server when needed
        METHOD(XonoticServerList, setSelected, void(entity, float));
        METHOD(XonoticServerList, setSortOrder, void(entity, float, float));
-       ATTRIB(XonoticServerList, filterShowEmpty, float, 1)
-       ATTRIB(XonoticServerList, filterShowFull, float, 1)
-       ATTRIB(XonoticServerList, filterString, string, string_null)
-       ATTRIB(XonoticServerList, controlledTextbox, entity, NULL)
-       ATTRIB(XonoticServerList, ipAddressBox, entity, NULL)
-       ATTRIB(XonoticServerList, favoriteButton, entity, NULL)
-       ATTRIB(XonoticServerList, nextRefreshTime, float, 0)
+       ATTRIB(XonoticServerList, filterShowEmpty, float, 1);
+       ATTRIB(XonoticServerList, filterShowFull, float, 1);
+       ATTRIB(XonoticServerList, filterString, string);
+       ATTRIB(XonoticServerList, controlledTextbox, entity);
+       ATTRIB(XonoticServerList, ipAddressBox, entity);
+       ATTRIB(XonoticServerList, favoriteButton, entity);
+       ATTRIB(XonoticServerList, nextRefreshTime, float, 0);
        METHOD(XonoticServerList, refreshServerList, void(entity, float));  // refresh mode: REFRESHSERVERLIST_*
-       ATTRIB(XonoticServerList, needsRefresh, float, 1)
+       ATTRIB(XonoticServerList, needsRefresh, float, 1);
        METHOD(XonoticServerList, focusEnter, void(entity));
        METHOD(XonoticServerList, positionSortButton, void(entity, entity, float, float, string, void(entity, entity)));
-       ATTRIB(XonoticServerList, sortButton1, entity, NULL)
-       ATTRIB(XonoticServerList, sortButton2, entity, NULL)
-       ATTRIB(XonoticServerList, sortButton3, entity, NULL)
-       ATTRIB(XonoticServerList, sortButton4, entity, NULL)
-       ATTRIB(XonoticServerList, sortButton5, entity, NULL)
-       ATTRIB(XonoticServerList, connectButton, entity, NULL)
-       ATTRIB(XonoticServerList, infoButton, entity, NULL)
-       ATTRIB(XonoticServerList, currentSortOrder, float, 0)
-       ATTRIB(XonoticServerList, currentSortField, float, -1)
-
-       ATTRIB(XonoticServerList, ipAddressBoxFocused, float, -1)
-
-       ATTRIB(XonoticServerList, seenIPv4, float, 0)
-       ATTRIB(XonoticServerList, seenIPv6, float, 0)
-       ATTRIB(XonoticServerList, categoriesHeight, float, 1.25)
+       ATTRIB(XonoticServerList, sortButton1, entity);
+       ATTRIB(XonoticServerList, sortButton2, entity);
+       ATTRIB(XonoticServerList, sortButton3, entity);
+       ATTRIB(XonoticServerList, sortButton4, entity);
+       ATTRIB(XonoticServerList, sortButton5, entity);
+       ATTRIB(XonoticServerList, connectButton, entity);
+       ATTRIB(XonoticServerList, infoButton, entity);
+       ATTRIB(XonoticServerList, currentSortOrder, float, 0);
+       ATTRIB(XonoticServerList, currentSortField, float, -1);
+
+       ATTRIB(XonoticServerList, ipAddressBoxFocused, float, -1);
+
+       ATTRIB(XonoticServerList, seenIPv4, float, 0);
+       ATTRIB(XonoticServerList, seenIPv6, float, 0);
+       ATTRIB(XonoticServerList, categoriesHeight, float, 1.25);
 
        METHOD(XonoticServerList, getTotalHeight, float(entity));
        METHOD(XonoticServerList, getItemAtPos, float(entity, float));
index 616fc233dcdd6a9bac92d9f0c66ae628a022ac56..9ea9aa54c6d1a80afa31d5f215de8b89ba8c9fb0 100644 (file)
@@ -3,7 +3,7 @@
 #include "listbox.qh"
 CLASS(XonoticSkinList, XonoticListBox)
        METHOD(XonoticSkinList, configureXonoticSkinList, void(entity));
-       ATTRIB(XonoticSkinList, rowsPerItem, float, 4)
+       ATTRIB(XonoticSkinList, rowsPerItem, float, 4);
        METHOD(XonoticSkinList, resizeNotify, void(entity, vector, vector, vector, vector));
        METHOD(XonoticSkinList, drawListBoxItem, void(entity, int, vector, bool, bool));
        METHOD(XonoticSkinList, getSkins, void(entity));
@@ -15,18 +15,18 @@ CLASS(XonoticSkinList, XonoticListBox)
        METHOD(XonoticSkinList, keyDown, float(entity, float, float, float));
        METHOD(XonoticSkinList, destroy, void(entity));
 
-       ATTRIB(XonoticSkinList, skinlist, float, -1)
-       ATTRIB(XonoticSkinList, realFontSize, vector, '0 0 0')
-       ATTRIB(XonoticSkinList, columnPreviewOrigin, float, 0)
-       ATTRIB(XonoticSkinList, columnPreviewSize, float, 0)
-       ATTRIB(XonoticSkinList, columnNameOrigin, float, 0)
-       ATTRIB(XonoticSkinList, columnNameSize, float, 0)
-       ATTRIB(XonoticSkinList, realUpperMargin1, float, 0)
-       ATTRIB(XonoticSkinList, realUpperMargin2, float, 0)
-       ATTRIB(XonoticSkinList, origin, vector, '0 0 0')
-       ATTRIB(XonoticSkinList, itemAbsSize, vector, '0 0 0')
+       ATTRIB(XonoticSkinList, skinlist, float, -1);
+       ATTRIB(XonoticSkinList, realFontSize, vector, '0 0 0');
+       ATTRIB(XonoticSkinList, columnPreviewOrigin, float, 0);
+       ATTRIB(XonoticSkinList, columnPreviewSize, float, 0);
+       ATTRIB(XonoticSkinList, columnNameOrigin, float, 0);
+       ATTRIB(XonoticSkinList, columnNameSize, float, 0);
+       ATTRIB(XonoticSkinList, realUpperMargin1, float, 0);
+       ATTRIB(XonoticSkinList, realUpperMargin2, float, 0);
+       ATTRIB(XonoticSkinList, origin, vector, '0 0 0');
+       ATTRIB(XonoticSkinList, itemAbsSize, vector, '0 0 0');
 
-       ATTRIB(XonoticSkinList, name, string, "skinselector")
+       ATTRIB(XonoticSkinList, name, string, "skinselector");
 ENDCLASS(XonoticSkinList)
 
 entity makeXonoticSkinList();
index 17287c42841cc3b8f164ad6ab0090a750517fc8e..9204c5eb35b501481d2be533c53c361b18b10245 100644 (file)
@@ -5,24 +5,24 @@ CLASS(XonoticSlider, Slider)
        METHOD(XonoticSlider, configureXonoticSlider, void(entity, float, float, float, string, string));
        METHOD(XonoticSlider, setValue, void(entity, float));
        METHOD(XonoticSlider, setValue_noAnim, void(entity, float));
-       ATTRIB(XonoticSlider, fontSize, float, SKINFONTSIZE_NORMAL)
-       ATTRIB(XonoticSlider, valueSpace, float, SKINWIDTH_SLIDERTEXT)
-       ATTRIB(XonoticSlider, image, string, SKINGFX_SLIDER)
-       ATTRIB(XonoticSlider, tolerance, vector, SKINTOLERANCE_SLIDER)
-       ATTRIB(XonoticSlider, align, float, 0.5)
-       ATTRIB(XonoticSlider, color, vector, SKINCOLOR_SLIDER_N)
-       ATTRIB(XonoticSlider, colorC, vector, SKINCOLOR_SLIDER_C)
-       ATTRIB(XonoticSlider, colorF, vector, SKINCOLOR_SLIDER_F)
-       ATTRIB(XonoticSlider, colorD, vector, SKINCOLOR_SLIDER_D)
-       ATTRIB(XonoticSlider, color2, vector, SKINCOLOR_SLIDER_S)
+       ATTRIB(XonoticSlider, fontSize, float, SKINFONTSIZE_NORMAL);
+       ATTRIB(XonoticSlider, valueSpace, float, SKINWIDTH_SLIDERTEXT);
+       ATTRIB(XonoticSlider, image, string, SKINGFX_SLIDER);
+       ATTRIB(XonoticSlider, tolerance, vector, SKINTOLERANCE_SLIDER);
+       ATTRIB(XonoticSlider, align, float, 0.5);
+       ATTRIB(XonoticSlider, color, vector, SKINCOLOR_SLIDER_N);
+       ATTRIB(XonoticSlider, colorC, vector, SKINCOLOR_SLIDER_C);
+       ATTRIB(XonoticSlider, colorF, vector, SKINCOLOR_SLIDER_F);
+       ATTRIB(XonoticSlider, colorD, vector, SKINCOLOR_SLIDER_D);
+       ATTRIB(XonoticSlider, color2, vector, SKINCOLOR_SLIDER_S);
 
-       ATTRIB(XonoticSlider, cvarName, string, string_null)
+       ATTRIB(XonoticSlider, cvarName, string);
        METHOD(XonoticSlider, loadCvars, void(entity));
        METHOD(XonoticSlider, saveCvars, void(entity));
-       ATTRIB(XonoticSlider, sendCvars, float, 0)
+       ATTRIB(XonoticSlider, sendCvars, float, 0);
 
-       ATTRIB(XonoticSlider, alpha, float, SKINALPHA_TEXT)
-       ATTRIB(XonoticSlider, disabledAlpha, float, SKINALPHA_DISABLED)
+       ATTRIB(XonoticSlider, alpha, float, SKINALPHA_TEXT);
+       ATTRIB(XonoticSlider, disabledAlpha, float, SKINALPHA_DISABLED);
 ENDCLASS(XonoticSlider)
 entity makeXonoticSlider_T(float, float, float, string, string theTooltip);
 entity makeXonoticSlider(float, float, float, string);
index d25ba994befebe50917885258f9e72905c49a407..3661fd4936e13281d41d3d2a3237ecf30b849455 100644 (file)
@@ -5,6 +5,6 @@ CLASS(XonoticPicmipSlider, XonoticTextSlider)
        METHOD(XonoticPicmipSlider, configureXonoticPicmipSlider, void(entity));
        METHOD(XonoticPicmipSlider, draw, void(entity));
        METHOD(XonoticPicmipSlider, autofix, void(entity));
-       ATTRIB(XonoticPicmipSlider, have_s3tc, float, 0)
+       ATTRIB(XonoticPicmipSlider, have_s3tc, float, 0);
 ENDCLASS(XonoticPicmipSlider)
 entity makeXonoticPicmipSlider();  // note: you still need to call addValue and configureXonoticTextSliderValues!
index 1e0a80b7676d91f349d21045f06167b5f9fe0b04..9a55f884030e25732d23cad43de801e4e6c22c13 100644 (file)
@@ -39,8 +39,8 @@ float updateConwidths(float width, float height, float pixelheight)
 
        minfactor = min(1, 640 / c.x);            // can be > 1 only if c_x is <640
        maxfactor = max(1, r.x / c.x, r.y / c.y); // can be < 1 only if r_x < c_x and r_y < c_y
-       LOG_TRACE("min factor: ", ftos(minfactor), "\n");
-       LOG_TRACE("max factor: ", ftos(maxfactor), "\n");
+       LOG_TRACE("min factor: ", ftos(minfactor));
+       LOG_TRACE("max factor: ", ftos(maxfactor));
 
        if(sz < 0)
                f = 1 - (maxfactor - 1) * sz;
@@ -149,7 +149,7 @@ void XonoticResolutionSlider_loadResolutions(entity me, float fullscreen)
                r = getresolution(-1);
                if(r.x != 0 || r.y != 0)
                        me.addResolution(me, r.x, r.y, r.z);
-               LOG_TRACE("Added system resolutions.\n");
+               LOG_TRACE("Added system resolutions.");
        }
 
        if(me.nValues == 0)
@@ -184,9 +184,9 @@ void XonoticResolutionSlider_loadResolutions(entity me, float fullscreen)
                me.addResolution(me, 1280, 960, 1); // pc res
                me.addResolution(me, 1280, 1024, 1); // pc res
                me.addResolution(me, 1920, 1080, 1); // 1080p
-               LOG_TRACE("Added default resolutions.\n");
+               LOG_TRACE("Added default resolutions.");
        }
-       LOG_TRACE("Total number of resolutions detected: ", ftos(me.nValues), "\n");
+       LOG_TRACE("Total number of resolutions detected: ", ftos(me.nValues));
 
        me.vid_fullscreen = fullscreen;
 
index 40b7bbbc246764e24f4b20a7fcb3d07f53aaa994..3b56c2a8fdb27c9511f7dc3856ba2dd0ae18abfd 100644 (file)
@@ -8,9 +8,9 @@ CLASS(XonoticResolutionSlider, XonoticTextSlider)
        METHOD(XonoticResolutionSlider, loadCvars, void(entity));
        METHOD(XonoticResolutionSlider, saveCvars, void(entity));
        METHOD(XonoticResolutionSlider, draw, void(entity));
-       ATTRIB(XonoticResolutionSlider, vid_fullscreen, float, -1)
-       ATTRIB(XonoticResolutionSlider, maxAllowedWidth, float, 0)
-       ATTRIB(XonoticResolutionSlider, maxAllowedHeight, float, 0)
+       ATTRIB(XonoticResolutionSlider, vid_fullscreen, float, -1);
+       ATTRIB(XonoticResolutionSlider, maxAllowedWidth, float, 0);
+       ATTRIB(XonoticResolutionSlider, maxAllowedHeight, float, 0);
 ENDCLASS(XonoticResolutionSlider)
 entity makeXonoticResolutionSlider();
 float updateConwidths(float width, float height, float pixelheight);
index 1e4bdbca21664d56fea25791cf0c3bf5161d1d53..048a42184c86c6b9ffadc3f0014414ca2dafc65d 100644 (file)
@@ -9,7 +9,7 @@ entity makeXonoticScoreboardFadeTimeSlider()
 }
 void XonoticScoreboardFadeTimeSlider_configureXonoticScoreboardFadeTimeSlider(entity me)
 {
-       me.configureXonoticTextSlider(me, "scoreboard_fadeinspeed", string_null);
+       me.configureXonoticTextSlider(me, "hud_panel_scoreboard_fadeinspeed", string_null);
        me.addValue(me, ZCTX(_("PART^Slow")),     "5 2.5");
        me.addValue(me, ZCTX(_("PART^Normal")),   "10 5");
        me.addValue(me, ZCTX(_("PART^Fast")),     "15 7.5");
@@ -19,8 +19,8 @@ void XonoticScoreboardFadeTimeSlider_configureXonoticScoreboardFadeTimeSlider(en
 void XonoticScoreboardFadeTimeSlider_loadCvars(entity me)
 {
        me.setValueFromIdentifier_noAnim(me, sprintf("%s %s",
-               cvar_string("scoreboard_fadeinspeed"),
-               cvar_string("scoreboard_fadeoutspeed")
+               cvar_string("hud_panel_scoreboard_fadeinspeed"),
+               cvar_string("hud_panel_scoreboard_fadeoutspeed")
        ));
 }
 void XonoticScoreboardFadeTimeSlider_saveCvars(entity me)
@@ -28,7 +28,7 @@ void XonoticScoreboardFadeTimeSlider_saveCvars(entity me)
        if(me.value >= 0 || me.value < me.nValues)
        {
                tokenize_console(me.getIdentifier(me));
-               cvar_set("scoreboard_fadeinspeed", argv(0));
-               cvar_set("scoreboard_fadeoutspeed", argv(1));
+               cvar_set("hud_panel_scoreboard_fadeinspeed", argv(0));
+               cvar_set("hud_panel_scoreboard_fadeoutspeed", argv(1));
        }
 }
index 86dc4c773f8f1afa62b3011ecc20c8e788cf5bbc..1e30baa11d773f9cf00617b0786f8ed3a4f51728 100644 (file)
@@ -3,7 +3,7 @@
 #include "listbox.qh"
 CLASS(XonoticSoundList, XonoticListBox)
        METHOD(XonoticSoundList, configureXonoticSoundList, void(entity));
-       ATTRIB(XonoticSoundList, rowsPerItem, float, 1)
+       ATTRIB(XonoticSoundList, rowsPerItem, float, 1);
        METHOD(XonoticSoundList, resizeNotify, void(entity, vector, vector, vector, vector));
        METHOD(XonoticSoundList, drawListBoxItem, void(entity, int, vector, bool, bool));
        METHOD(XonoticSoundList, getSounds, void(entity));
@@ -13,18 +13,18 @@ CLASS(XonoticSoundList, XonoticListBox)
        METHOD(XonoticSoundList, destroy, void(entity));
        METHOD(XonoticSoundList, showNotify, void(entity));
 
-       ATTRIB(XonoticSoundList, listSound, int, -1)
-       ATTRIB(XonoticSoundList, realFontSize, vector, '0 0 0')
-       ATTRIB(XonoticSoundList, columnNameOrigin, float, 0)
-       ATTRIB(XonoticSoundList, columnNameSize, float, 0)
-       ATTRIB(XonoticSoundList, columnNumberOrigin, float, 0)
-       ATTRIB(XonoticSoundList, columnNumberSize, float, 0)
-       ATTRIB(XonoticSoundList, realUpperMargin, float, 0)
-       ATTRIB(XonoticSoundList, origin, vector, '0 0 0')
-       ATTRIB(XonoticSoundList, itemAbsSize, vector, '0 0 0')
+       ATTRIB(XonoticSoundList, listSound, int, -1);
+       ATTRIB(XonoticSoundList, realFontSize, vector, '0 0 0');
+       ATTRIB(XonoticSoundList, columnNameOrigin, float, 0);
+       ATTRIB(XonoticSoundList, columnNameSize, float, 0);
+       ATTRIB(XonoticSoundList, columnNumberOrigin, float, 0);
+       ATTRIB(XonoticSoundList, columnNumberSize, float, 0);
+       ATTRIB(XonoticSoundList, realUpperMargin, float, 0);
+       ATTRIB(XonoticSoundList, origin, vector, '0 0 0');
+       ATTRIB(XonoticSoundList, itemAbsSize, vector, '0 0 0');
 
-       ATTRIB(XonoticSoundList, filterString, string, string_null)
-       ATTRIB(XonoticSoundList, playlist, entity, NULL)
+       ATTRIB(XonoticSoundList, filterString, string);
+       ATTRIB(XonoticSoundList, playlist, entity);
 ENDCLASS(XonoticSoundList)
 
 entity makeXonoticSoundList();
index 7fdbf9c1645dde038675f8787e947d8dbba794aa..3e94738a9ab500d89a162003be58ef67106e49f0 100644 (file)
@@ -51,7 +51,7 @@ string XonoticStatsList_convertDate(string input)
 
 void XonoticStatsList_getStats(entity me)
 {
-       LOG_TRACE("XonoticStatsList_getStats() at time: ", ftos(time), "\n");
+       LOG_TRACE("XonoticStatsList_getStats() at time: ", ftos(time));
        // delete the old buffer if it exists
        if(me.listStats >= 0)
                buf_del(me.listStats);
index ebef28ac0140a34a9d17813389b7deda95653f47..01fb93645bf6aeb92991805cb4d642e1b2bed5b1 100644 (file)
@@ -3,7 +3,7 @@
 #include "listbox.qh"
 CLASS(XonoticStatsList, XonoticListBox)
        METHOD(XonoticStatsList, configureXonoticStatsList, void(entity));
-       ATTRIB(XonoticStatsList, rowsPerItem, float, 1.4)
+       ATTRIB(XonoticStatsList, rowsPerItem, float, 1.4);
        METHOD(XonoticStatsList, resizeNotify, void(entity, vector, vector, vector, vector));
        METHOD(XonoticStatsList, drawListBoxItem, void(entity, int, vector, bool, bool));
        METHOD(XonoticStatsList, getStats, void(entity));
@@ -11,13 +11,13 @@ CLASS(XonoticStatsList, XonoticListBox)
        METHOD(XonoticStatsList, keyDown, float(entity, float, float, float));
        METHOD(XonoticStatsList, destroy, void(entity));
        METHOD(XonoticStatsList, showNotify, void(entity));
-       ATTRIB(XonoticStatsList, selectionDoesntMatter, bool, true)
+       ATTRIB(XonoticStatsList, selectionDoesntMatter, bool, true);
 
-       ATTRIB(XonoticStatsList, listStats, float, -1)
-       ATTRIB(XonoticStatsList, realFontSize, vector, '0 0 0')
-       ATTRIB(XonoticStatsList, realUpperMargin, float, 0)
-       ATTRIB(XonoticStatsList, columnNameOrigin, float, 0)
-       ATTRIB(XonoticStatsList, columnNameSize, float, 0)
+       ATTRIB(XonoticStatsList, listStats, float, -1);
+       ATTRIB(XonoticStatsList, realFontSize, vector, '0 0 0');
+       ATTRIB(XonoticStatsList, realUpperMargin, float, 0);
+       ATTRIB(XonoticStatsList, columnNameOrigin, float, 0);
+       ATTRIB(XonoticStatsList, columnNameSize, float, 0);
 ENDCLASS(XonoticStatsList)
 
 entity statslist;  // for reference elsewhere
index b296d2491846c5f27ca20b45847397d631699b6f..ff561d57e68d139dcb404e97270e4c6befc9e277 100644 (file)
@@ -4,24 +4,24 @@
 CLASS(XonoticTab, Tab)
        // still to be customized by user
        /*
-       ATTRIB(XonoticTab, intendedWidth, float, 0)
-       ATTRIB(XonoticTab, rows, float, 3)
-       ATTRIB(XonoticTab, columns, float, 2)
+       ATTRIB(XonoticTab, intendedWidth, float, 0);
+       ATTRIB(XonoticTab, rows, float, 3);
+       ATTRIB(XonoticTab, columns, float, 2);
        */
        METHOD(XonoticTab, showNotify, void(entity));
 
-       ATTRIB(XonoticTab, marginTop, float, 0)                                       // pixels
-       ATTRIB(XonoticTab, marginBottom, float, 0)                                    // pixels
-       ATTRIB(XonoticTab, marginLeft, float, 0)                                      // pixels
-       ATTRIB(XonoticTab, marginRight, float, 0)                                     // pixels
-       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, marginTop, float, 0);                                       // pixels
+       ATTRIB(XonoticTab, marginBottom, float, 0);                                    // pixels
+       ATTRIB(XonoticTab, marginLeft, float, 0);                                      // pixels
+       ATTRIB(XonoticTab, marginRight, float, 0);                                     // pixels
+       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, backgroundImage, string, string_null)
+       ATTRIB(XonoticTab, backgroundImage, string);
 
        // using "titleTooltip" instead of "tooltip" so that
        // the tooltip search function doesn't find it
        // .tooltip should be set only in the item displaying the tab title
-       ATTRIB(XonoticTab, titleTooltip, string, string_null)
+       ATTRIB(XonoticTab, titleTooltip, string);
 ENDCLASS(XonoticTab)
index eb4d48f8d96efa436bb35d05e570e2f1e3723ee6..46d140eb08d8023c6450ad3b4a03c7e7892ff5fb 100644 (file)
@@ -5,8 +5,8 @@ CLASS(XonoticTabController, ModalController)
        METHOD(XonoticTabController, configureXonoticTabController, void(entity, float));
        METHOD(XonoticTabController, makeTabButton_T, entity(entity, string, entity, string));
        METHOD(XonoticTabController, makeTabButton, entity(entity, string, entity));
-       ATTRIB(XonoticTabController, rows, float, 0)
-       ATTRIB(XonoticTabController, fontSize, float, SKINFONTSIZE_NORMAL)
-       ATTRIB(XonoticTabController, image, string, SKINGFX_BUTTON)
+       ATTRIB(XonoticTabController, rows, float, 0);
+       ATTRIB(XonoticTabController, fontSize, float, SKINFONTSIZE_NORMAL);
+       ATTRIB(XonoticTabController, image, string, SKINGFX_BUTTON);
 ENDCLASS(XonoticTabController)
 entity makeXonoticTabController(float theRows);
index fde05de8a34bd6b0897c0f093f8668547cc5f2b5..94f7a74228ef45c58f5b9055241b9271bf9abba1 100644 (file)
@@ -4,9 +4,9 @@
 CLASS(XonoticTextLabel, Label)
        METHOD(XonoticTextLabel, configureXonoticTextLabel, void(entity, float, string));
        METHOD(XonoticTextLabel, draw, void(entity));
-       ATTRIB(XonoticTextLabel, fontSize, float, SKINFONTSIZE_NORMAL)
-       ATTRIB(XonoticTextLabel, alpha, float, SKINALPHA_TEXT)
-       ATTRIB(XonoticTextLabel, disabledAlpha, float, SKINALPHA_DISABLED)
+       ATTRIB(XonoticTextLabel, fontSize, float, SKINFONTSIZE_NORMAL);
+       ATTRIB(XonoticTextLabel, alpha, float, SKINALPHA_TEXT);
+       ATTRIB(XonoticTextLabel, disabledAlpha, float, SKINALPHA_DISABLED);
 ENDCLASS(XonoticTextLabel)
 entity makeXonoticTextLabel(float theAlign, string theText);
 entity makeXonoticHeaderLabel(string theText);
index ae81f36e87ba44e5e8d52f024ce33fe154abdf50..58fe8e86bbe4a0becaac10ea463fe493f50b2d72 100644 (file)
@@ -6,24 +6,24 @@ CLASS(XonoticTextSlider, TextSlider)
        METHOD(XonoticTextSlider, setValue, void(entity, float));
        METHOD(XonoticTextSlider, setValue_noAnim, void(entity, float));
        METHOD(XonoticTextSlider, configureXonoticTextSliderValues, void(entity));
-       ATTRIB(XonoticTextSlider, fontSize, float, SKINFONTSIZE_NORMAL)
-       ATTRIB(XonoticTextSlider, valueSpace, float, SKINWIDTH_SLIDERTEXT)
-       ATTRIB(XonoticTextSlider, image, string, SKINGFX_SLIDER)
-       ATTRIB(XonoticTextSlider, tolerance, vector, SKINTOLERANCE_SLIDER)
-       ATTRIB(XonoticTextSlider, align, float, 0.5)
-       ATTRIB(XonoticTextSlider, color, vector, SKINCOLOR_SLIDER_N)
-       ATTRIB(XonoticTextSlider, colorC, vector, SKINCOLOR_SLIDER_C)
-       ATTRIB(XonoticTextSlider, colorF, vector, SKINCOLOR_SLIDER_F)
-       ATTRIB(XonoticTextSlider, colorD, vector, SKINCOLOR_SLIDER_D)
-       ATTRIB(XonoticTextSlider, color2, vector, SKINCOLOR_SLIDER_S)
+       ATTRIB(XonoticTextSlider, fontSize, float, SKINFONTSIZE_NORMAL);
+       ATTRIB(XonoticTextSlider, valueSpace, float, SKINWIDTH_SLIDERTEXT);
+       ATTRIB(XonoticTextSlider, image, string, SKINGFX_SLIDER);
+       ATTRIB(XonoticTextSlider, tolerance, vector, SKINTOLERANCE_SLIDER);
+       ATTRIB(XonoticTextSlider, align, float, 0.5);
+       ATTRIB(XonoticTextSlider, color, vector, SKINCOLOR_SLIDER_N);
+       ATTRIB(XonoticTextSlider, colorC, vector, SKINCOLOR_SLIDER_C);
+       ATTRIB(XonoticTextSlider, colorF, vector, SKINCOLOR_SLIDER_F);
+       ATTRIB(XonoticTextSlider, colorD, vector, SKINCOLOR_SLIDER_D);
+       ATTRIB(XonoticTextSlider, color2, vector, SKINCOLOR_SLIDER_S);
 
-       ATTRIB(XonoticTextSlider, cvarName, string, string_null)
+       ATTRIB(XonoticTextSlider, cvarName, string);
        METHOD(XonoticTextSlider, loadCvars, void(entity));
        METHOD(XonoticTextSlider, saveCvars, void(entity));
-       ATTRIB(XonoticTextSlider, sendCvars, float, 0)
+       ATTRIB(XonoticTextSlider, sendCvars, float, 0);
 
-       ATTRIB(XonoticTextSlider, alpha, float, SKINALPHA_TEXT)
-       ATTRIB(XonoticTextSlider, disabledAlpha, float, SKINALPHA_DISABLED)
+       ATTRIB(XonoticTextSlider, alpha, float, SKINALPHA_TEXT);
+       ATTRIB(XonoticTextSlider, disabledAlpha, float, SKINALPHA_DISABLED);
 ENDCLASS(XonoticTextSlider)
 entity makeXonoticTextSlider_T(string, string theTooltip);
 entity makeXonoticTextSlider(string);  // note: you still need to call addValue and configureXonoticTextSliderValues!
index a0018b99a905f7af574d043c37f8de75711c3021..9cc4da8c38705baeeb633b9607ad7086870848bf 100644 (file)
@@ -321,22 +321,22 @@ void UpdateNotification_URI_Get_Callback(float id, float status, string data)
 
        if(_Nex_ExtResponseSystem_UpdateTo)
        {
-               LOG_TRACE("error: UpdateNotification_URI_Get_Callback has been called before\n");
+               LOG_TRACE("error: UpdateNotification_URI_Get_Callback has been called before");
                return;
        }
        if(status != 0)
        {
-               LOG_TRACEF("error receiving update notification: status is %d\n", status);
+               LOG_TRACEF("error receiving update notification: status is %d", status);
                return;
        }
        if(substring(data, 0, 1) == "<")
        {
-               LOG_TRACE("error: received HTML instead of an update notification\n");
+               LOG_TRACE("error: received HTML instead of an update notification");
                return;
        }
        if(strstrofs(data, "\r", 0) != -1)
        {
-               LOG_TRACE("error: received carriage returns from update notification server\n");
+               LOG_TRACE("error: received carriage returns from update notification server");
                return;
        }
 
@@ -515,7 +515,7 @@ float preMenuInit()
 
        MapInfo_Cache_Create();
        MapInfo_Enumerate();
-       if(!MapInfo_FilterGametype(MAPINFO_TYPE_ALL, 0, 0, 0, 1))
+       if(!_MapInfo_FilterGametype(MAPINFO_TYPE_ALL, 0, 0, 0, 1))
        {
                draw_reset_cropped();
 
@@ -690,48 +690,34 @@ float updateCompression()
        /* GAMETYPE(MAPINFO_TYPE_INVASION) */ \
        /**/
 
-int GameType_GetID(int cnt)
+Gametype GameType_GetID(int cnt)
 {
        int i = 0;
-
-       #define GAMETYPE(id) { if (i++ == cnt) return id; }
+       #define GAMETYPE(it) { if (i++ == cnt) return it; }
        GAMETYPES
        #undef GAMETYPE
-
-       unused_float = i;
-
-       return 0;
+       return NULL;
 }
 
 int GameType_GetCount()
 {
        int i = 0;
-
        #define GAMETYPE(id) ++i;
        GAMETYPES
        #undef GAMETYPE
-
        return i;
 }
 
 string GameType_GetName(int cnt)
 {
-       int i = GameType_GetID(cnt);
-
-       if(i)
-               return MapInfo_Type_ToText(i);
-
-       return "";
+       Gametype i = GameType_GetID(cnt);
+       return i ? MapInfo_Type_ToText(i) : "";
 }
 
 string GameType_GetIcon(int cnt)
 {
-       int i = GameType_GetID(cnt);
-
-       if(i)
-               return strcat("gametype_", MapInfo_Type_ToString(i));
-
-       return "";
+       Gametype i = GameType_GetID(cnt);
+       return i ? strcat("gametype_", MapInfo_Type_ToString(i)) : "";
 }
 
 .void(entity) TR;
index d433352cf5a1734e70429d8ed33e0faf0d11fc9f..c7e7c0cd70b96d138e8f7c09fdf70a7d61693343 100644 (file)
@@ -29,7 +29,7 @@ void UpdateNotification_URI_Get_Callback(float id, float status, string data);
 
 // game type list box stuff (does not NEED to contain all game types, other
 // types stay available via console)
-int GameType_GetID(int cnt);
+entity GameType_GetID(int cnt);
 string GameType_GetName(int cnt);
 string GameType_GetIcon(int cnt);
 //string GameType_GetTeams(float cnt);
index 0b8e214c8097916f2b58fa74e837a956a5920837..c3c155bb2b83dde97c56c552fb16759431aa38ab 100644 (file)
@@ -4,9 +4,9 @@
 CLASS(XonoticWeaponarenaCheckBox, CheckBox)
        METHOD(XonoticWeaponarenaCheckBox, configureXonoticWeaponarenaCheckBox, void(entity, string, string));
        METHOD(XonoticWeaponarenaCheckBox, setChecked, void(entity, float));
-       ATTRIB(XonoticWeaponarenaCheckBox, fontSize, float, SKINFONTSIZE_NORMAL)
-       ATTRIB(XonoticWeaponarenaCheckBox, image, string, SKINGFX_CHECKBOX)
-       ATTRIB(XonoticWeaponarenaCheckBox, netname, string, string_null)
+       ATTRIB(XonoticWeaponarenaCheckBox, fontSize, float, SKINFONTSIZE_NORMAL);
+       ATTRIB(XonoticWeaponarenaCheckBox, image, string, SKINGFX_CHECKBOX);
+       ATTRIB(XonoticWeaponarenaCheckBox, netname, string);
 
        METHOD(XonoticWeaponarenaCheckBox, loadCvars, void(entity));
        METHOD(XonoticWeaponarenaCheckBox, saveCvars, void(entity));
index 953a40cc0dd39a9f921fd7b2162a62015fc66130..4726d8553dc1a765fbc03672cc4137180a5135c7 100644 (file)
@@ -4,16 +4,16 @@
 CLASS(XonoticWeaponsList, XonoticListBox)
        METHOD(XonoticWeaponsList, configureXonoticWeaponsList, void(entity));
        METHOD(XonoticWeaponsList, toString, string(entity));
-       ATTRIB(XonoticWeaponsList, rowsPerItem, float, 1)
+       ATTRIB(XonoticWeaponsList, rowsPerItem, float, 1);
        METHOD(XonoticWeaponsList, draw, void(entity));
        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')
-       ATTRIB(XonoticWeaponsList, realUpperMargin, float, 0)
+       ATTRIB(XonoticWeaponsList, realFontSize, vector, '0 0 0');
+       ATTRIB(XonoticWeaponsList, realUpperMargin, float, 0);
        METHOD(XonoticWeaponsList, mouseDrag, float(entity, vector));
 
-       ATTRIB(XonoticWeaponsList, applyButton, entity, NULL)
+       ATTRIB(XonoticWeaponsList, applyButton, entity);
 ENDCLASS(XonoticWeaponsList)
 entity makeXonoticWeaponsList();
 void WeaponsList_MoveUp_Click(entity btn, entity me);
index 1ec7115ef27c503b55cd6c723a2a14e97a77afba..1735e1c11335f4e672c7908de65bd12ca6a231cb 100644 (file)
@@ -7,7 +7,7 @@ float test();
 spawnfunc(worldspawn)
 {
        float r;
-       LOG_TRACE("TESTCASE: START\n");
+       LOG_TRACE("TESTCASE: START");
        r = test();
        if(r == 1)
                error("TESTCASE: PASS");
index f66b77a068145eadb0460bfdd776d531aed6b454..a8d45bd5221ce1cde56fa0e9c8d3dd98fc639898 100644 (file)
@@ -5,61 +5,9 @@ bool autocvar__campaign_testrun;
 int autocvar__campaign_index;
 string autocvar__campaign_name;
 bool autocvar__sv_init;
-float autocvar_bot_ai_aimskill_blendrate;
-float autocvar_bot_ai_aimskill_firetolerance_distdegrees;
-float autocvar_bot_ai_aimskill_firetolerance_maxdegrees;
-float autocvar_bot_ai_aimskill_firetolerance_mindegrees;
-float autocvar_bot_ai_aimskill_fixedrate;
-float autocvar_bot_ai_aimskill_mouse;
-float autocvar_bot_ai_aimskill_offset;
-float autocvar_bot_ai_aimskill_order_filter_1st;
-float autocvar_bot_ai_aimskill_order_filter_2nd;
-float autocvar_bot_ai_aimskill_order_filter_3th;
-float autocvar_bot_ai_aimskill_order_filter_4th;
-float autocvar_bot_ai_aimskill_order_filter_5th;
-float autocvar_bot_ai_aimskill_order_mix_1st;
-float autocvar_bot_ai_aimskill_order_mix_2nd;
-float autocvar_bot_ai_aimskill_order_mix_3th;
-float autocvar_bot_ai_aimskill_order_mix_4th;
-float autocvar_bot_ai_aimskill_order_mix_5th;
-float autocvar_bot_ai_aimskill_think;
-float autocvar_bot_ai_bunnyhop_firstjumpdelay;
-float autocvar_bot_ai_bunnyhop_skilloffset;
-float autocvar_bot_ai_bunnyhop_startdistance;
-float autocvar_bot_ai_bunnyhop_stopdistance;
-float autocvar_bot_ai_chooseweaponinterval;
-string autocvar_bot_ai_custom_weapon_priority_close;
-string autocvar_bot_ai_custom_weapon_priority_distances;
-string autocvar_bot_ai_custom_weapon_priority_far;
-string autocvar_bot_ai_custom_weapon_priority_mid;
-float autocvar_bot_ai_dangerdetectioninterval;
-float autocvar_bot_ai_dangerdetectionupdates;
-float autocvar_bot_ai_enemydetectioninterval;
-float autocvar_bot_ai_enemydetectionradius;
-float autocvar_bot_ai_friends_aware_pickup_radius;
-float autocvar_bot_ai_ignoregoal_timeout;
-float autocvar_bot_ai_keyboard_distance;
-float autocvar_bot_ai_keyboard_threshold;
-float autocvar_bot_ai_navigation_jetpack;
-float autocvar_bot_ai_navigation_jetpack_mindistance;
 float autocvar_bot_ai_strategyinterval;
-float autocvar_bot_ai_thinkinterval;
-bool autocvar_bot_ai_weapon_combo;
-float autocvar_bot_ai_weapon_combo_threshold;
-string autocvar_bot_config_file;
-bool autocvar_bot_god;
-bool autocvar_bot_ignore_bots;
-bool autocvar_bot_join_empty;
-bool autocvar_bot_navigation_ignoreplayers;
-bool autocvar_bot_nofire;
 #define autocvar_bot_number cvar("bot_number")
-#define autocvar_bot_prefix cvar_string("bot_prefix")
-#define autocvar_bot_suffix cvar_string("bot_suffix")
-bool autocvar_bot_usemodelnames;
 int autocvar_bot_vs_human;
-bool autocvar_bot_debug_tracewalk;
-bool autocvar_bot_debug_goalstack;
-bool autocvar_bot_wander_enable;
 int autocvar_captureleadlimit_override;
 #define autocvar_capturelimit_override cvar("capturelimit_override")
 float autocvar_ekg;
@@ -172,7 +120,6 @@ float autocvar_g_chat_flood_spl_tell;
 int autocvar_g_chat_nospectators;
 bool autocvar_g_chat_teamcolors;
 bool autocvar_g_chat_tellprivacy;
-bool autocvar_g_debug_bot_commands;
 bool autocvar_g_forced_respawn;
 string autocvar_g_forced_team_blue;
 string autocvar_g_forced_team_otherwise;
@@ -296,7 +243,6 @@ float autocvar_g_turrets_targetscan_maxdelay;
 float autocvar_g_turrets_targetscan_mindelay;
 bool autocvar_g_use_ammunition;
 bool autocvar_g_waypointeditor;
-int autocvar_g_waypointeditor_auto;
 bool autocvar_g_waypoints_for_items;
 #define autocvar_g_weapon_stay cvar("g_weapon_stay")
 bool autocvar_g_weapon_throwable;
@@ -321,7 +267,6 @@ 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;
 int autocvar_spawn_debug;
@@ -429,7 +374,6 @@ float autocvar_timelimit_overtime;
 int autocvar_timelimit_overtimes;
 float autocvar_timelimit_suddendeath;
 #define autocvar_utf8_enable cvar("utf8_enable")
-bool autocvar_waypoint_benchmark;
 float autocvar_sv_gameplayfix_gravityunaffectedbyticrate;
 bool autocvar_sv_gameplayfix_upwardvelocityclearsongroundflag;
 float autocvar_g_trueaim_minrange;
@@ -574,3 +518,4 @@ float autocvar_sv_stopspeed;
 float autocvar_sv_airaccelerate;
 float autocvar_sv_airstopaccelerate;
 float autocvar_sv_track_canjump;
+bool autocvar_sv_showspectators;
index 787939110d9951f662439e926cd936a38b57dfb8..8f0672e2623074a3db074eb081ff4bb1c8617ca3 100644 (file)
@@ -1,6 +1,2 @@
 // generated file; do not modify
-#include <server/bot/aim.qc>
-#include <server/bot/bot.qc>
-#include <server/bot/navigation.qc>
-#include <server/bot/scripting.qc>
-#include <server/bot/waypoints.qc>
+#include <server/bot/api.qc>
index 802d39187818db60fd811789a83c585b1bcaae23..33f0b022911f943822c9b9a9c1ebc27f6e126c89 100644 (file)
@@ -1,6 +1,2 @@
 // generated file; do not modify
-#include <server/bot/aim.qh>
-#include <server/bot/bot.qh>
-#include <server/bot/navigation.qh>
-#include <server/bot/scripting.qh>
-#include <server/bot/waypoints.qh>
+#include <server/bot/api.qh>
diff --git a/qcsrc/server/bot/aim.qc b/qcsrc/server/bot/aim.qc
deleted file mode 100644 (file)
index b867b5f..0000000
+++ /dev/null
@@ -1,393 +0,0 @@
-#include "aim.qh"
-
-#include "bot.qh"
-
-#include <common/physics/player.qh>
-#include <common/state.qh>
-
-#include "../weapons/weaponsystem.qh"
-
-#include "../mutators/all.qh"
-
-// traces multiple trajectories to find one that will impact the target
-// 'end' vector is the place it aims for,
-// returns true only if it hit targ (don't target non-solid entities)
-
-float findtrajectorywithleading(vector org, vector m1, vector m2, entity targ, float shotspeed, float shotspeedupward, float maxtime, float shotdelay, entity ignore)
-{
-       float c, savesolid, shottime;
-       vector dir, end, v, o;
-       if (shotspeed < 1)
-               return false; // could cause division by zero if calculated
-       if (targ.solid < SOLID_BBOX) // SOLID_NOT and SOLID_TRIGGER
-               return false; // could never hit it
-       if (!tracetossent)
-               tracetossent = new(tracetossent);
-       tracetossent.owner = ignore;
-       setsize(tracetossent, m1, m2);
-       savesolid = targ.solid;
-       targ.solid = SOLID_NOT;
-       o = (targ.absmin + targ.absmax) * 0.5;
-       shottime = ((vlen(o - org) / shotspeed) + shotdelay);
-       v = targ.velocity * shottime + o;
-       tracebox(o, targ.mins, targ.maxs, v, false, targ);
-       v = trace_endpos;
-       end = v + (targ.mins + targ.maxs) * 0.5;
-       if ((vlen(end - org) / shotspeed + 0.2) > maxtime)
-       {
-               // out of range
-               targ.solid = savesolid;
-               return false;
-       }
-
-       if (!tracetossfaketarget)
-               tracetossfaketarget = new(tracetossfaketarget);
-       tracetossfaketarget.solid = savesolid;
-       set_movetype(tracetossfaketarget, targ.move_movetype);
-       _setmodel(tracetossfaketarget, targ.model); // no low precision
-       tracetossfaketarget.model = targ.model;
-       tracetossfaketarget.modelindex = targ.modelindex;
-       setsize(tracetossfaketarget, targ.mins, targ.maxs);
-       setorigin(tracetossfaketarget, v);
-
-       c = 0;
-       dir = normalize(end - org);
-       while (c < 10) // 10 traces
-       {
-               setorigin(tracetossent, org); // reset
-               tracetossent.velocity = findtrajectory_velocity = normalize(dir) * shotspeed + shotspeedupward * '0 0 1';
-               tracetoss(tracetossent, ignore); // love builtin functions...
-               if (trace_ent == tracetossfaketarget) // done
-               {
-                       targ.solid = savesolid;
-
-                       // make it disappear
-                       tracetossfaketarget.solid = SOLID_NOT;
-                       set_movetype(tracetossfaketarget, MOVETYPE_NONE);
-                       tracetossfaketarget.model = "";
-                       tracetossfaketarget.modelindex = 0;
-                       // relink to remove it from physics considerations
-                       setorigin(tracetossfaketarget, v);
-
-                       return true;
-               }
-               dir.z = dir.z + 0.1; // aim up a little more
-               c = c + 1;
-       }
-       targ.solid = savesolid;
-
-       // make it disappear
-       tracetossfaketarget.solid = SOLID_NOT;
-       set_movetype(tracetossfaketarget, MOVETYPE_NONE);
-       tracetossfaketarget.model = "";
-       tracetossfaketarget.modelindex = 0;
-       // relink to remove it from physics considerations
-       setorigin(tracetossfaketarget, v);
-
-       // leave a valid one even if it won't reach
-       findtrajectory_velocity = normalize(end - org) * shotspeed + shotspeedupward * '0 0 1';
-       return false;
-}
-
-void lag_update(entity this)
-{
-       if (this.lag1_time) if (time > this.lag1_time) {this.lag_func(this, this.lag1_time, this.lag1_float1, this.lag1_float2, this.lag1_entity1, this.lag1_vec1, this.lag1_vec2, this.lag1_vec3, this.lag1_vec4);this.lag1_time = 0;}
-       if (this.lag2_time) if (time > this.lag2_time) {this.lag_func(this, this.lag2_time, this.lag2_float1, this.lag2_float2, this.lag2_entity1, this.lag2_vec1, this.lag2_vec2, this.lag2_vec3, this.lag2_vec4);this.lag2_time = 0;}
-       if (this.lag3_time) if (time > this.lag3_time) {this.lag_func(this, this.lag3_time, this.lag3_float1, this.lag3_float2, this.lag3_entity1, this.lag3_vec1, this.lag3_vec2, this.lag3_vec3, this.lag3_vec4);this.lag3_time = 0;}
-       if (this.lag4_time) if (time > this.lag4_time) {this.lag_func(this, this.lag4_time, this.lag4_float1, this.lag4_float2, this.lag4_entity1, this.lag4_vec1, this.lag4_vec2, this.lag4_vec3, this.lag4_vec4);this.lag4_time = 0;}
-       if (this.lag5_time) if (time > this.lag5_time) {this.lag_func(this, this.lag5_time, this.lag5_float1, this.lag5_float2, this.lag5_entity1, this.lag5_vec1, this.lag5_vec2, this.lag5_vec3, this.lag5_vec4);this.lag5_time = 0;}
-}
-
-float lag_additem(entity this, float t, float f1, float f2, entity e1, vector v1, vector v2, vector v3, vector v4)
-{
-       if (this.lag1_time == 0) {this.lag1_time = t;this.lag1_float1 = f1;this.lag1_float2 = f2;this.lag1_entity1 = e1;this.lag1_vec1 = v1;this.lag1_vec2 = v2;this.lag1_vec3 = v3;this.lag1_vec4 = v4;return true;}
-       if (this.lag2_time == 0) {this.lag2_time = t;this.lag2_float1 = f1;this.lag2_float2 = f2;this.lag2_entity1 = e1;this.lag2_vec1 = v1;this.lag2_vec2 = v2;this.lag2_vec3 = v3;this.lag2_vec4 = v4;return true;}
-       if (this.lag3_time == 0) {this.lag3_time = t;this.lag3_float1 = f1;this.lag3_float2 = f2;this.lag3_entity1 = e1;this.lag3_vec1 = v1;this.lag3_vec2 = v2;this.lag3_vec3 = v3;this.lag3_vec4 = v4;return true;}
-       if (this.lag4_time == 0) {this.lag4_time = t;this.lag4_float1 = f1;this.lag4_float2 = f2;this.lag4_entity1 = e1;this.lag4_vec1 = v1;this.lag4_vec2 = v2;this.lag4_vec3 = v3;this.lag4_vec4 = v4;return true;}
-       if (this.lag5_time == 0) {this.lag5_time = t;this.lag5_float1 = f1;this.lag5_float2 = f2;this.lag5_entity1 = e1;this.lag5_vec1 = v1;this.lag5_vec2 = v2;this.lag5_vec3 = v3;this.lag5_vec4 = v4;return true;}
-       // no room for it (what is the best thing to do here??)
-       return false;
-}
-
-bool bot_shouldattack(entity this, entity targ)
-{
-       if (targ.team == this.team)
-       {
-               if (targ == this)
-                       return false;
-               if (teamplay)
-               if (targ.team != 0)
-                       return false;
-       }
-
-       if(STAT(FROZEN, targ))
-               return false;
-
-       if(teamplay)
-       {
-               if(targ.team==0)
-                       return false;
-       }
-       else if(bot_ignore_bots)
-               if(IS_BOT_CLIENT(targ))
-                       return false;
-
-       if (!targ.takedamage)
-               return false;
-       if (IS_DEAD(targ))
-               return false;
-       if (PHYS_INPUT_BUTTON_CHAT(targ))
-               return false;
-       if(targ.flags & FL_NOTARGET)
-               return false;
-
-       if(MUTATOR_CALLHOOK(BotShouldAttack, this, targ))
-               return false;
-
-       return true;
-}
-
-void bot_lagfunc(entity this, float t, float f1, float f2, entity e1, vector v1, vector v2, vector v3, vector v4)
-{
-       if(this.flags & FL_INWATER)
-       {
-               this.bot_aimtarg = NULL;
-               return;
-       }
-       this.bot_aimtarg = e1;
-       this.bot_aimlatency = this.ping; // FIXME?  Shouldn't this be in the lag item?
-       //this.bot_aimorigin = v1;
-       //this.bot_aimvelocity = v2;
-       this.bot_aimtargorigin = v3;
-       this.bot_aimtargvelocity = v4;
-       if(skill <= 0)
-               this.bot_canfire = (random() < 0.8);
-       else if(skill <= 1)
-               this.bot_canfire = (random() < 0.9);
-       else if(skill <= 2)
-               this.bot_canfire = (random() < 0.95);
-       else
-               this.bot_canfire = 1;
-}
-
-float bot_aimdir(entity this, vector v, float maxfiredeviation)
-{
-       float dist, delta_t, blend;
-       vector desiredang, diffang;
-
-       //dprint("aim ", this.netname, ": old:", vtos(this.v_angle));
-       // make sure v_angle is sane first
-       this.v_angle_y = this.v_angle.y - floor(this.v_angle.y / 360) * 360;
-       this.v_angle_z = 0;
-
-       // get the desired angles to aim at
-       //dprint(" at:", vtos(v));
-       v = normalize(v);
-       //te_lightning2(NULL, this.origin + this.view_ofs, this.origin + this.view_ofs + v * 200);
-       if (time >= this.bot_badaimtime)
-       {
-               this.bot_badaimtime = max(this.bot_badaimtime + 0.3, time);
-               this.bot_badaimoffset = randomvec() * bound(0, 5 - 0.5 * (skill+this.bot_offsetskill), 5) * autocvar_bot_ai_aimskill_offset;
-       }
-       desiredang = vectoangles(v) + this.bot_badaimoffset;
-       //dprint(" desired:", vtos(desiredang));
-       if (desiredang.x >= 180)
-               desiredang.x = desiredang.x - 360;
-       desiredang.x = bound(-90, 0 - desiredang.x, 90);
-       desiredang.z = this.v_angle.z;
-       //dprint(" / ", vtos(desiredang));
-
-       //// pain throws off aim
-       //if (this.bot_painintensity)
-       //{
-       //      // shake from pain
-       //      desiredang = desiredang + randomvec() * this.bot_painintensity * 0.2;
-       //}
-
-       // calculate turn angles
-       diffang = (desiredang - this.bot_olddesiredang);
-       // wrap yaw turn
-       diffang.y = diffang.y - floor(diffang.y / 360) * 360;
-       if (diffang.y >= 180)
-               diffang.y = diffang.y - 360;
-       this.bot_olddesiredang = desiredang;
-       //dprint(" diff:", vtos(diffang));
-
-       delta_t = time-this.bot_prevaimtime;
-       this.bot_prevaimtime = time;
-       // Here we will try to anticipate the comming aiming direction
-       this.bot_1st_order_aimfilter= this.bot_1st_order_aimfilter
-               + (diffang * (1 / delta_t)    - this.bot_1st_order_aimfilter) * bound(0, autocvar_bot_ai_aimskill_order_filter_1st,1);
-       this.bot_2nd_order_aimfilter= this.bot_2nd_order_aimfilter
-               + (this.bot_1st_order_aimfilter - this.bot_2nd_order_aimfilter) * bound(0, autocvar_bot_ai_aimskill_order_filter_2nd,1);
-       this.bot_3th_order_aimfilter= this.bot_3th_order_aimfilter
-               + (this.bot_2nd_order_aimfilter - this.bot_3th_order_aimfilter) * bound(0, autocvar_bot_ai_aimskill_order_filter_3th,1);
-       this.bot_4th_order_aimfilter= this.bot_4th_order_aimfilter
-               + (this.bot_3th_order_aimfilter - this.bot_4th_order_aimfilter) * bound(0, autocvar_bot_ai_aimskill_order_filter_4th,1);
-       this.bot_5th_order_aimfilter= this.bot_5th_order_aimfilter
-               + (this.bot_4th_order_aimfilter - this.bot_5th_order_aimfilter) * bound(0, autocvar_bot_ai_aimskill_order_filter_5th,1);
-
-       //blend = (bound(0,skill,10)*0.1)*pow(1-bound(0,skill,10)*0.05,2.5)*5.656854249; //Plot formule before changing !
-       blend = bound(0,skill+this.bot_aimskill,10)*0.1;
-       desiredang = desiredang + blend *
-       (
-                 this.bot_1st_order_aimfilter * autocvar_bot_ai_aimskill_order_mix_1st
-               + this.bot_2nd_order_aimfilter * autocvar_bot_ai_aimskill_order_mix_2nd
-               + this.bot_3th_order_aimfilter * autocvar_bot_ai_aimskill_order_mix_3th
-               + this.bot_4th_order_aimfilter * autocvar_bot_ai_aimskill_order_mix_4th
-               + this.bot_5th_order_aimfilter * autocvar_bot_ai_aimskill_order_mix_5th
-       );
-
-       // calculate turn angles
-       diffang = desiredang - this.bot_mouseaim;
-       // wrap yaw turn
-       diffang.y = diffang.y - floor(diffang.y / 360) * 360;
-       if (diffang.y >= 180)
-               diffang.y = diffang.y - 360;
-       //dprint(" diff:", vtos(diffang));
-
-       if (time >= this.bot_aimthinktime)
-       {
-               this.bot_aimthinktime = max(this.bot_aimthinktime + 0.5 - 0.05*(skill+this.bot_thinkskill), time);
-               this.bot_mouseaim = this.bot_mouseaim + diffang * (1-random()*0.1*bound(1,10-(skill+this.bot_thinkskill),10));
-       }
-
-       //this.v_angle = this.v_angle + diffang * bound(0, r * frametime * (skill * 0.5 + 2), 1);
-
-       diffang = this.bot_mouseaim - desiredang;
-       // wrap yaw turn
-       diffang.y = diffang.y - floor(diffang.y / 360) * 360;
-       if (diffang.y >= 180)
-               diffang.y = diffang.y - 360;
-       desiredang = desiredang + diffang * bound(0,autocvar_bot_ai_aimskill_think,1);
-
-       // calculate turn angles
-       diffang = desiredang - this.v_angle;
-       // wrap yaw turn
-       diffang.y = diffang.y - floor(diffang.y / 360) * 360;
-       if (diffang.y >= 180)
-               diffang.y = diffang.y - 360;
-       //dprint(" diff:", vtos(diffang));
-
-       // jitter tracking
-       dist = vlen(diffang);
-       //diffang = diffang + randomvec() * (dist * 0.05 * (3.5 - bound(0, skill, 3)));
-
-       // turn
-       float r, fixedrate, blendrate;
-       fixedrate = autocvar_bot_ai_aimskill_fixedrate / bound(1,dist,1000);
-       blendrate = autocvar_bot_ai_aimskill_blendrate;
-       r = max(fixedrate, blendrate);
-       //this.v_angle = this.v_angle + diffang * bound(frametime, r * frametime * (2+skill*skill*0.05-random()*0.05*(10-skill)), 1);
-       this.v_angle = this.v_angle + diffang * bound(delta_t, r * delta_t * (2+pow(skill+this.bot_mouseskill,3)*0.005-random()), 1);
-       this.v_angle = this.v_angle * bound(0,autocvar_bot_ai_aimskill_mouse,1) + desiredang * bound(0,(1-autocvar_bot_ai_aimskill_mouse),1);
-       //this.v_angle = this.v_angle + diffang * bound(0, r * frametime * (skill * 0.5 + 2), 1);
-       //this.v_angle = this.v_angle + diffang * (1/ blendrate);
-       this.v_angle_z = 0;
-       this.v_angle_y = this.v_angle.y - floor(this.v_angle.y / 360) * 360;
-       //dprint(" turn:", vtos(this.v_angle));
-
-       makevectors(this.v_angle);
-       shotorg = this.origin + this.view_ofs;
-       shotdir = v_forward;
-
-       //dprint(" dir:", vtos(v_forward));
-       //te_lightning2(NULL, shotorg, shotorg + shotdir * 100);
-
-       // calculate turn angles again
-       //diffang = desiredang - this.v_angle;
-       //diffang_y = diffang_y - floor(diffang_y / 360) * 360;
-       //if (diffang_y >= 180)
-       //      diffang_y = diffang_y - 360;
-
-       //dprint("e ", vtos(diffang), " < ", ftos(maxfiredeviation), "\n");
-
-       // decide whether to fire this time
-       // note the maxfiredeviation is in degrees so this has to convert to radians first
-       //if ((normalize(v) * shotdir) >= cos(maxfiredeviation * (3.14159265358979323846 / 180)))
-       if ((normalize(v) * shotdir) >= cos(maxfiredeviation * (3.14159265358979323846 / 180)))
-       if(vdist(trace_endpos-shotorg, <, 500 + 500 * bound(0, skill + this.bot_aggresskill, 10)) || random()*random()>bound(0,(skill+this.bot_aggresskill)*0.05,1))
-               this.bot_firetimer = time + bound(0.1, 0.5-(skill+this.bot_aggresskill)*0.05, 0.5);
-       //traceline(shotorg,shotorg+shotdir*1000,false,NULL);
-       //dprint(ftos(maxfiredeviation),"\n");
-       //dprint(" diff:", vtos(diffang), "\n");
-
-       return this.bot_canfire && (time < this.bot_firetimer);
-}
-
-vector bot_shotlead(vector targorigin, vector targvelocity, float shotspeed, float shotdelay)
-{
-       // Try to add code here that predicts gravity effect here, no clue HOW to though ... well not yet atleast...
-       return targorigin + targvelocity * (shotdelay + vlen(targorigin - shotorg) / shotspeed);
-}
-
-bool bot_aim(entity this, float shotspeed, float shotspeedupward, float maxshottime, bool applygravity)
-{
-       float f, r, hf, distanceratio;
-       vector v;
-       /*
-       eprint(this);
-       dprint("bot_aim(", ftos(shotspeed));
-       dprint(", ", ftos(shotspeedupward));
-       dprint(", ", ftos(maxshottime));
-       dprint(", ", ftos(applygravity));
-       dprint(");\n");
-       */
-
-       hf = this.dphitcontentsmask;
-       this.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_CORPSE;
-
-       shotspeed *= W_WeaponSpeedFactor(this);
-       shotspeedupward *= W_WeaponSpeedFactor(this);
-       if (!shotspeed)
-       {
-               LOG_TRACE("bot_aim: WARNING: weapon ", PS(this).m_weapon.m_name, " shotspeed is zero!\n");
-               shotspeed = 1000000;
-       }
-       if (!maxshottime)
-       {
-               LOG_TRACE("bot_aim: WARNING: weapon ", PS(this).m_weapon.m_name, " maxshottime is zero!\n");
-               maxshottime = 1;
-       }
-       makevectors(this.v_angle);
-       shotorg = this.origin + this.view_ofs;
-       shotdir = v_forward;
-       v = bot_shotlead(this.bot_aimtargorigin, this.bot_aimtargvelocity, shotspeed, this.bot_aimlatency);
-       distanceratio = sqrt(bound(0,skill,10000))*0.3*(vlen(v-shotorg)-100)/autocvar_bot_ai_aimskill_firetolerance_distdegrees;
-       distanceratio = bound(0,distanceratio,1);
-       r =  (autocvar_bot_ai_aimskill_firetolerance_maxdegrees-autocvar_bot_ai_aimskill_firetolerance_mindegrees)
-               * (1-distanceratio) + autocvar_bot_ai_aimskill_firetolerance_mindegrees;
-       if (applygravity && this.bot_aimtarg)
-       {
-               if (!findtrajectorywithleading(shotorg, '0 0 0', '0 0 0', this.bot_aimtarg, shotspeed, shotspeedupward, maxshottime, 0, this))
-               {
-                       this.dphitcontentsmask = hf;
-                       return false;
-               }
-
-               f = bot_aimdir(this, findtrajectory_velocity - shotspeedupward * '0 0 1', r);
-       }
-       else
-       {
-               f = bot_aimdir(this, v - shotorg, r);
-               //dprint("AIM: ");dprint(vtos(this.bot_aimtargorigin));dprint(" + ");dprint(vtos(this.bot_aimtargvelocity));dprint(" * ");dprint(ftos(this.bot_aimlatency + vlen(this.bot_aimtargorigin - shotorg) / shotspeed));dprint(" = ");dprint(vtos(v));dprint(" : aimdir = ");dprint(vtos(normalize(v - shotorg)));dprint(" : ");dprint(vtos(shotdir));dprint("\n");
-               //traceline(shotorg, shotorg + shotdir * 10000, false, this);
-               //if (trace_ent.takedamage)
-               //if (trace_fraction < 1)
-               //if (!bot_shouldattack(this, trace_ent))
-               //      return false;
-               traceline(shotorg, this.bot_aimtargorigin, false, this);
-               if (trace_fraction < 1)
-               if (trace_ent != this.enemy)
-               if (!bot_shouldattack(this, trace_ent))
-               {
-                       this.dphitcontentsmask = hf;
-                       return false;
-               }
-       }
-
-       //if (r > maxshottime * shotspeed)
-       //      return false;
-       this.dphitcontentsmask = hf;
-       return true;
-}
diff --git a/qcsrc/server/bot/aim.qh b/qcsrc/server/bot/aim.qh
deleted file mode 100644 (file)
index dfe10e2..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-#pragma once
-/*
- * Globals and Fields
- */
-
-entity tracetossent;
-entity tracetossfaketarget;
-vector findtrajectory_velocity;
-
-
-
-vector shotorg;
-vector shotdir;
-
-// lag simulation
-// upto 5 queued messages
-.float lag1_time;
-.float lag1_float1;
-.float lag1_float2;
-.entity lag1_entity1;
-.vector lag1_vec1;
-.vector lag1_vec2;
-.vector lag1_vec3;
-.vector lag1_vec4;
-
-.float lag2_time;
-.float lag2_float1;
-.float lag2_float2;
-.entity lag2_entity1;
-.vector lag2_vec1;
-.vector lag2_vec2;
-.vector lag2_vec3;
-.vector lag2_vec4;
-
-.float lag3_time;
-.float lag3_float1;
-.float lag3_float2;
-.entity lag3_entity1;
-.vector lag3_vec1;
-.vector lag3_vec2;
-.vector lag3_vec3;
-.vector lag3_vec4;
-
-.float lag4_time;
-.float lag4_float1;
-.float lag4_float2;
-.entity lag4_entity1;
-.vector lag4_vec1;
-.vector lag4_vec2;
-.vector lag4_vec3;
-.vector lag4_vec4;
-
-.float lag5_time;
-.float lag5_float1;
-.float lag5_float2;
-.entity lag5_entity1;
-.vector lag5_vec1;
-.vector lag5_vec2;
-.vector lag5_vec3;
-.vector lag5_vec4;
-
-.float bot_badaimtime;
-.float bot_aimthinktime;
-.float bot_prevaimtime;
-.float bot_firetimer;
-.float bot_aimlatency;
-
-.vector bot_mouseaim;
-.vector bot_badaimoffset;
-.vector bot_1st_order_aimfilter;
-.vector bot_2nd_order_aimfilter;
-.vector bot_3th_order_aimfilter;
-.vector bot_4th_order_aimfilter;
-.vector bot_5th_order_aimfilter;
-.vector bot_olddesiredang;
-
-//.vector bot_aimorigin;
-//.vector bot_aimvelocity;
-.vector bot_aimtargorigin;
-.vector bot_aimtargvelocity;
-
-.entity bot_aimtarg;
-
-/*
- * Functions
- */
-
-float lag_additem(entity this, float t, float f1, float f2, entity e1, vector v1, vector v2, vector v3, vector v4);
-void lag_update(entity this);
-void bot_lagfunc(entity this, float t, float f1, float f2, entity e1, vector v1, vector v2, vector v3, vector v4);
-
-float bot_shouldattack(entity this, entity targ);
-float bot_aimdir(entity this, vector v, float maxfiredeviation);
-bool bot_aim(entity this, float shotspeed, float shotspeedupward, float maxshottime, bool applygravity);
-float findtrajectorywithleading(vector org, vector m1, vector m2, entity targ, float shotspeed, float shotspeedupward, float maxtime, float shotdelay, entity ignore);
-
-vector bot_shotlead(vector targorigin, vector targvelocity, float shotspeed, float shotdelay);
-
-.void(entity this, float t, float f1, float f2, entity e1, vector v1, vector v2, vector v3, vector v4) lag_func;
diff --git a/qcsrc/server/bot/api.qc b/qcsrc/server/bot/api.qc
new file mode 100644 (file)
index 0000000..85b0e46
--- /dev/null
@@ -0,0 +1,49 @@
+#include "api.qh"
+
+#if 1
+
+#include "default/_mod.inc"
+#include "default/havocbot/_mod.inc"
+
+#else
+
+bool bot_aim(entity this, float shotspeed, float shotspeedupward, float maxshottime, float applygravity) { return false; }
+void bot_clientconnect(entity this) { }
+void bot_clientdisconnect(entity this) { }
+void bot_cmdhelp(string scmd) { }
+void bot_endgame() { }
+bool bot_fixcount() { return true; }
+void bot_list_commands() { }
+void bot_queuecommand(entity bot, string cmdstring) { }
+void bot_relinkplayerlist() { }
+void bot_resetqueues() { }
+void bot_serverframe() { }
+bool bot_shouldattack(entity this, entity e) { return false; }
+void bot_think(entity this) { }
+
+entity find_bot_by_name(string name) { return NULL; }
+entity find_bot_by_number(float number) { return NULL; }
+
+void havocbot_goalrating_controlpoints(entity this, float ratingscale, vector org, float sradius) { }
+void havocbot_goalrating_enemyplayers(entity this, float ratingscale, vector org, float sradius) { }
+void havocbot_goalrating_items(entity this, float ratingscale, vector org, float sradius) { }
+
+entity navigation_findnearestwaypoint(entity ent, float walkfromwp) { return NULL; }
+void navigation_goalrating_end(entity this) { }
+void navigation_goalrating_start(entity this) { }
+void navigation_markroutes(entity this, entity fixed_source_waypoint) { }
+void navigation_markroutes_inverted(entity fixed_source_waypoint) { }
+void navigation_routerating(entity this, entity e, float f, float rangebias) { }
+
+bool tracewalk(entity e, vector start, vector m1, vector m2, vector end, float movemode) { return false; }
+
+void waypoint_remove(entity e) { }
+void waypoint_saveall() { }
+void waypoint_schedulerelinkall() { }
+void waypoint_schedulerelink(entity wp) { }
+void waypoint_spawnforitem(entity e) { }
+void waypoint_spawnforitem_force(entity e, vector org) { }
+void waypoint_spawnforteleporter(entity e, vector destination, float timetaken) { }
+void waypoint_spawnforteleporter_v(entity e, vector org, vector destination, float timetaken) { }
+entity waypoint_spawn(vector m1, vector m2, float f) { return NULL; }
+#endif
diff --git a/qcsrc/server/bot/api.qh b/qcsrc/server/bot/api.qh
new file mode 100644 (file)
index 0000000..9c52589
--- /dev/null
@@ -0,0 +1,87 @@
+#pragma once
+
+#include <common/weapons/all.qh>
+
+const int WAYPOINTFLAG_GENERATED = BIT(23);
+const int WAYPOINTFLAG_ITEM = BIT(22);
+const int WAYPOINTFLAG_TELEPORT = BIT(21);
+const int WAYPOINTFLAG_NORELINK = BIT(20);
+const int WAYPOINTFLAG_PERSONAL = BIT(19);
+const int WAYPOINTFLAG_PROTECTED = BIT(18);  // Useless WP detection never kills these.
+const int WAYPOINTFLAG_USEFUL = BIT(17);  // Useless WP detection temporary flag.
+const int WAYPOINTFLAG_DEAD_END = BIT(16);  // Useless WP detection temporary flag.
+
+entity kh_worldkeylist;
+.entity kh_worldkeynext;
+
+float bot_custom_weapon;
+float bot_weapons_close[Weapons_MAX];
+float bot_weapons_far[Weapons_MAX];
+float bot_weapons_mid[Weapons_MAX];
+float skill;
+
+.float bot_attack;
+.float bot_dodgerating;
+.float bot_dodge;
+.float bot_forced_team;
+.float bot_moveskill; // moving technique
+.float bot_pickup;
+.float(entity player, entity item) bot_pickupevalfunc;
+.float bot_strategytime;
+.string cleanname;
+.float havocbot_role_timeout;
+.float isbot; // true if this client is actually a bot
+.float lastteleporttime;
+.float navigation_hasgoals;
+.float nearestwaypointtimeout;
+.entity nearestwaypoint;
+.float speed;
+.entity wp00, wp01, wp02, wp03, wp04, wp05, wp06, wp07, wp08, wp09, wp10, wp11, wp12, wp13, wp14, wp15;
+.entity wp16, wp17, wp18, wp19, wp20, wp21, wp22, wp23, wp24, wp25, wp26, wp27, wp28, wp29, wp30, wp31;
+.float wp00mincost, wp01mincost, wp02mincost, wp03mincost, wp04mincost, wp05mincost, wp06mincost, wp07mincost;
+.float wp08mincost, wp09mincost, wp10mincost, wp11mincost, wp12mincost, wp13mincost, wp14mincost, wp15mincost;
+.float wp16mincost, wp17mincost, wp18mincost, wp19mincost, wp20mincost, wp21mincost, wp22mincost, wp23mincost;
+.float wp24mincost, wp25mincost, wp26mincost, wp27mincost, wp28mincost, wp29mincost, wp30mincost, wp31mincost;
+.float wpconsidered;
+.float wpcost;
+.int wpflags;
+
+bool bot_aim(entity this, float shotspeed, float shotspeedupward, float maxshottime, float applygravity);
+void bot_clientconnect(entity this);
+void bot_clientdisconnect(entity this);
+void bot_cmdhelp(string scmd);
+void bot_endgame();
+bool bot_fixcount();
+void bot_list_commands();
+void bot_queuecommand(entity bot, string cmdstring);
+void bot_relinkplayerlist();
+void bot_resetqueues();
+void bot_serverframe();
+bool bot_shouldattack(entity this, entity e);
+void bot_think(entity this);
+
+entity find_bot_by_name(string name);
+entity find_bot_by_number(float number);
+
+void havocbot_goalrating_controlpoints(entity this, float ratingscale, vector org, float sradius);
+void havocbot_goalrating_enemyplayers(entity this, float ratingscale, vector org, float sradius);
+void havocbot_goalrating_items(entity this, float ratingscale, vector org, float sradius);
+
+entity navigation_findnearestwaypoint(entity ent, float walkfromwp);
+void navigation_goalrating_end(entity this);
+void navigation_goalrating_start(entity this);
+void navigation_markroutes(entity this, entity fixed_source_waypoint);
+void navigation_markroutes_inverted(entity fixed_source_waypoint);
+void navigation_routerating(entity this, entity e, float f, float rangebias);
+
+bool tracewalk(entity e, vector start, vector m1, vector m2, vector end, float movemode);
+
+void waypoint_remove(entity e);
+void waypoint_saveall();
+void waypoint_schedulerelinkall();
+void waypoint_schedulerelink(entity wp);
+void waypoint_spawnforitem(entity e);
+void waypoint_spawnforitem_force(entity e, vector org);
+void waypoint_spawnforteleporter(entity e, vector destination, float timetaken);
+void waypoint_spawnforteleporter_v(entity e, vector org, vector destination, float timetaken);
+entity waypoint_spawn(vector m1, vector m2, float f);
diff --git a/qcsrc/server/bot/bot.qc b/qcsrc/server/bot/bot.qc
deleted file mode 100644 (file)
index 308cd95..0000000
+++ /dev/null
@@ -1,725 +0,0 @@
-#include "bot.qh"
-
-#include "aim.qh"
-#include "navigation.qh"
-#include "scripting.qh"
-#include "waypoints.qh"
-
-#include "havocbot/havocbot.qh"
-#include "havocbot/scripting.qh"
-
-#include "../teamplay.qh"
-
-#include "../antilag.qh"
-#include "../autocvars.qh"
-#include "../campaign.qh"
-#include "../cl_client.qh"
-#include "../constants.qh"
-#include "../defs.qh"
-#include "../race.qh"
-#include <common/t_items.qh>
-
-#include "../mutators/all.qh"
-
-#include "../weapons/accuracy.qh"
-
-#include <common/physics/player.qh>
-#include <common/constants.qh>
-#include <common/mapinfo.qh>
-#include <common/teams.qh>
-#include <common/util.qh>
-
-#include <common/weapons/all.qh>
-
-#include <lib/csqcmodel/sv_model.qh>
-
-#include <lib/warpzone/common.qh>
-#include <lib/warpzone/util_server.qh>
-
-entity bot_spawn()
-{
-       entity bot = spawnclient();
-       if (bot)
-       {
-               currentbots = currentbots + 1;
-               bot_setnameandstuff(bot);
-               ClientConnect(bot);
-               PutClientInServer(bot);
-       }
-       return bot;
-}
-
-void bot_think(entity this)
-{
-       if (this.bot_nextthink > time)
-               return;
-
-       this.flags &= ~FL_GODMODE;
-       if(autocvar_bot_god)
-               this.flags |= FL_GODMODE;
-
-       this.bot_nextthink = this.bot_nextthink + autocvar_bot_ai_thinkinterval * pow(0.5, this.bot_aiskill);
-       //if (this.bot_painintensity > 0)
-       //      this.bot_painintensity = this.bot_painintensity - (skill + 1) * 40 * frametime;
-
-       //this.bot_painintensity = this.bot_painintensity + this.bot_oldhealth - this.health;
-       //this.bot_painintensity = bound(0, this.bot_painintensity, 100);
-
-       if (!IS_PLAYER(this) || (autocvar_g_campaign && !campaign_bots_may_start))
-       {
-               this.bot_nextthink = time + 0.5;
-               return;
-       }
-
-       if (this.fixangle)
-       {
-               this.v_angle = this.angles;
-               this.v_angle_z = 0;
-               this.fixangle = false;
-       }
-
-       this.dmg_take = 0;
-       this.dmg_save = 0;
-       this.dmg_inflictor = NULL;
-
-       // calculate an aiming latency based on the skill setting
-       // (simulated network latency + naturally delayed reflexes)
-       //this.ping = 0.7 - bound(0, 0.05 * skill, 0.5); // moved the reflexes to bot_aimdir (under the name 'think')
-       // minimum ping 20+10 random
-       this.ping = bound(0,0.07 - bound(0, (skill + this.bot_pingskill) * 0.005,0.05)+random()*0.01,0.65); // Now holds real lag to server, and higer skill players take a less laggy server
-       // skill 10 = ping 0.2 (adrenaline)
-       // skill 0 = ping 0.7 (slightly drunk)
-
-       // clear buttons
-       PHYS_INPUT_BUTTON_ATCK(this) = false;
-       PHYS_INPUT_BUTTON_JUMP(this) = false;
-       PHYS_INPUT_BUTTON_ATCK2(this) = false;
-       PHYS_INPUT_BUTTON_ZOOM(this) = false;
-       PHYS_INPUT_BUTTON_CROUCH(this) = false;
-       PHYS_INPUT_BUTTON_HOOK(this) = false;
-       PHYS_INPUT_BUTTON_INFO(this) = false;
-       PHYS_INPUT_BUTTON_DRAG(this) = false;
-       PHYS_INPUT_BUTTON_CHAT(this) = false;
-       PHYS_INPUT_BUTTON_USE(this) = false;
-
-       if (time < game_starttime)
-       {
-               // block the bot during the countdown to game start
-               this.movement = '0 0 0';
-               this.bot_nextthink = game_starttime;
-               return;
-       }
-
-       // if dead, just wait until we can respawn
-       if (IS_DEAD(this))
-       {
-               if (this.deadflag == DEAD_DEAD)
-               {
-                       PHYS_INPUT_BUTTON_JUMP(this) = true; // press jump to respawn
-                       this.bot_strategytime = 0;
-               }
-       }
-       else if(this.aistatus & AI_STATUS_STUCK)
-               navigation_unstuck(this);
-
-       // now call the current bot AI (havocbot for example)
-       this.bot_ai(this);
-}
-
-void bot_setnameandstuff(entity this)
-{
-       string readfile, s;
-       float file, tokens, prio;
-
-       string bot_name, bot_model, bot_skin, bot_shirt, bot_pants;
-       string name, prefix, suffix;
-
-       if(autocvar_g_campaign)
-       {
-               prefix = "";
-               suffix = "";
-       }
-       else
-       {
-               prefix = autocvar_bot_prefix;
-               suffix = autocvar_bot_suffix;
-       }
-
-       file = fopen(autocvar_bot_config_file, FILE_READ);
-
-       if(file < 0)
-       {
-               LOG_INFO(strcat("Error: Can not open the bot configuration file '",autocvar_bot_config_file,"'\n"));
-               readfile = "";
-       }
-       else
-       {
-               RandomSelection_Init();
-               while((readfile = fgets(file)))
-               {
-                       if(substring(readfile, 0, 2) == "//")
-                               continue;
-                       if(substring(readfile, 0, 1) == "#")
-                               continue;
-                       tokens = tokenizebyseparator(readfile, "\t");
-                       if(tokens == 0)
-                               continue;
-                       s = argv(0);
-                       prio = 1;
-                       FOREACH_CLIENT(IS_BOT_CLIENT(it), LAMBDA(
-                               if(s == it.cleanname)
-                               {
-                                       prio = 0;
-                                       break;
-                               }
-                       ));
-                       RandomSelection_Add(NULL, 0, readfile, 1, prio);
-               }
-               readfile = RandomSelection_chosen_string;
-               fclose(file);
-       }
-
-       tokens = tokenizebyseparator(readfile, "\t");
-       if(argv(0) != "") bot_name = argv(0);
-       else bot_name = "Bot";
-
-       if(argv(1) != "") bot_model = argv(1);
-       else bot_model = "";
-
-       if(argv(2) != "") bot_skin = argv(2);
-       else bot_skin = "0";
-
-       if(argv(3) != "" && stof(argv(3)) >= 0) bot_shirt = argv(3);
-       else bot_shirt = ftos(floor(random() * 15));
-
-       if(argv(4) != "" && stof(argv(4)) >= 0) bot_pants = argv(4);
-       else bot_pants = ftos(floor(random() * 15));
-
-       this.bot_forced_team = stof(argv(5));
-
-       prio = 6;
-
-       #define READSKILL(f,w,r) if(argv(prio) != "") this.f = stof(argv(prio)) * (w); else this.f = (!autocvar_g_campaign) * (2 * random() - 1) * (r) * (w); ++prio
-       //print(bot_name, ": ping=", argv(9), "\n");
-
-       READSKILL(havocbot_keyboardskill, 0.5, 0.5); // keyboard skill
-       READSKILL(bot_moveskill, 2, 0); // move skill
-       READSKILL(bot_dodgeskill, 2, 0); // dodge skill
-
-       READSKILL(bot_pingskill, 0.5, 0); // ping skill
-
-       READSKILL(bot_weaponskill, 2, 0); // weapon skill
-       READSKILL(bot_aggresskill, 1, 0); // aggre skill
-       READSKILL(bot_rangepreference, 1, 0); // read skill
-
-       READSKILL(bot_aimskill, 2, 0); // aim skill
-       READSKILL(bot_offsetskill, 2, 0.5); // offset skill
-       READSKILL(bot_mouseskill, 1, 0.5); // mouse skill
-
-       READSKILL(bot_thinkskill, 1, 0.5); // think skill
-       READSKILL(bot_aiskill, 2, 0); // "ai" skill
-
-       this.bot_config_loaded = true;
-
-       // this is really only a default, JoinBestTeam is called later
-       setcolor(this, stof(bot_shirt) * 16 + stof(bot_pants));
-       this.bot_preferredcolors = this.clientcolors;
-
-       // pick the name
-       if (autocvar_bot_usemodelnames)
-               name = bot_model;
-       else
-               name = bot_name;
-
-       // number bots with identical names
-       int j = 0;
-       FOREACH_CLIENT(IS_BOT_CLIENT(it), LAMBDA(
-               if(it.cleanname == name)
-                       ++j;
-       ));
-       if (j)
-               this.netname = this.netname_freeme = strzone(strcat(prefix, name, "(", ftos(j), ")", suffix));
-       else
-               this.netname = this.netname_freeme = strzone(strcat(prefix, name, suffix));
-
-       this.cleanname = strzone(name);
-
-       // pick the model and skin
-       if(substring(bot_model, -4, 1) != ".")
-               bot_model = strcat(bot_model, ".iqm");
-       this.playermodel = this.playermodel_freeme = strzone(strcat("models/player/", bot_model));
-       this.playerskin = this.playerskin_freeme = strzone(bot_skin);
-
-       this.cvar_cl_accuracy_data_share = 1;  // share the bots weapon accuracy data with the NULL
-       this.cvar_cl_accuracy_data_receive = 0;  // don't receive any weapon accuracy data
-}
-
-void bot_custom_weapon_priority_setup()
-{
-       float tokens, i, w;
-
-       bot_custom_weapon = false;
-
-       if(     autocvar_bot_ai_custom_weapon_priority_far == "" ||
-               autocvar_bot_ai_custom_weapon_priority_mid == "" ||
-               autocvar_bot_ai_custom_weapon_priority_close == "" ||
-               autocvar_bot_ai_custom_weapon_priority_distances == ""
-       )
-               return;
-
-       // Parse distances
-       tokens = tokenizebyseparator(autocvar_bot_ai_custom_weapon_priority_distances," ");
-
-       if (tokens!=2)
-               return;
-
-       bot_distance_far = stof(argv(0));
-       bot_distance_close = stof(argv(1));
-
-       if(bot_distance_far < bot_distance_close){
-               bot_distance_far = stof(argv(1));
-               bot_distance_close = stof(argv(0));
-       }
-
-       // Initialize list of weapons
-       bot_weapons_far[0] = -1;
-       bot_weapons_mid[0] = -1;
-       bot_weapons_close[0] = -1;
-
-       // Parse far distance weapon priorities
-       tokens = tokenizebyseparator(W_NumberWeaponOrder(autocvar_bot_ai_custom_weapon_priority_far)," ");
-
-       int c = 0;
-       for(i=0; i < tokens && c < Weapons_COUNT; ++i){
-               w = stof(argv(i));
-               if ( w >= WEP_FIRST && w <= WEP_LAST) {
-                       bot_weapons_far[c] = w;
-                       ++c;
-               }
-       }
-       if(c < Weapons_COUNT)
-               bot_weapons_far[c] = -1;
-
-       // Parse mid distance weapon priorities
-       tokens = tokenizebyseparator(W_NumberWeaponOrder(autocvar_bot_ai_custom_weapon_priority_mid)," ");
-
-       c = 0;
-       for(i=0; i < tokens && c < Weapons_COUNT; ++i){
-               w = stof(argv(i));
-               if ( w >= WEP_FIRST && w <= WEP_LAST) {
-                       bot_weapons_mid[c] = w;
-                       ++c;
-               }
-       }
-       if(c < Weapons_COUNT)
-               bot_weapons_mid[c] = -1;
-
-       // Parse close distance weapon priorities
-       tokens = tokenizebyseparator(W_NumberWeaponOrder(autocvar_bot_ai_custom_weapon_priority_close)," ");
-
-       c = 0;
-       for(i=0; i < tokens && i < Weapons_COUNT; ++i){
-               w = stof(argv(i));
-               if ( w >= WEP_FIRST && w <= WEP_LAST) {
-                       bot_weapons_close[c] = w;
-                       ++c;
-               }
-       }
-       if(c < Weapons_COUNT)
-               bot_weapons_close[c] = -1;
-
-       bot_custom_weapon = true;
-}
-
-void bot_endgame()
-{
-       entity e;
-       //dprint("bot_endgame\n");
-       e = bot_list;
-       while (e)
-       {
-               setcolor(e, e.bot_preferredcolors);
-               e = e.nextbot;
-       }
-       // if dynamic waypoints are ever implemented, save them here
-}
-
-void bot_relinkplayerlist()
-{
-       player_count = 0;
-       currentbots = 0;
-       bot_list = NULL;
-
-       entity prevbot = NULL;
-       FOREACH_CLIENT(true,
-       {
-               ++player_count;
-
-               if(IS_BOT_CLIENT(it))
-               {
-                       if(prevbot)
-                               prevbot.nextbot = it;
-                       else
-                       {
-                               bot_list = it;
-                               bot_list.nextbot = NULL;
-                       }
-                       prevbot = it;
-                       ++currentbots;
-               }
-       });
-       LOG_TRACE(strcat("relink: ", ftos(currentbots), " bots seen.\n"));
-       bot_strategytoken = bot_list;
-       bot_strategytoken_taken = true;
-}
-
-void bot_clientdisconnect(entity this)
-{
-       if (!IS_BOT_CLIENT(this))
-               return;
-       bot_clearqueue(this);
-       if(this.cleanname)
-               strunzone(this.cleanname);
-       if(this.netname_freeme)
-               strunzone(this.netname_freeme);
-       if(this.playermodel_freeme)
-               strunzone(this.playermodel_freeme);
-       if(this.playerskin_freeme)
-               strunzone(this.playerskin_freeme);
-       this.cleanname = string_null;
-       this.netname_freeme = string_null;
-       this.playermodel_freeme = string_null;
-       this.playerskin_freeme = string_null;
-       if(this.bot_cmd_current)
-               remove(this.bot_cmd_current);
-       if(bot_waypoint_queue_owner==this)
-               bot_waypoint_queue_owner = NULL;
-}
-
-void bot_clientconnect(entity this)
-{
-       if (!IS_BOT_CLIENT(this)) return;
-       this.bot_preferredcolors = this.clientcolors;
-       this.bot_nextthink = time - random();
-       this.lag_func = bot_lagfunc;
-       this.isbot = true;
-       this.createdtime = this.bot_nextthink;
-
-       if(!this.bot_config_loaded) // This is needed so team overrider doesn't break between matches
-               bot_setnameandstuff(this);
-
-       if(this.bot_forced_team==1)
-               this.team = NUM_TEAM_1;
-       else if(this.bot_forced_team==2)
-               this.team = NUM_TEAM_2;
-       else if(this.bot_forced_team==3)
-               this.team = NUM_TEAM_3;
-       else if(this.bot_forced_team==4)
-               this.team = NUM_TEAM_4;
-       else
-               JoinBestTeam(this, false, true);
-
-       havocbot_setupbot(this);
-}
-
-void bot_removefromlargestteam()
-{
-       CheckAllowedTeams(NULL);
-       GetTeamCounts(NULL);
-
-       entity best = NULL;
-       float besttime = 0;
-       int bestcount = 0;
-
-       int bcount = 0;
-       FOREACH_ENTITY_FLOAT(isbot, true,
-       {
-               ++bcount;
-
-               if(!best)
-               {
-                       best = it;
-                       besttime = it.createdtime;
-               }
-
-               int thiscount = 0;
-
-               switch(it.team)
-               {
-                       case NUM_TEAM_1: thiscount = c1; break;
-                       case NUM_TEAM_2: thiscount = c2; break;
-                       case NUM_TEAM_3: thiscount = c3; break;
-                       case NUM_TEAM_4: thiscount = c4; break;
-               }
-
-               if(thiscount > bestcount)
-               {
-                       bestcount = thiscount;
-                       besttime = it.createdtime;
-                       best = it;
-               }
-               else if(thiscount == bestcount && besttime < it.createdtime)
-               {
-                       besttime = it.createdtime;
-                       best = it;
-               }
-       });
-       if(!bcount)
-               return; // no bots to remove
-       currentbots = currentbots - 1;
-       dropclient(best);
-}
-
-void bot_removenewest()
-{
-       if(teamplay)
-       {
-               bot_removefromlargestteam();
-               return;
-       }
-
-       float besttime = 0;
-       entity best = NULL;
-       int bcount = 0;
-
-       FOREACH_ENTITY_FLOAT(isbot, true,
-       {
-               ++bcount;
-
-               if(!best)
-               {
-                       best = it;
-                       besttime = it.createdtime;
-               }
-
-               if(besttime < it.createdtime)
-               {
-                       besttime = it.createdtime;
-                       best = it;
-               }
-       });
-
-       if(!bcount)
-               return; // no bots to remove
-
-       currentbots = currentbots - 1;
-       dropclient(best);
-}
-
-void autoskill(float factor)
-{
-       float bestbot;
-       float bestplayer;
-
-       bestbot = -1;
-       bestplayer = -1;
-       FOREACH_CLIENT(IS_PLAYER(it), LAMBDA(
-               if(IS_REAL_CLIENT(it))
-                       bestplayer = max(bestplayer, it.totalfrags - it.totalfrags_lastcheck);
-               else
-                       bestbot = max(bestbot, it.totalfrags - it.totalfrags_lastcheck);
-       ));
-
-       LOG_TRACE("autoskill: best player got ", ftos(bestplayer), ", ");
-       LOG_TRACE("best bot got ", ftos(bestbot), "; ");
-       if(bestbot < 0 || bestplayer < 0)
-       {
-               LOG_TRACE("not doing anything\n");
-               // don't return, let it reset all counters below
-       }
-       else if(bestbot <= bestplayer * factor - 2)
-       {
-               if(autocvar_skill < 17)
-               {
-                       LOG_TRACE("2 frags difference, increasing skill\n");
-                       cvar_set("skill", ftos(autocvar_skill + 1));
-                       bprint("^2SKILL UP!^7 Now at level ", ftos(autocvar_skill), "\n");
-               }
-       }
-       else if(bestbot >= bestplayer * factor + 2)
-       {
-               if(autocvar_skill > 0)
-               {
-                       LOG_TRACE("2 frags difference, decreasing skill\n");
-                       cvar_set("skill", ftos(autocvar_skill - 1));
-                       bprint("^1SKILL DOWN!^7 Now at level ", ftos(autocvar_skill), "\n");
-               }
-       }
-       else
-       {
-               LOG_TRACE("not doing anything\n");
-               return;
-               // don't reset counters, wait for them to accumulate
-       }
-
-       FOREACH_CLIENT(IS_PLAYER(it), LAMBDA(it.totalfrags_lastcheck = it.totalfrags));
-}
-
-void bot_calculate_stepheightvec()
-{
-       stepheightvec = autocvar_sv_stepheight * '0 0 1';
-       jumpstepheightvec = stepheightvec +
-               ((autocvar_sv_jumpvelocity * autocvar_sv_jumpvelocity) / (2 * autocvar_sv_gravity)) * '0 0 0.85';
-               // 0.75 factor is for safety to make the jumps easy
-}
-
-float bot_fixcount()
-{
-       int activerealplayers = 0;
-       int realplayers = 0;
-       if (MUTATOR_CALLHOOK(Bot_FixCount, activerealplayers, realplayers)) {
-               activerealplayers = M_ARGV(0, int);
-               realplayers = M_ARGV(1, int);
-       } else {
-               FOREACH_CLIENT(IS_REAL_CLIENT(it), LAMBDA(
-                       if(IS_PLAYER(it))
-                               ++activerealplayers;
-                       ++realplayers;
-               ));
-       }
-
-       int bots;
-       // add/remove bots if needed to make sure there are at least
-       // minplayers+bot_number, or remove all bots if no one is playing
-       // But don't remove bots immediately on level change, as the real players
-       // usually haven't rejoined yet
-       bots_would_leave = false;
-       if (teamplay && autocvar_bot_vs_human && AvailableTeams() == 2)
-               bots = min(ceil(fabs(autocvar_bot_vs_human) * activerealplayers), maxclients - realplayers);
-       else if ((realplayers || autocvar_bot_join_empty || (currentbots > 0 && time < 5)))
-       {
-               float realminplayers, minplayers;
-               realminplayers = autocvar_minplayers;
-               minplayers = max(0, floor(realminplayers));
-
-               float realminbots, minbots;
-               realminbots = autocvar_bot_number;
-               minbots = max(0, floor(realminbots));
-
-               bots = min(max(minbots, minplayers - activerealplayers), maxclients - realplayers);
-               if(bots > minbots)
-                       bots_would_leave = true;
-       }
-       else
-       {
-               // if there are no players, remove bots
-               bots = 0;
-       }
-
-       // only add one bot per frame to avoid utter chaos
-       if(time > botframe_nextthink)
-       {
-               //dprint(ftos(bots), " ? ", ftos(currentbots), "\n");
-               while (currentbots < bots)
-               {
-                       if (bot_spawn() == NULL)
-                       {
-                               bprint("Can not add bot, server full.\n");
-                               return false;
-                       }
-               }
-               while (currentbots > bots)
-                       bot_removenewest();
-       }
-
-       return true;
-}
-
-void bot_serverframe()
-{
-       if (intermission_running)
-               return;
-
-       if (time < 2)
-               return;
-
-       bot_calculate_stepheightvec();
-       bot_navigation_movemode = ((autocvar_bot_navigation_ignoreplayers) ? MOVE_NOMONSTERS : MOVE_NORMAL);
-
-       if(time > autoskill_nextthink)
-       {
-               float a;
-               a = autocvar_skill_auto;
-               if(a)
-                       autoskill(a);
-               autoskill_nextthink = time + 5;
-       }
-
-       if(time > botframe_nextthink)
-       {
-               if(!bot_fixcount())
-                       botframe_nextthink = time + 10;
-       }
-
-       bot_ignore_bots = autocvar_bot_ignore_bots;
-
-       if(botframe_spawnedwaypoints)
-       {
-               if(autocvar_waypoint_benchmark)
-                       localcmd("quit\n");
-       }
-
-       if (currentbots > 0 || autocvar_g_waypointeditor || autocvar_g_waypointeditor_auto)
-       if (botframe_spawnedwaypoints)
-       {
-               if(botframe_cachedwaypointlinks)
-               {
-                       if(!botframe_loadedforcedlinks)
-                               waypoint_load_links_hardwired();
-               }
-               else
-               {
-                       // TODO: Make this check cleaner
-                       IL_EACH(g_waypoints, time - it.nextthink > 10,
-                       {
-                               waypoint_save_links();
-                               break;
-                       });
-               }
-       }
-       else
-       {
-               botframe_spawnedwaypoints = true;
-               waypoint_loadall();
-               if(!waypoint_load_links())
-                       waypoint_schedulerelinkall();
-       }
-
-       if (bot_list)
-       {
-               // cycle the goal token from one bot to the next each frame
-               // (this prevents them from all doing spawnfunc_waypoint searches on the same
-               //  frame, which causes choppy framerates)
-               if (bot_strategytoken_taken)
-               {
-                       bot_strategytoken_taken = false;
-                       if (bot_strategytoken)
-                               bot_strategytoken = bot_strategytoken.nextbot;
-                       if (!bot_strategytoken)
-                               bot_strategytoken = bot_list;
-               }
-
-               if (botframe_nextdangertime < time)
-               {
-                       float interval;
-                       interval = autocvar_bot_ai_dangerdetectioninterval;
-                       if (botframe_nextdangertime < time - interval * 1.5)
-                               botframe_nextdangertime = time;
-                       botframe_nextdangertime = botframe_nextdangertime + interval;
-                       botframe_updatedangerousobjects(autocvar_bot_ai_dangerdetectionupdates);
-               }
-       }
-
-       if (autocvar_g_waypointeditor)
-               botframe_showwaypointlinks();
-
-       if (autocvar_g_waypointeditor_auto)
-               botframe_autowaypoints();
-
-       if(time > bot_cvar_nextthink)
-       {
-               if(currentbots>0)
-                       bot_custom_weapon_priority_setup();
-               bot_cvar_nextthink = time + 5;
-       }
-}
diff --git a/qcsrc/server/bot/bot.qh b/qcsrc/server/bot/bot.qh
deleted file mode 100644 (file)
index e9dd926..0000000
+++ /dev/null
@@ -1,114 +0,0 @@
-#pragma once
-/*
- * Globals and Fields
- */
-
-const int AI_STATUS_ROAMING                                            = BIT(0);       // Bot is just crawling the map. No enemies at sight
-const int AI_STATUS_ATTACKING                                  = BIT(1);       // There are enemies at sight
-const int AI_STATUS_RUNNING                                            = BIT(2);       // Bot is bunny hopping
-const int AI_STATUS_DANGER_AHEAD                               = BIT(3);       // There is lava/slime/trigger_hurt ahead
-const int AI_STATUS_OUT_JUMPPAD                                        = BIT(4);       // Trying to get out of a "vertical" jump pad
-const int AI_STATUS_OUT_WATER                                  = BIT(5);       // Trying to get out of water
-const int AI_STATUS_WAYPOINT_PERSONAL_LINKING  = BIT(6);       // Waiting for the personal waypoint to be linked
-const int AI_STATUS_WAYPOINT_PERSONAL_GOING            = BIT(7);       // Going to a personal waypoint
-const int AI_STATUS_WAYPOINT_PERSONAL_REACHED  = BIT(8);       // Personal waypoint reached
-const int AI_STATUS_JETPACK_FLYING                             = BIT(9);
-const int AI_STATUS_JETPACK_LANDING                            = BIT(10);
-const int AI_STATUS_STUCK                                              = BIT(11);  // Cannot reach any goal
-
-.float isbot; // true if this client is actually a bot
-.int aistatus;
-
-// Skill system
-float skill;
-float autoskill_nextthink;
-
-// havocbot_keyboardskill // keyboard movement
-.float bot_moveskill; // moving technique
-.float bot_dodgeskill; // dodging
-
-.float bot_pingskill; // ping offset
-
-.float bot_weaponskill; // weapon usage skill (combos, e.g.)
-.float bot_aggresskill; // aggressivity, controls "think before fire" behaviour
-.float bot_rangepreference; // weapon choice offset for range (>0 = prefer long range earlier "sniper", <0 = prefer short range "spammer")
-
-.float bot_aimskill; // aim accuracy
-.float bot_offsetskill; // aim breakage
-.float bot_mouseskill; // mouse "speed"
-
-.float bot_thinkskill; // target choice
-.float bot_aiskill; // strategy choice
-
-.float totalfrags_lastcheck;
-
-// Custom weapon priorities
-float bot_custom_weapon;
-float bot_distance_far;
-float bot_distance_close;
-
-float bot_weapons_far[Weapons_MAX];
-float bot_weapons_mid[Weapons_MAX];
-float bot_weapons_close[Weapons_MAX];
-
-entity bot_list;
-.entity nextbot;
-.string cleanname;
-.string netname_freeme;
-.string playermodel_freeme;
-.string playerskin_freeme;
-
-.float bot_nextthink;
-
-.float createdtime;
-.float bot_preferredcolors;
-.float bot_attack;
-.float bot_dodge;
-.float bot_dodgerating;
-
-.float bot_pickup;
-.float bot_pickupbasevalue;
-.float bot_canfire;
-.float bot_strategytime;
-
-.float bot_forced_team;
-.float bot_config_loaded;
-
-float bot_strategytoken_taken;
-entity bot_strategytoken;
-
-float botframe_spawnedwaypoints;
-float botframe_nextthink;
-float botframe_nextdangertime;
-float bot_cvar_nextthink;
-float bot_ignore_bots; // let bots not attack other bots (only works in non-teamplay)
-
-/*
- * Functions
- */
-
-entity bot_spawn();
-float bot_fixcount();
-
-void bot_think(entity this);
-void bot_setnameandstuff(entity this);
-void bot_custom_weapon_priority_setup();
-void bot_endgame();
-void bot_relinkplayerlist();
-void bot_clientdisconnect(entity this);
-void bot_clientconnect(entity this);
-void bot_removefromlargestteam();
-void bot_removenewest();
-void autoskill(float factor);
-void bot_serverframe();
-
-.void(entity this) bot_ai;
-.float(entity player, entity item) bot_pickupevalfunc;
-
-/*
- * Imports
- */
-
-void(entity this) havocbot_setupbot;
-
-void bot_calculate_stepheightvec();
diff --git a/qcsrc/server/bot/default/_mod.inc b/qcsrc/server/bot/default/_mod.inc
new file mode 100644 (file)
index 0000000..ec73502
--- /dev/null
@@ -0,0 +1,7 @@
+// generated file; do not modify
+#include <server/bot/default/aim.qc>
+#include <server/bot/default/bot.qc>
+#include <server/bot/default/cvars.qc>
+#include <server/bot/default/navigation.qc>
+#include <server/bot/default/scripting.qc>
+#include <server/bot/default/waypoints.qc>
diff --git a/qcsrc/server/bot/default/_mod.qh b/qcsrc/server/bot/default/_mod.qh
new file mode 100644 (file)
index 0000000..9252f19
--- /dev/null
@@ -0,0 +1,7 @@
+// generated file; do not modify
+#include <server/bot/default/aim.qh>
+#include <server/bot/default/bot.qh>
+#include <server/bot/default/cvars.qh>
+#include <server/bot/default/navigation.qh>
+#include <server/bot/default/scripting.qh>
+#include <server/bot/default/waypoints.qh>
diff --git a/qcsrc/server/bot/default/aim.qc b/qcsrc/server/bot/default/aim.qc
new file mode 100644 (file)
index 0000000..15dfb0b
--- /dev/null
@@ -0,0 +1,395 @@
+#include "aim.qh"
+
+#include "cvars.qh"
+
+#include "bot.qh"
+
+#include <common/physics/player.qh>
+#include <common/state.qh>
+
+#include "../../weapons/weaponsystem.qh"
+
+#include "../../mutators/all.qh"
+
+// traces multiple trajectories to find one that will impact the target
+// 'end' vector is the place it aims for,
+// returns true only if it hit targ (don't target non-solid entities)
+
+float findtrajectorywithleading(vector org, vector m1, vector m2, entity targ, float shotspeed, float shotspeedupward, float maxtime, float shotdelay, entity ignore)
+{
+       float c, savesolid, shottime;
+       vector dir, end, v, o;
+       if (shotspeed < 1)
+               return false; // could cause division by zero if calculated
+       if (targ.solid < SOLID_BBOX) // SOLID_NOT and SOLID_TRIGGER
+               return false; // could never hit it
+       if (!tracetossent)
+               tracetossent = new(tracetossent);
+       tracetossent.owner = ignore;
+       setsize(tracetossent, m1, m2);
+       savesolid = targ.solid;
+       targ.solid = SOLID_NOT;
+       o = (targ.absmin + targ.absmax) * 0.5;
+       shottime = ((vlen(o - org) / shotspeed) + shotdelay);
+       v = targ.velocity * shottime + o;
+       tracebox(o, targ.mins, targ.maxs, v, false, targ);
+       v = trace_endpos;
+       end = v + (targ.mins + targ.maxs) * 0.5;
+       if ((vlen(end - org) / shotspeed + 0.2) > maxtime)
+       {
+               // out of range
+               targ.solid = savesolid;
+               return false;
+       }
+
+       if (!tracetossfaketarget)
+               tracetossfaketarget = new(tracetossfaketarget);
+       tracetossfaketarget.solid = savesolid;
+       set_movetype(tracetossfaketarget, targ.move_movetype);
+       _setmodel(tracetossfaketarget, targ.model); // no low precision
+       tracetossfaketarget.model = targ.model;
+       tracetossfaketarget.modelindex = targ.modelindex;
+       setsize(tracetossfaketarget, targ.mins, targ.maxs);
+       setorigin(tracetossfaketarget, v);
+
+       c = 0;
+       dir = normalize(end - org);
+       while (c < 10) // 10 traces
+       {
+               setorigin(tracetossent, org); // reset
+               tracetossent.velocity = findtrajectory_velocity = normalize(dir) * shotspeed + shotspeedupward * '0 0 1';
+               tracetoss(tracetossent, ignore); // love builtin functions...
+               if (trace_ent == tracetossfaketarget) // done
+               {
+                       targ.solid = savesolid;
+
+                       // make it disappear
+                       tracetossfaketarget.solid = SOLID_NOT;
+                       set_movetype(tracetossfaketarget, MOVETYPE_NONE);
+                       tracetossfaketarget.model = "";
+                       tracetossfaketarget.modelindex = 0;
+                       // relink to remove it from physics considerations
+                       setorigin(tracetossfaketarget, v);
+
+                       return true;
+               }
+               dir.z = dir.z + 0.1; // aim up a little more
+               c = c + 1;
+       }
+       targ.solid = savesolid;
+
+       // make it disappear
+       tracetossfaketarget.solid = SOLID_NOT;
+       set_movetype(tracetossfaketarget, MOVETYPE_NONE);
+       tracetossfaketarget.model = "";
+       tracetossfaketarget.modelindex = 0;
+       // relink to remove it from physics considerations
+       setorigin(tracetossfaketarget, v);
+
+       // leave a valid one even if it won't reach
+       findtrajectory_velocity = normalize(end - org) * shotspeed + shotspeedupward * '0 0 1';
+       return false;
+}
+
+void lag_update(entity this)
+{
+       if (this.lag1_time) if (time > this.lag1_time) {this.lag_func(this, this.lag1_time, this.lag1_float1, this.lag1_float2, this.lag1_entity1, this.lag1_vec1, this.lag1_vec2, this.lag1_vec3, this.lag1_vec4);this.lag1_time = 0;}
+       if (this.lag2_time) if (time > this.lag2_time) {this.lag_func(this, this.lag2_time, this.lag2_float1, this.lag2_float2, this.lag2_entity1, this.lag2_vec1, this.lag2_vec2, this.lag2_vec3, this.lag2_vec4);this.lag2_time = 0;}
+       if (this.lag3_time) if (time > this.lag3_time) {this.lag_func(this, this.lag3_time, this.lag3_float1, this.lag3_float2, this.lag3_entity1, this.lag3_vec1, this.lag3_vec2, this.lag3_vec3, this.lag3_vec4);this.lag3_time = 0;}
+       if (this.lag4_time) if (time > this.lag4_time) {this.lag_func(this, this.lag4_time, this.lag4_float1, this.lag4_float2, this.lag4_entity1, this.lag4_vec1, this.lag4_vec2, this.lag4_vec3, this.lag4_vec4);this.lag4_time = 0;}
+       if (this.lag5_time) if (time > this.lag5_time) {this.lag_func(this, this.lag5_time, this.lag5_float1, this.lag5_float2, this.lag5_entity1, this.lag5_vec1, this.lag5_vec2, this.lag5_vec3, this.lag5_vec4);this.lag5_time = 0;}
+}
+
+float lag_additem(entity this, float t, float f1, float f2, entity e1, vector v1, vector v2, vector v3, vector v4)
+{
+       if (this.lag1_time == 0) {this.lag1_time = t;this.lag1_float1 = f1;this.lag1_float2 = f2;this.lag1_entity1 = e1;this.lag1_vec1 = v1;this.lag1_vec2 = v2;this.lag1_vec3 = v3;this.lag1_vec4 = v4;return true;}
+       if (this.lag2_time == 0) {this.lag2_time = t;this.lag2_float1 = f1;this.lag2_float2 = f2;this.lag2_entity1 = e1;this.lag2_vec1 = v1;this.lag2_vec2 = v2;this.lag2_vec3 = v3;this.lag2_vec4 = v4;return true;}
+       if (this.lag3_time == 0) {this.lag3_time = t;this.lag3_float1 = f1;this.lag3_float2 = f2;this.lag3_entity1 = e1;this.lag3_vec1 = v1;this.lag3_vec2 = v2;this.lag3_vec3 = v3;this.lag3_vec4 = v4;return true;}
+       if (this.lag4_time == 0) {this.lag4_time = t;this.lag4_float1 = f1;this.lag4_float2 = f2;this.lag4_entity1 = e1;this.lag4_vec1 = v1;this.lag4_vec2 = v2;this.lag4_vec3 = v3;this.lag4_vec4 = v4;return true;}
+       if (this.lag5_time == 0) {this.lag5_time = t;this.lag5_float1 = f1;this.lag5_float2 = f2;this.lag5_entity1 = e1;this.lag5_vec1 = v1;this.lag5_vec2 = v2;this.lag5_vec3 = v3;this.lag5_vec4 = v4;return true;}
+       // no room for it (what is the best thing to do here??)
+       return false;
+}
+
+bool bot_shouldattack(entity this, entity targ)
+{
+       if (targ.team == this.team)
+       {
+               if (targ == this)
+                       return false;
+               if (teamplay)
+               if (targ.team != 0)
+                       return false;
+       }
+
+       if(STAT(FROZEN, targ))
+               return false;
+
+       if(teamplay)
+       {
+               if(targ.team==0)
+                       return false;
+       }
+       else if(bot_ignore_bots)
+               if(IS_BOT_CLIENT(targ))
+                       return false;
+
+       if (!targ.takedamage)
+               return false;
+       if (IS_DEAD(targ))
+               return false;
+       if (PHYS_INPUT_BUTTON_CHAT(targ))
+               return false;
+       if(targ.flags & FL_NOTARGET)
+               return false;
+
+       if(MUTATOR_CALLHOOK(BotShouldAttack, this, targ))
+               return false;
+
+       return true;
+}
+
+void bot_lagfunc(entity this, float t, float f1, float f2, entity e1, vector v1, vector v2, vector v3, vector v4)
+{
+       if(this.flags & FL_INWATER)
+       {
+               this.bot_aimtarg = NULL;
+               return;
+       }
+       this.bot_aimtarg = e1;
+       this.bot_aimlatency = this.ping; // FIXME?  Shouldn't this be in the lag item?
+       //this.bot_aimorigin = v1;
+       //this.bot_aimvelocity = v2;
+       this.bot_aimtargorigin = v3;
+       this.bot_aimtargvelocity = v4;
+       if(skill <= 0)
+               this.bot_canfire = (random() < 0.8);
+       else if(skill <= 1)
+               this.bot_canfire = (random() < 0.9);
+       else if(skill <= 2)
+               this.bot_canfire = (random() < 0.95);
+       else
+               this.bot_canfire = 1;
+}
+
+float bot_aimdir(entity this, vector v, float maxfiredeviation)
+{
+       float dist, delta_t, blend;
+       vector desiredang, diffang;
+
+       //dprint("aim ", this.netname, ": old:", vtos(this.v_angle));
+       // make sure v_angle is sane first
+       this.v_angle_y = this.v_angle.y - floor(this.v_angle.y / 360) * 360;
+       this.v_angle_z = 0;
+
+       // get the desired angles to aim at
+       //dprint(" at:", vtos(v));
+       v = normalize(v);
+       //te_lightning2(NULL, this.origin + this.view_ofs, this.origin + this.view_ofs + v * 200);
+       if (time >= this.bot_badaimtime)
+       {
+               this.bot_badaimtime = max(this.bot_badaimtime + 0.3, time);
+               this.bot_badaimoffset = randomvec() * bound(0, 5 - 0.5 * (skill+this.bot_offsetskill), 5) * autocvar_bot_ai_aimskill_offset;
+       }
+       desiredang = vectoangles(v) + this.bot_badaimoffset;
+       //dprint(" desired:", vtos(desiredang));
+       if (desiredang.x >= 180)
+               desiredang.x = desiredang.x - 360;
+       desiredang.x = bound(-90, 0 - desiredang.x, 90);
+       desiredang.z = this.v_angle.z;
+       //dprint(" / ", vtos(desiredang));
+
+       //// pain throws off aim
+       //if (this.bot_painintensity)
+       //{
+       //      // shake from pain
+       //      desiredang = desiredang + randomvec() * this.bot_painintensity * 0.2;
+       //}
+
+       // calculate turn angles
+       diffang = (desiredang - this.bot_olddesiredang);
+       // wrap yaw turn
+       diffang.y = diffang.y - floor(diffang.y / 360) * 360;
+       if (diffang.y >= 180)
+               diffang.y = diffang.y - 360;
+       this.bot_olddesiredang = desiredang;
+       //dprint(" diff:", vtos(diffang));
+
+       delta_t = time-this.bot_prevaimtime;
+       this.bot_prevaimtime = time;
+       // Here we will try to anticipate the comming aiming direction
+       this.bot_1st_order_aimfilter= this.bot_1st_order_aimfilter
+               + (diffang * (1 / delta_t)    - this.bot_1st_order_aimfilter) * bound(0, autocvar_bot_ai_aimskill_order_filter_1st,1);
+       this.bot_2nd_order_aimfilter= this.bot_2nd_order_aimfilter
+               + (this.bot_1st_order_aimfilter - this.bot_2nd_order_aimfilter) * bound(0, autocvar_bot_ai_aimskill_order_filter_2nd,1);
+       this.bot_3th_order_aimfilter= this.bot_3th_order_aimfilter
+               + (this.bot_2nd_order_aimfilter - this.bot_3th_order_aimfilter) * bound(0, autocvar_bot_ai_aimskill_order_filter_3th,1);
+       this.bot_4th_order_aimfilter= this.bot_4th_order_aimfilter
+               + (this.bot_3th_order_aimfilter - this.bot_4th_order_aimfilter) * bound(0, autocvar_bot_ai_aimskill_order_filter_4th,1);
+       this.bot_5th_order_aimfilter= this.bot_5th_order_aimfilter
+               + (this.bot_4th_order_aimfilter - this.bot_5th_order_aimfilter) * bound(0, autocvar_bot_ai_aimskill_order_filter_5th,1);
+
+       //blend = (bound(0,skill,10)*0.1)*pow(1-bound(0,skill,10)*0.05,2.5)*5.656854249; //Plot formule before changing !
+       blend = bound(0,skill+this.bot_aimskill,10)*0.1;
+       desiredang = desiredang + blend *
+       (
+                 this.bot_1st_order_aimfilter * autocvar_bot_ai_aimskill_order_mix_1st
+               + this.bot_2nd_order_aimfilter * autocvar_bot_ai_aimskill_order_mix_2nd
+               + this.bot_3th_order_aimfilter * autocvar_bot_ai_aimskill_order_mix_3th
+               + this.bot_4th_order_aimfilter * autocvar_bot_ai_aimskill_order_mix_4th
+               + this.bot_5th_order_aimfilter * autocvar_bot_ai_aimskill_order_mix_5th
+       );
+
+       // calculate turn angles
+       diffang = desiredang - this.bot_mouseaim;
+       // wrap yaw turn
+       diffang.y = diffang.y - floor(diffang.y / 360) * 360;
+       if (diffang.y >= 180)
+               diffang.y = diffang.y - 360;
+       //dprint(" diff:", vtos(diffang));
+
+       if (time >= this.bot_aimthinktime)
+       {
+               this.bot_aimthinktime = max(this.bot_aimthinktime + 0.5 - 0.05*(skill+this.bot_thinkskill), time);
+               this.bot_mouseaim = this.bot_mouseaim + diffang * (1-random()*0.1*bound(1,10-(skill+this.bot_thinkskill),10));
+       }
+
+       //this.v_angle = this.v_angle + diffang * bound(0, r * frametime * (skill * 0.5 + 2), 1);
+
+       diffang = this.bot_mouseaim - desiredang;
+       // wrap yaw turn
+       diffang.y = diffang.y - floor(diffang.y / 360) * 360;
+       if (diffang.y >= 180)
+               diffang.y = diffang.y - 360;
+       desiredang = desiredang + diffang * bound(0,autocvar_bot_ai_aimskill_think,1);
+
+       // calculate turn angles
+       diffang = desiredang - this.v_angle;
+       // wrap yaw turn
+       diffang.y = diffang.y - floor(diffang.y / 360) * 360;
+       if (diffang.y >= 180)
+               diffang.y = diffang.y - 360;
+       //dprint(" diff:", vtos(diffang));
+
+       // jitter tracking
+       dist = vlen(diffang);
+       //diffang = diffang + randomvec() * (dist * 0.05 * (3.5 - bound(0, skill, 3)));
+
+       // turn
+       float r, fixedrate, blendrate;
+       fixedrate = autocvar_bot_ai_aimskill_fixedrate / bound(1,dist,1000);
+       blendrate = autocvar_bot_ai_aimskill_blendrate;
+       r = max(fixedrate, blendrate);
+       //this.v_angle = this.v_angle + diffang * bound(frametime, r * frametime * (2+skill*skill*0.05-random()*0.05*(10-skill)), 1);
+       this.v_angle = this.v_angle + diffang * bound(delta_t, r * delta_t * (2+pow(skill+this.bot_mouseskill,3)*0.005-random()), 1);
+       this.v_angle = this.v_angle * bound(0,autocvar_bot_ai_aimskill_mouse,1) + desiredang * bound(0,(1-autocvar_bot_ai_aimskill_mouse),1);
+       //this.v_angle = this.v_angle + diffang * bound(0, r * frametime * (skill * 0.5 + 2), 1);
+       //this.v_angle = this.v_angle + diffang * (1/ blendrate);
+       this.v_angle_z = 0;
+       this.v_angle_y = this.v_angle.y - floor(this.v_angle.y / 360) * 360;
+       //dprint(" turn:", vtos(this.v_angle));
+
+       makevectors(this.v_angle);
+       shotorg = this.origin + this.view_ofs;
+       shotdir = v_forward;
+
+       //dprint(" dir:", vtos(v_forward));
+       //te_lightning2(NULL, shotorg, shotorg + shotdir * 100);
+
+       // calculate turn angles again
+       //diffang = desiredang - this.v_angle;
+       //diffang_y = diffang_y - floor(diffang_y / 360) * 360;
+       //if (diffang_y >= 180)
+       //      diffang_y = diffang_y - 360;
+
+       //dprint("e ", vtos(diffang), " < ", ftos(maxfiredeviation), "\n");
+
+       // decide whether to fire this time
+       // note the maxfiredeviation is in degrees so this has to convert to radians first
+       //if ((normalize(v) * shotdir) >= cos(maxfiredeviation * (3.14159265358979323846 / 180)))
+       if ((normalize(v) * shotdir) >= cos(maxfiredeviation * (3.14159265358979323846 / 180)))
+       if(vdist(trace_endpos-shotorg, <, 500 + 500 * bound(0, skill + this.bot_aggresskill, 10)) || random()*random()>bound(0,(skill+this.bot_aggresskill)*0.05,1))
+               this.bot_firetimer = time + bound(0.1, 0.5-(skill+this.bot_aggresskill)*0.05, 0.5);
+       //traceline(shotorg,shotorg+shotdir*1000,false,NULL);
+       //dprint(ftos(maxfiredeviation),"\n");
+       //dprint(" diff:", vtos(diffang), "\n");
+
+       return this.bot_canfire && (time < this.bot_firetimer);
+}
+
+vector bot_shotlead(vector targorigin, vector targvelocity, float shotspeed, float shotdelay)
+{
+       // Try to add code here that predicts gravity effect here, no clue HOW to though ... well not yet atleast...
+       return targorigin + targvelocity * (shotdelay + vlen(targorigin - shotorg) / shotspeed);
+}
+
+bool bot_aim(entity this, float shotspeed, float shotspeedupward, float maxshottime, bool applygravity)
+{
+       float f, r, hf, distanceratio;
+       vector v;
+       /*
+       eprint(this);
+       dprint("bot_aim(", ftos(shotspeed));
+       dprint(", ", ftos(shotspeedupward));
+       dprint(", ", ftos(maxshottime));
+       dprint(", ", ftos(applygravity));
+       dprint(");\n");
+       */
+
+       hf = this.dphitcontentsmask;
+       this.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_CORPSE;
+
+       shotspeed *= W_WeaponSpeedFactor(this);
+       shotspeedupward *= W_WeaponSpeedFactor(this);
+       if (!shotspeed)
+       {
+               LOG_TRACE("bot_aim: WARNING: weapon ", PS(this).m_weapon.m_name, " shotspeed is zero!");
+               shotspeed = 1000000;
+       }
+       if (!maxshottime)
+       {
+               LOG_TRACE("bot_aim: WARNING: weapon ", PS(this).m_weapon.m_name, " maxshottime is zero!");
+               maxshottime = 1;
+       }
+       makevectors(this.v_angle);
+       shotorg = this.origin + this.view_ofs;
+       shotdir = v_forward;
+       v = bot_shotlead(this.bot_aimtargorigin, this.bot_aimtargvelocity, shotspeed, this.bot_aimlatency);
+       distanceratio = sqrt(bound(0,skill,10000))*0.3*(vlen(v-shotorg)-100)/autocvar_bot_ai_aimskill_firetolerance_distdegrees;
+       distanceratio = bound(0,distanceratio,1);
+       r =  (autocvar_bot_ai_aimskill_firetolerance_maxdegrees-autocvar_bot_ai_aimskill_firetolerance_mindegrees)
+               * (1-distanceratio) + autocvar_bot_ai_aimskill_firetolerance_mindegrees;
+       if (applygravity && this.bot_aimtarg)
+       {
+               if (!findtrajectorywithleading(shotorg, '0 0 0', '0 0 0', this.bot_aimtarg, shotspeed, shotspeedupward, maxshottime, 0, this))
+               {
+                       this.dphitcontentsmask = hf;
+                       return false;
+               }
+
+               f = bot_aimdir(this, findtrajectory_velocity - shotspeedupward * '0 0 1', r);
+       }
+       else
+       {
+               f = bot_aimdir(this, v - shotorg, r);
+               //dprint("AIM: ");dprint(vtos(this.bot_aimtargorigin));dprint(" + ");dprint(vtos(this.bot_aimtargvelocity));dprint(" * ");dprint(ftos(this.bot_aimlatency + vlen(this.bot_aimtargorigin - shotorg) / shotspeed));dprint(" = ");dprint(vtos(v));dprint(" : aimdir = ");dprint(vtos(normalize(v - shotorg)));dprint(" : ");dprint(vtos(shotdir));dprint("\n");
+               //traceline(shotorg, shotorg + shotdir * 10000, false, this);
+               //if (trace_ent.takedamage)
+               //if (trace_fraction < 1)
+               //if (!bot_shouldattack(this, trace_ent))
+               //      return false;
+               traceline(shotorg, this.bot_aimtargorigin, false, this);
+               if (trace_fraction < 1)
+               if (trace_ent != this.enemy)
+               if (!bot_shouldattack(this, trace_ent))
+               {
+                       this.dphitcontentsmask = hf;
+                       return false;
+               }
+       }
+
+       //if (r > maxshottime * shotspeed)
+       //      return false;
+       this.dphitcontentsmask = hf;
+       return true;
+}
diff --git a/qcsrc/server/bot/default/aim.qh b/qcsrc/server/bot/default/aim.qh
new file mode 100644 (file)
index 0000000..dfe10e2
--- /dev/null
@@ -0,0 +1,99 @@
+#pragma once
+/*
+ * Globals and Fields
+ */
+
+entity tracetossent;
+entity tracetossfaketarget;
+vector findtrajectory_velocity;
+
+
+
+vector shotorg;
+vector shotdir;
+
+// lag simulation
+// upto 5 queued messages
+.float lag1_time;
+.float lag1_float1;
+.float lag1_float2;
+.entity lag1_entity1;
+.vector lag1_vec1;
+.vector lag1_vec2;
+.vector lag1_vec3;
+.vector lag1_vec4;
+
+.float lag2_time;
+.float lag2_float1;
+.float lag2_float2;
+.entity lag2_entity1;
+.vector lag2_vec1;
+.vector lag2_vec2;
+.vector lag2_vec3;
+.vector lag2_vec4;
+
+.float lag3_time;
+.float lag3_float1;
+.float lag3_float2;
+.entity lag3_entity1;
+.vector lag3_vec1;
+.vector lag3_vec2;
+.vector lag3_vec3;
+.vector lag3_vec4;
+
+.float lag4_time;
+.float lag4_float1;
+.float lag4_float2;
+.entity lag4_entity1;
+.vector lag4_vec1;
+.vector lag4_vec2;
+.vector lag4_vec3;
+.vector lag4_vec4;
+
+.float lag5_time;
+.float lag5_float1;
+.float lag5_float2;
+.entity lag5_entity1;
+.vector lag5_vec1;
+.vector lag5_vec2;
+.vector lag5_vec3;
+.vector lag5_vec4;
+
+.float bot_badaimtime;
+.float bot_aimthinktime;
+.float bot_prevaimtime;
+.float bot_firetimer;
+.float bot_aimlatency;
+
+.vector bot_mouseaim;
+.vector bot_badaimoffset;
+.vector bot_1st_order_aimfilter;
+.vector bot_2nd_order_aimfilter;
+.vector bot_3th_order_aimfilter;
+.vector bot_4th_order_aimfilter;
+.vector bot_5th_order_aimfilter;
+.vector bot_olddesiredang;
+
+//.vector bot_aimorigin;
+//.vector bot_aimvelocity;
+.vector bot_aimtargorigin;
+.vector bot_aimtargvelocity;
+
+.entity bot_aimtarg;
+
+/*
+ * Functions
+ */
+
+float lag_additem(entity this, float t, float f1, float f2, entity e1, vector v1, vector v2, vector v3, vector v4);
+void lag_update(entity this);
+void bot_lagfunc(entity this, float t, float f1, float f2, entity e1, vector v1, vector v2, vector v3, vector v4);
+
+float bot_shouldattack(entity this, entity targ);
+float bot_aimdir(entity this, vector v, float maxfiredeviation);
+bool bot_aim(entity this, float shotspeed, float shotspeedupward, float maxshottime, bool applygravity);
+float findtrajectorywithleading(vector org, vector m1, vector m2, entity targ, float shotspeed, float shotspeedupward, float maxtime, float shotdelay, entity ignore);
+
+vector bot_shotlead(vector targorigin, vector targvelocity, float shotspeed, float shotdelay);
+
+.void(entity this, float t, float f1, float f2, entity e1, vector v1, vector v2, vector v3, vector v4) lag_func;
diff --git a/qcsrc/server/bot/default/bot.qc b/qcsrc/server/bot/default/bot.qc
new file mode 100644 (file)
index 0000000..cab3814
--- /dev/null
@@ -0,0 +1,727 @@
+#include "bot.qh"
+
+#include "cvars.qh"
+
+#include "aim.qh"
+#include "navigation.qh"
+#include "scripting.qh"
+#include "waypoints.qh"
+
+#include "havocbot/havocbot.qh"
+#include "havocbot/scripting.qh"
+
+#include "../../teamplay.qh"
+
+#include "../../antilag.qh"
+#include "../../autocvars.qh"
+#include "../../campaign.qh"
+#include "../../cl_client.qh"
+#include "../../constants.qh"
+#include "../../defs.qh"
+#include "../../race.qh"
+#include <common/t_items.qh>
+
+#include "../../mutators/all.qh"
+
+#include "../../weapons/accuracy.qh"
+
+#include <common/physics/player.qh>
+#include <common/constants.qh>
+#include <common/mapinfo.qh>
+#include <common/teams.qh>
+#include <common/util.qh>
+
+#include <common/weapons/all.qh>
+
+#include <lib/csqcmodel/sv_model.qh>
+
+#include <lib/warpzone/common.qh>
+#include <lib/warpzone/util_server.qh>
+
+entity bot_spawn()
+{
+       entity bot = spawnclient();
+       if (bot)
+       {
+               currentbots = currentbots + 1;
+               bot_setnameandstuff(bot);
+               ClientConnect(bot);
+               PutClientInServer(bot);
+       }
+       return bot;
+}
+
+void bot_think(entity this)
+{
+       if (this.bot_nextthink > time)
+               return;
+
+       this.flags &= ~FL_GODMODE;
+       if(autocvar_bot_god)
+               this.flags |= FL_GODMODE;
+
+       this.bot_nextthink = this.bot_nextthink + autocvar_bot_ai_thinkinterval * pow(0.5, this.bot_aiskill);
+       //if (this.bot_painintensity > 0)
+       //      this.bot_painintensity = this.bot_painintensity - (skill + 1) * 40 * frametime;
+
+       //this.bot_painintensity = this.bot_painintensity + this.bot_oldhealth - this.health;
+       //this.bot_painintensity = bound(0, this.bot_painintensity, 100);
+
+       if (!IS_PLAYER(this) || (autocvar_g_campaign && !campaign_bots_may_start))
+       {
+               this.bot_nextthink = time + 0.5;
+               return;
+       }
+
+       if (this.fixangle)
+       {
+               this.v_angle = this.angles;
+               this.v_angle_z = 0;
+               this.fixangle = false;
+       }
+
+       this.dmg_take = 0;
+       this.dmg_save = 0;
+       this.dmg_inflictor = NULL;
+
+       // calculate an aiming latency based on the skill setting
+       // (simulated network latency + naturally delayed reflexes)
+       //this.ping = 0.7 - bound(0, 0.05 * skill, 0.5); // moved the reflexes to bot_aimdir (under the name 'think')
+       // minimum ping 20+10 random
+       this.ping = bound(0,0.07 - bound(0, (skill + this.bot_pingskill) * 0.005,0.05)+random()*0.01,0.65); // Now holds real lag to server, and higer skill players take a less laggy server
+       // skill 10 = ping 0.2 (adrenaline)
+       // skill 0 = ping 0.7 (slightly drunk)
+
+       // clear buttons
+       PHYS_INPUT_BUTTON_ATCK(this) = false;
+       PHYS_INPUT_BUTTON_JUMP(this) = false;
+       PHYS_INPUT_BUTTON_ATCK2(this) = false;
+       PHYS_INPUT_BUTTON_ZOOM(this) = false;
+       PHYS_INPUT_BUTTON_CROUCH(this) = false;
+       PHYS_INPUT_BUTTON_HOOK(this) = false;
+       PHYS_INPUT_BUTTON_INFO(this) = false;
+       PHYS_INPUT_BUTTON_DRAG(this) = false;
+       PHYS_INPUT_BUTTON_CHAT(this) = false;
+       PHYS_INPUT_BUTTON_USE(this) = false;
+
+       if (time < game_starttime)
+       {
+               // block the bot during the countdown to game start
+               this.movement = '0 0 0';
+               this.bot_nextthink = game_starttime;
+               return;
+       }
+
+       // if dead, just wait until we can respawn
+       if (IS_DEAD(this))
+       {
+               if (this.deadflag == DEAD_DEAD)
+               {
+                       PHYS_INPUT_BUTTON_JUMP(this) = true; // press jump to respawn
+                       this.bot_strategytime = 0;
+               }
+       }
+       else if(this.aistatus & AI_STATUS_STUCK)
+               navigation_unstuck(this);
+
+       // now call the current bot AI (havocbot for example)
+       this.bot_ai(this);
+}
+
+void bot_setnameandstuff(entity this)
+{
+       string readfile, s;
+       float file, tokens, prio;
+
+       string bot_name, bot_model, bot_skin, bot_shirt, bot_pants;
+       string name, prefix, suffix;
+
+       if(autocvar_g_campaign)
+       {
+               prefix = "";
+               suffix = "";
+       }
+       else
+       {
+               prefix = autocvar_bot_prefix;
+               suffix = autocvar_bot_suffix;
+       }
+
+       file = fopen(autocvar_bot_config_file, FILE_READ);
+
+       if(file < 0)
+       {
+               LOG_INFO(strcat("Error: Can not open the bot configuration file '",autocvar_bot_config_file,"'\n"));
+               readfile = "";
+       }
+       else
+       {
+               RandomSelection_Init();
+               while((readfile = fgets(file)))
+               {
+                       if(substring(readfile, 0, 2) == "//")
+                               continue;
+                       if(substring(readfile, 0, 1) == "#")
+                               continue;
+                       tokens = tokenizebyseparator(readfile, "\t");
+                       if(tokens == 0)
+                               continue;
+                       s = argv(0);
+                       prio = 1;
+                       FOREACH_CLIENT(IS_BOT_CLIENT(it), LAMBDA(
+                               if(s == it.cleanname)
+                               {
+                                       prio = 0;
+                                       break;
+                               }
+                       ));
+                       RandomSelection_Add(NULL, 0, readfile, 1, prio);
+               }
+               readfile = RandomSelection_chosen_string;
+               fclose(file);
+       }
+
+       tokens = tokenizebyseparator(readfile, "\t");
+       if(argv(0) != "") bot_name = argv(0);
+       else bot_name = "Bot";
+
+       if(argv(1) != "") bot_model = argv(1);
+       else bot_model = "";
+
+       if(argv(2) != "") bot_skin = argv(2);
+       else bot_skin = "0";
+
+       if(argv(3) != "" && stof(argv(3)) >= 0) bot_shirt = argv(3);
+       else bot_shirt = ftos(floor(random() * 15));
+
+       if(argv(4) != "" && stof(argv(4)) >= 0) bot_pants = argv(4);
+       else bot_pants = ftos(floor(random() * 15));
+
+       this.bot_forced_team = stof(argv(5));
+
+       prio = 6;
+
+       #define READSKILL(f,w,r) if(argv(prio) != "") this.f = stof(argv(prio)) * (w); else this.f = (!autocvar_g_campaign) * (2 * random() - 1) * (r) * (w); ++prio
+       //print(bot_name, ": ping=", argv(9), "\n");
+
+       READSKILL(havocbot_keyboardskill, 0.5, 0.5); // keyboard skill
+       READSKILL(bot_moveskill, 2, 0); // move skill
+       READSKILL(bot_dodgeskill, 2, 0); // dodge skill
+
+       READSKILL(bot_pingskill, 0.5, 0); // ping skill
+
+       READSKILL(bot_weaponskill, 2, 0); // weapon skill
+       READSKILL(bot_aggresskill, 1, 0); // aggre skill
+       READSKILL(bot_rangepreference, 1, 0); // read skill
+
+       READSKILL(bot_aimskill, 2, 0); // aim skill
+       READSKILL(bot_offsetskill, 2, 0.5); // offset skill
+       READSKILL(bot_mouseskill, 1, 0.5); // mouse skill
+
+       READSKILL(bot_thinkskill, 1, 0.5); // think skill
+       READSKILL(bot_aiskill, 2, 0); // "ai" skill
+
+       this.bot_config_loaded = true;
+
+       // this is really only a default, JoinBestTeam is called later
+       setcolor(this, stof(bot_shirt) * 16 + stof(bot_pants));
+       this.bot_preferredcolors = this.clientcolors;
+
+       // pick the name
+       if (autocvar_bot_usemodelnames)
+               name = bot_model;
+       else
+               name = bot_name;
+
+       // number bots with identical names
+       int j = 0;
+       FOREACH_CLIENT(IS_BOT_CLIENT(it), LAMBDA(
+               if(it.cleanname == name)
+                       ++j;
+       ));
+       if (j)
+               this.netname = this.netname_freeme = strzone(strcat(prefix, name, "(", ftos(j), ")", suffix));
+       else
+               this.netname = this.netname_freeme = strzone(strcat(prefix, name, suffix));
+
+       this.cleanname = strzone(name);
+
+       // pick the model and skin
+       if(substring(bot_model, -4, 1) != ".")
+               bot_model = strcat(bot_model, ".iqm");
+       this.playermodel = this.playermodel_freeme = strzone(strcat("models/player/", bot_model));
+       this.playerskin = this.playerskin_freeme = strzone(bot_skin);
+
+       this.cvar_cl_accuracy_data_share = 1;  // share the bots weapon accuracy data with the NULL
+       this.cvar_cl_accuracy_data_receive = 0;  // don't receive any weapon accuracy data
+}
+
+void bot_custom_weapon_priority_setup()
+{
+       float tokens, i, w;
+
+       bot_custom_weapon = false;
+
+       if(     autocvar_bot_ai_custom_weapon_priority_far == "" ||
+               autocvar_bot_ai_custom_weapon_priority_mid == "" ||
+               autocvar_bot_ai_custom_weapon_priority_close == "" ||
+               autocvar_bot_ai_custom_weapon_priority_distances == ""
+       )
+               return;
+
+       // Parse distances
+       tokens = tokenizebyseparator(autocvar_bot_ai_custom_weapon_priority_distances," ");
+
+       if (tokens!=2)
+               return;
+
+       bot_distance_far = stof(argv(0));
+       bot_distance_close = stof(argv(1));
+
+       if(bot_distance_far < bot_distance_close){
+               bot_distance_far = stof(argv(1));
+               bot_distance_close = stof(argv(0));
+       }
+
+       // Initialize list of weapons
+       bot_weapons_far[0] = -1;
+       bot_weapons_mid[0] = -1;
+       bot_weapons_close[0] = -1;
+
+       // Parse far distance weapon priorities
+       tokens = tokenizebyseparator(W_NumberWeaponOrder(autocvar_bot_ai_custom_weapon_priority_far)," ");
+
+       int c = 0;
+       for(i=0; i < tokens && c < Weapons_COUNT; ++i){
+               w = stof(argv(i));
+               if ( w >= WEP_FIRST && w <= WEP_LAST) {
+                       bot_weapons_far[c] = w;
+                       ++c;
+               }
+       }
+       if(c < Weapons_COUNT)
+               bot_weapons_far[c] = -1;
+
+       // Parse mid distance weapon priorities
+       tokens = tokenizebyseparator(W_NumberWeaponOrder(autocvar_bot_ai_custom_weapon_priority_mid)," ");
+
+       c = 0;
+       for(i=0; i < tokens && c < Weapons_COUNT; ++i){
+               w = stof(argv(i));
+               if ( w >= WEP_FIRST && w <= WEP_LAST) {
+                       bot_weapons_mid[c] = w;
+                       ++c;
+               }
+       }
+       if(c < Weapons_COUNT)
+               bot_weapons_mid[c] = -1;
+
+       // Parse close distance weapon priorities
+       tokens = tokenizebyseparator(W_NumberWeaponOrder(autocvar_bot_ai_custom_weapon_priority_close)," ");
+
+       c = 0;
+       for(i=0; i < tokens && i < Weapons_COUNT; ++i){
+               w = stof(argv(i));
+               if ( w >= WEP_FIRST && w <= WEP_LAST) {
+                       bot_weapons_close[c] = w;
+                       ++c;
+               }
+       }
+       if(c < Weapons_COUNT)
+               bot_weapons_close[c] = -1;
+
+       bot_custom_weapon = true;
+}
+
+void bot_endgame()
+{
+       entity e;
+       //dprint("bot_endgame\n");
+       e = bot_list;
+       while (e)
+       {
+               setcolor(e, e.bot_preferredcolors);
+               e = e.nextbot;
+       }
+       // if dynamic waypoints are ever implemented, save them here
+}
+
+void bot_relinkplayerlist()
+{
+       player_count = 0;
+       currentbots = 0;
+       bot_list = NULL;
+
+       entity prevbot = NULL;
+       FOREACH_CLIENT(true,
+       {
+               ++player_count;
+
+               if(IS_BOT_CLIENT(it))
+               {
+                       if(prevbot)
+                               prevbot.nextbot = it;
+                       else
+                       {
+                               bot_list = it;
+                               bot_list.nextbot = NULL;
+                       }
+                       prevbot = it;
+                       ++currentbots;
+               }
+       });
+       LOG_TRACE("relink: ", ftos(currentbots), " bots seen.");
+       bot_strategytoken = bot_list;
+       bot_strategytoken_taken = true;
+}
+
+void bot_clientdisconnect(entity this)
+{
+       if (!IS_BOT_CLIENT(this))
+               return;
+       bot_clearqueue(this);
+       if(this.cleanname)
+               strunzone(this.cleanname);
+       if(this.netname_freeme)
+               strunzone(this.netname_freeme);
+       if(this.playermodel_freeme)
+               strunzone(this.playermodel_freeme);
+       if(this.playerskin_freeme)
+               strunzone(this.playerskin_freeme);
+       this.cleanname = string_null;
+       this.netname_freeme = string_null;
+       this.playermodel_freeme = string_null;
+       this.playerskin_freeme = string_null;
+       if(this.bot_cmd_current)
+               delete(this.bot_cmd_current);
+       if(bot_waypoint_queue_owner==this)
+               bot_waypoint_queue_owner = NULL;
+}
+
+void bot_clientconnect(entity this)
+{
+       if (!IS_BOT_CLIENT(this)) return;
+       this.bot_preferredcolors = this.clientcolors;
+       this.bot_nextthink = time - random();
+       this.lag_func = bot_lagfunc;
+       this.isbot = true;
+       this.createdtime = this.bot_nextthink;
+
+       if(!this.bot_config_loaded) // This is needed so team overrider doesn't break between matches
+               bot_setnameandstuff(this);
+
+       if(this.bot_forced_team==1)
+               this.team = NUM_TEAM_1;
+       else if(this.bot_forced_team==2)
+               this.team = NUM_TEAM_2;
+       else if(this.bot_forced_team==3)
+               this.team = NUM_TEAM_3;
+       else if(this.bot_forced_team==4)
+               this.team = NUM_TEAM_4;
+       else
+               JoinBestTeam(this, false, true);
+
+       havocbot_setupbot(this);
+}
+
+void bot_removefromlargestteam()
+{
+       CheckAllowedTeams(NULL);
+       GetTeamCounts(NULL);
+
+       entity best = NULL;
+       float besttime = 0;
+       int bestcount = 0;
+
+       int bcount = 0;
+       FOREACH_ENTITY_FLOAT(isbot, true,
+       {
+               ++bcount;
+
+               if(!best)
+               {
+                       best = it;
+                       besttime = it.createdtime;
+               }
+
+               int thiscount = 0;
+
+               switch(it.team)
+               {
+                       case NUM_TEAM_1: thiscount = c1; break;
+                       case NUM_TEAM_2: thiscount = c2; break;
+                       case NUM_TEAM_3: thiscount = c3; break;
+                       case NUM_TEAM_4: thiscount = c4; break;
+               }
+
+               if(thiscount > bestcount)
+               {
+                       bestcount = thiscount;
+                       besttime = it.createdtime;
+                       best = it;
+               }
+               else if(thiscount == bestcount && besttime < it.createdtime)
+               {
+                       besttime = it.createdtime;
+                       best = it;
+               }
+       });
+       if(!bcount)
+               return; // no bots to remove
+       currentbots = currentbots - 1;
+       dropclient(best);
+}
+
+void bot_removenewest()
+{
+       if(teamplay)
+       {
+               bot_removefromlargestteam();
+               return;
+       }
+
+       float besttime = 0;
+       entity best = NULL;
+       int bcount = 0;
+
+       FOREACH_ENTITY_FLOAT(isbot, true,
+       {
+               ++bcount;
+
+               if(!best)
+               {
+                       best = it;
+                       besttime = it.createdtime;
+               }
+
+               if(besttime < it.createdtime)
+               {
+                       besttime = it.createdtime;
+                       best = it;
+               }
+       });
+
+       if(!bcount)
+               return; // no bots to remove
+
+       currentbots = currentbots - 1;
+       dropclient(best);
+}
+
+void autoskill(float factor)
+{
+       float bestbot;
+       float bestplayer;
+
+       bestbot = -1;
+       bestplayer = -1;
+       FOREACH_CLIENT(IS_PLAYER(it), LAMBDA(
+               if(IS_REAL_CLIENT(it))
+                       bestplayer = max(bestplayer, it.totalfrags - it.totalfrags_lastcheck);
+               else
+                       bestbot = max(bestbot, it.totalfrags - it.totalfrags_lastcheck);
+       ));
+
+       LOG_TRACE("autoskill: best player got ", ftos(bestplayer), ", ");
+       LOG_TRACE("best bot got ", ftos(bestbot), "; ");
+       if(bestbot < 0 || bestplayer < 0)
+       {
+               LOG_TRACE("not doing anything");
+               // don't return, let it reset all counters below
+       }
+       else if(bestbot <= bestplayer * factor - 2)
+       {
+               if(autocvar_skill < 17)
+               {
+                       LOG_TRACE("2 frags difference, increasing skill");
+                       cvar_set("skill", ftos(autocvar_skill + 1));
+                       bprint("^2SKILL UP!^7 Now at level ", ftos(autocvar_skill), "\n");
+               }
+       }
+       else if(bestbot >= bestplayer * factor + 2)
+       {
+               if(autocvar_skill > 0)
+               {
+                       LOG_TRACE("2 frags difference, decreasing skill");
+                       cvar_set("skill", ftos(autocvar_skill - 1));
+                       bprint("^1SKILL DOWN!^7 Now at level ", ftos(autocvar_skill), "\n");
+               }
+       }
+       else
+       {
+               LOG_TRACE("not doing anything");
+               return;
+               // don't reset counters, wait for them to accumulate
+       }
+
+       FOREACH_CLIENT(IS_PLAYER(it), LAMBDA(it.totalfrags_lastcheck = it.totalfrags));
+}
+
+void bot_calculate_stepheightvec()
+{
+       stepheightvec = autocvar_sv_stepheight * '0 0 1';
+       jumpstepheightvec = stepheightvec +
+               ((autocvar_sv_jumpvelocity * autocvar_sv_jumpvelocity) / (2 * autocvar_sv_gravity)) * '0 0 0.85';
+               // 0.75 factor is for safety to make the jumps easy
+}
+
+float bot_fixcount()
+{
+       int activerealplayers = 0;
+       int realplayers = 0;
+       if (MUTATOR_CALLHOOK(Bot_FixCount, activerealplayers, realplayers)) {
+               activerealplayers = M_ARGV(0, int);
+               realplayers = M_ARGV(1, int);
+       } else {
+               FOREACH_CLIENT(IS_REAL_CLIENT(it), LAMBDA(
+                       if(IS_PLAYER(it))
+                               ++activerealplayers;
+                       ++realplayers;
+               ));
+       }
+
+       int bots;
+       // add/remove bots if needed to make sure there are at least
+       // minplayers+bot_number, or remove all bots if no one is playing
+       // But don't remove bots immediately on level change, as the real players
+       // usually haven't rejoined yet
+       bots_would_leave = false;
+       if (teamplay && autocvar_bot_vs_human && AvailableTeams() == 2)
+               bots = min(ceil(fabs(autocvar_bot_vs_human) * activerealplayers), maxclients - realplayers);
+       else if ((realplayers || autocvar_bot_join_empty || (currentbots > 0 && time < 5)))
+       {
+               float realminplayers, minplayers;
+               realminplayers = autocvar_minplayers;
+               minplayers = max(0, floor(realminplayers));
+
+               float realminbots, minbots;
+               realminbots = autocvar_bot_number;
+               minbots = max(0, floor(realminbots));
+
+               bots = min(max(minbots, minplayers - activerealplayers), maxclients - realplayers);
+               if(bots > minbots)
+                       bots_would_leave = true;
+       }
+       else
+       {
+               // if there are no players, remove bots
+               bots = 0;
+       }
+
+       // only add one bot per frame to avoid utter chaos
+       if(time > botframe_nextthink)
+       {
+               //dprint(ftos(bots), " ? ", ftos(currentbots), "\n");
+               while (currentbots < bots)
+               {
+                       if (bot_spawn() == NULL)
+                       {
+                               bprint("Can not add bot, server full.\n");
+                               return false;
+                       }
+               }
+               while (currentbots > bots)
+                       bot_removenewest();
+       }
+
+       return true;
+}
+
+void bot_serverframe()
+{
+       if (intermission_running)
+               return;
+
+       if (time < 2)
+               return;
+
+       bot_calculate_stepheightvec();
+       bot_navigation_movemode = ((autocvar_bot_navigation_ignoreplayers) ? MOVE_NOMONSTERS : MOVE_NORMAL);
+
+       if(time > autoskill_nextthink)
+       {
+               float a;
+               a = autocvar_skill_auto;
+               if(a)
+                       autoskill(a);
+               autoskill_nextthink = time + 5;
+       }
+
+       if(time > botframe_nextthink)
+       {
+               if(!bot_fixcount())
+                       botframe_nextthink = time + 10;
+       }
+
+       bot_ignore_bots = autocvar_bot_ignore_bots;
+
+       if(botframe_spawnedwaypoints)
+       {
+               if(autocvar_waypoint_benchmark)
+                       localcmd("quit\n");
+       }
+
+       if (currentbots > 0 || autocvar_g_waypointeditor || autocvar_g_waypointeditor_auto)
+       if (botframe_spawnedwaypoints)
+       {
+               if(botframe_cachedwaypointlinks)
+               {
+                       if(!botframe_loadedforcedlinks)
+                               waypoint_load_links_hardwired();
+               }
+               else
+               {
+                       // TODO: Make this check cleaner
+                       IL_EACH(g_waypoints, time - it.nextthink > 10,
+                       {
+                               waypoint_save_links();
+                               break;
+                       });
+               }
+       }
+       else
+       {
+               botframe_spawnedwaypoints = true;
+               waypoint_loadall();
+               if(!waypoint_load_links())
+                       waypoint_schedulerelinkall();
+       }
+
+       if (bot_list)
+       {
+               // cycle the goal token from one bot to the next each frame
+               // (this prevents them from all doing spawnfunc_waypoint searches on the same
+               //  frame, which causes choppy framerates)
+               if (bot_strategytoken_taken)
+               {
+                       bot_strategytoken_taken = false;
+                       if (bot_strategytoken)
+                               bot_strategytoken = bot_strategytoken.nextbot;
+                       if (!bot_strategytoken)
+                               bot_strategytoken = bot_list;
+               }
+
+               if (botframe_nextdangertime < time)
+               {
+                       float interval;
+                       interval = autocvar_bot_ai_dangerdetectioninterval;
+                       if (botframe_nextdangertime < time - interval * 1.5)
+                               botframe_nextdangertime = time;
+                       botframe_nextdangertime = botframe_nextdangertime + interval;
+                       botframe_updatedangerousobjects(autocvar_bot_ai_dangerdetectionupdates);
+               }
+       }
+
+       if (autocvar_g_waypointeditor)
+               botframe_showwaypointlinks();
+
+       if (autocvar_g_waypointeditor_auto)
+               botframe_autowaypoints();
+
+       if(time > bot_cvar_nextthink)
+       {
+               if(currentbots>0)
+                       bot_custom_weapon_priority_setup();
+               bot_cvar_nextthink = time + 5;
+       }
+}
diff --git a/qcsrc/server/bot/default/bot.qh b/qcsrc/server/bot/default/bot.qh
new file mode 100644 (file)
index 0000000..0959307
--- /dev/null
@@ -0,0 +1,108 @@
+#pragma once
+/*
+ * Globals and Fields
+ */
+
+const int AI_STATUS_ROAMING                                            = BIT(0);       // Bot is just crawling the map. No enemies at sight
+const int AI_STATUS_ATTACKING                                  = BIT(1);       // There are enemies at sight
+const int AI_STATUS_RUNNING                                            = BIT(2);       // Bot is bunny hopping
+const int AI_STATUS_DANGER_AHEAD                               = BIT(3);       // There is lava/slime/trigger_hurt ahead
+const int AI_STATUS_OUT_JUMPPAD                                        = BIT(4);       // Trying to get out of a "vertical" jump pad
+const int AI_STATUS_OUT_WATER                                  = BIT(5);       // Trying to get out of water
+const int AI_STATUS_WAYPOINT_PERSONAL_LINKING  = BIT(6);       // Waiting for the personal waypoint to be linked
+const int AI_STATUS_WAYPOINT_PERSONAL_GOING            = BIT(7);       // Going to a personal waypoint
+const int AI_STATUS_WAYPOINT_PERSONAL_REACHED  = BIT(8);       // Personal waypoint reached
+const int AI_STATUS_JETPACK_FLYING                             = BIT(9);
+const int AI_STATUS_JETPACK_LANDING                            = BIT(10);
+const int AI_STATUS_STUCK                                              = BIT(11);  // Cannot reach any goal
+
+.float isbot; // true if this client is actually a bot
+.int aistatus;
+
+// Skill system
+float autoskill_nextthink;
+
+// havocbot_keyboardskill // keyboard movement
+.float bot_moveskill; // moving technique
+.float bot_dodgeskill; // dodging
+
+.float bot_pingskill; // ping offset
+
+.float bot_weaponskill; // weapon usage skill (combos, e.g.)
+.float bot_aggresskill; // aggressivity, controls "think before fire" behaviour
+.float bot_rangepreference; // weapon choice offset for range (>0 = prefer long range earlier "sniper", <0 = prefer short range "spammer")
+
+.float bot_aimskill; // aim accuracy
+.float bot_offsetskill; // aim breakage
+.float bot_mouseskill; // mouse "speed"
+
+.float bot_thinkskill; // target choice
+.float bot_aiskill; // strategy choice
+
+.float totalfrags_lastcheck;
+
+// Custom weapon priorities
+float bot_distance_far;
+float bot_distance_close;
+
+entity bot_list;
+.entity nextbot;
+.string cleanname;
+.string netname_freeme;
+.string playermodel_freeme;
+.string playerskin_freeme;
+
+.float bot_nextthink;
+
+.float createdtime;
+.float bot_preferredcolors;
+.float bot_attack;
+.float bot_dodge;
+.float bot_dodgerating;
+
+.float bot_pickup;
+.float bot_pickupbasevalue;
+.float bot_canfire;
+.float bot_strategytime;
+
+.float bot_forced_team;
+.float bot_config_loaded;
+
+float bot_strategytoken_taken;
+entity bot_strategytoken;
+
+float botframe_spawnedwaypoints;
+float botframe_nextthink;
+float botframe_nextdangertime;
+float bot_cvar_nextthink;
+float bot_ignore_bots; // let bots not attack other bots (only works in non-teamplay)
+
+/*
+ * Functions
+ */
+
+entity bot_spawn();
+float bot_fixcount();
+
+void bot_think(entity this);
+void bot_setnameandstuff(entity this);
+void bot_custom_weapon_priority_setup();
+void bot_endgame();
+void bot_relinkplayerlist();
+void bot_clientdisconnect(entity this);
+void bot_clientconnect(entity this);
+void bot_removefromlargestteam();
+void bot_removenewest();
+void autoskill(float factor);
+void bot_serverframe();
+
+.void(entity this) bot_ai;
+.float(entity player, entity item) bot_pickupevalfunc;
+
+/*
+ * Imports
+ */
+
+void(entity this) havocbot_setupbot;
+
+void bot_calculate_stepheightvec();
diff --git a/qcsrc/server/bot/default/cvars.qc b/qcsrc/server/bot/default/cvars.qc
new file mode 100644 (file)
index 0000000..779e7f0
--- /dev/null
@@ -0,0 +1 @@
+#include "cvars.qh"
diff --git a/qcsrc/server/bot/default/cvars.qh b/qcsrc/server/bot/default/cvars.qh
new file mode 100644 (file)
index 0000000..d612c7a
--- /dev/null
@@ -0,0 +1,58 @@
+#pragma once
+
+float autocvar_bot_ai_aimskill_blendrate;
+float autocvar_bot_ai_aimskill_firetolerance_distdegrees;
+float autocvar_bot_ai_aimskill_firetolerance_maxdegrees;
+float autocvar_bot_ai_aimskill_firetolerance_mindegrees;
+float autocvar_bot_ai_aimskill_fixedrate;
+float autocvar_bot_ai_aimskill_mouse;
+float autocvar_bot_ai_aimskill_offset;
+float autocvar_bot_ai_aimskill_order_filter_1st;
+float autocvar_bot_ai_aimskill_order_filter_2nd;
+float autocvar_bot_ai_aimskill_order_filter_3th;
+float autocvar_bot_ai_aimskill_order_filter_4th;
+float autocvar_bot_ai_aimskill_order_filter_5th;
+float autocvar_bot_ai_aimskill_order_mix_1st;
+float autocvar_bot_ai_aimskill_order_mix_2nd;
+float autocvar_bot_ai_aimskill_order_mix_3th;
+float autocvar_bot_ai_aimskill_order_mix_4th;
+float autocvar_bot_ai_aimskill_order_mix_5th;
+float autocvar_bot_ai_aimskill_think;
+float autocvar_bot_ai_bunnyhop_firstjumpdelay;
+float autocvar_bot_ai_bunnyhop_skilloffset;
+float autocvar_bot_ai_bunnyhop_startdistance;
+float autocvar_bot_ai_bunnyhop_stopdistance;
+float autocvar_bot_ai_chooseweaponinterval;
+string autocvar_bot_ai_custom_weapon_priority_close;
+string autocvar_bot_ai_custom_weapon_priority_distances;
+string autocvar_bot_ai_custom_weapon_priority_far;
+string autocvar_bot_ai_custom_weapon_priority_mid;
+float autocvar_bot_ai_dangerdetectioninterval;
+float autocvar_bot_ai_dangerdetectionupdates;
+float autocvar_bot_ai_enemydetectioninterval;
+float autocvar_bot_ai_enemydetectionradius;
+float autocvar_bot_ai_friends_aware_pickup_radius;
+float autocvar_bot_ai_ignoregoal_timeout;
+float autocvar_bot_ai_keyboard_distance;
+float autocvar_bot_ai_keyboard_threshold;
+float autocvar_bot_ai_navigation_jetpack;
+float autocvar_bot_ai_navigation_jetpack_mindistance;
+float autocvar_bot_ai_thinkinterval;
+bool autocvar_bot_ai_weapon_combo;
+float autocvar_bot_ai_weapon_combo_threshold;
+string autocvar_bot_config_file;
+bool autocvar_bot_god;
+bool autocvar_bot_ignore_bots;
+bool autocvar_bot_join_empty;
+bool autocvar_bot_navigation_ignoreplayers;
+bool autocvar_bot_nofire;
+#define autocvar_bot_prefix cvar_string("bot_prefix")
+#define autocvar_bot_suffix cvar_string("bot_suffix")
+bool autocvar_bot_usemodelnames;
+bool autocvar_bot_debug_tracewalk;
+bool autocvar_bot_debug_goalstack;
+bool autocvar_bot_wander_enable;
+bool autocvar_g_debug_bot_commands;
+int autocvar_g_waypointeditor_auto;
+float autocvar_skill_auto;
+bool autocvar_waypoint_benchmark;
diff --git a/qcsrc/server/bot/default/havocbot/_mod.inc b/qcsrc/server/bot/default/havocbot/_mod.inc
new file mode 100644 (file)
index 0000000..3ecfda1
--- /dev/null
@@ -0,0 +1,3 @@
+// generated file; do not modify
+#include <server/bot/default/havocbot/havocbot.qc>
+#include <server/bot/default/havocbot/roles.qc>
diff --git a/qcsrc/server/bot/default/havocbot/_mod.qh b/qcsrc/server/bot/default/havocbot/_mod.qh
new file mode 100644 (file)
index 0000000..01fcd46
--- /dev/null
@@ -0,0 +1,3 @@
+// generated file; do not modify
+#include <server/bot/default/havocbot/havocbot.qh>
+#include <server/bot/default/havocbot/roles.qh>
diff --git a/qcsrc/server/bot/default/havocbot/havocbot.qc b/qcsrc/server/bot/default/havocbot/havocbot.qc
new file mode 100644 (file)
index 0000000..5ccc80a
--- /dev/null
@@ -0,0 +1,1298 @@
+#include "havocbot.qh"
+
+#include "../cvars.qh"
+
+#include "../aim.qh"
+#include "../bot.qh"
+#include "../navigation.qh"
+#include "../scripting.qh"
+#include "../waypoints.qh"
+
+#include <common/constants.qh>
+#include <common/physics/player.qh>
+#include <common/state.qh>
+#include <common/items/all.qh>
+
+#include <common/triggers/trigger/jumppads.qh>
+
+#include <lib/warpzone/common.qh>
+
+.float speed;
+
+void havocbot_ai(entity this)
+{
+       if(this.draggedby)
+               return;
+
+       if(bot_execute_commands(this))
+               return;
+
+       if (bot_strategytoken == this)
+       if (!bot_strategytoken_taken)
+       {
+               if(this.havocbot_blockhead)
+               {
+                       this.havocbot_blockhead = false;
+               }
+               else
+               {
+                       if (!this.jumppadcount)
+                               this.havocbot_role(this); // little too far down the rabbit hole
+               }
+
+               // TODO: tracewalk() should take care of this job (better path finding under water)
+               // if we don't have a goal and we're under water look for a waypoint near the "shore" and push it
+               if(IS_DEAD(this))
+               if(!this.goalcurrent)
+               if(this.waterlevel == WATERLEVEL_SWIMMING || (this.aistatus & AI_STATUS_OUT_WATER))
+               {
+                       // Look for the closest waypoint out of water
+                       entity newgoal = NULL;
+                       IL_EACH(g_waypoints, vdist(it.origin - this.origin, <=, 10000),
+                       {
+                               if(it.origin.z < this.origin.z)
+                                       continue;
+
+                               if(it.origin.z - this.origin.z - this.view_ofs.z > 100)
+                                       continue;
+
+                               if (pointcontents(it.origin + it.maxs + '0 0 1') != CONTENT_EMPTY)
+                                       continue;
+
+                               traceline(this.origin + this.view_ofs, ((it.absmin + it.absmax) * 0.5), true, this);
+
+                               if(trace_fraction < 1)
+                                       continue;
+
+                               if(!newgoal || vlen2(it.origin - this.origin) < vlen2(newgoal.origin - this.origin))
+                                       newgoal = it;
+                       });
+
+                       if(newgoal)
+                       {
+                       //      te_wizspike(newgoal.origin);
+                               navigation_pushroute(this, newgoal);
+                       }
+               }
+
+               // token has been used this frame
+               bot_strategytoken_taken = true;
+       }
+
+       if(IS_DEAD(this))
+               return;
+
+       havocbot_chooseenemy(this);
+       if (this.bot_chooseweapontime < time )
+       {
+               this.bot_chooseweapontime = time + autocvar_bot_ai_chooseweaponinterval;
+               havocbot_chooseweapon(this);
+       }
+       havocbot_aim(this);
+       lag_update(this);
+       if (this.bot_aimtarg)
+       {
+               this.aistatus |= AI_STATUS_ATTACKING;
+               this.aistatus &= ~AI_STATUS_ROAMING;
+
+               if(this.weapons)
+               {
+                       Weapon w = PS(this).m_weapon;
+                       w.wr_aim(w, this);
+                       if (autocvar_bot_nofire || IS_INDEPENDENT_PLAYER(this))
+                       {
+                               PHYS_INPUT_BUTTON_ATCK(this) = false;
+                               PHYS_INPUT_BUTTON_ATCK2(this) = false;
+                       }
+                       else
+                       {
+                               if(PHYS_INPUT_BUTTON_ATCK(this) || PHYS_INPUT_BUTTON_ATCK2(this))
+                                       this.lastfiredweapon = PS(this).m_weapon.m_id;
+                       }
+               }
+               else
+               {
+                       if(IS_PLAYER(this.bot_aimtarg))
+                               bot_aimdir(this, this.bot_aimtarg.origin + this.bot_aimtarg.view_ofs - this.origin - this.view_ofs , -1);
+               }
+       }
+       else if (this.goalcurrent)
+       {
+               this.aistatus |= AI_STATUS_ROAMING;
+               this.aistatus &= ~AI_STATUS_ATTACKING;
+
+               vector now,v,next;//,heading;
+               float aimdistance,skillblend,distanceblend,blend;
+               next = now = ( (this.goalcurrent.absmin + this.goalcurrent.absmax) * 0.5) - (this.origin + this.view_ofs);
+               aimdistance = vlen(now);
+               //heading = this.velocity;
+               //dprint(this.goalstack01.classname,etos(this.goalstack01),"\n");
+               if(
+                       this.goalstack01 != this && this.goalstack01 != NULL && ((this.aistatus & AI_STATUS_RUNNING) == 0) &&
+                       !(this.goalcurrent.wpflags & WAYPOINTFLAG_TELEPORT)
+               )
+                       next = ((this.goalstack01.absmin + this.goalstack01.absmax) * 0.5) - (this.origin + this.view_ofs);
+
+               skillblend=bound(0,(skill+this.bot_moveskill-2.5)*0.5,1); //lower skill player can't preturn
+               distanceblend=bound(0,aimdistance/autocvar_bot_ai_keyboard_distance,1);
+               blend = skillblend * (1-distanceblend);
+               //v = (now * (distanceblend) + next * (1-distanceblend)) * (skillblend) + now * (1-skillblend);
+               //v = now * (distanceblend) * (skillblend) + next * (1-distanceblend) * (skillblend) + now * (1-skillblend);
+               //v = now * ((1-skillblend) + (distanceblend) * (skillblend)) + next * (1-distanceblend) * (skillblend);
+               v = now + blend * (next - now);
+               //dprint(etos(this), " ");
+               //dprint(vtos(now), ":", vtos(next), "=", vtos(v), " (blend ", ftos(blend), ")\n");
+               //v = now * (distanceblend) + next * (1-distanceblend);
+               if (this.waterlevel < WATERLEVEL_SWIMMING)
+                       v.z = 0;
+               //dprint("walk at:", vtos(v), "\n");
+               //te_lightning2(NULL, this.origin, this.goalcurrent.origin);
+               bot_aimdir(this, v, -1);
+       }
+       havocbot_movetogoal(this);
+
+       // if the bot is not attacking, consider reloading weapons
+       if (!(this.aistatus & AI_STATUS_ATTACKING))
+       {
+               // 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(this.clip_load < this.clip_size)
+                       this.impulse = 20; // "press" the reload button, not sure if this is done right
+
+               // if we're not reloading a weapon, switch to any weapon in our invnetory that's not fully loaded to reload it next
+               // the code above executes next frame, starting the reloading then
+               if(skill >= 5) // bots can only look for unloaded weapons past this skill
+               if(this.clip_load >= 0) // only if we're not reloading a weapon already
+               {
+                       FOREACH(Weapons, it != WEP_Null, LAMBDA(
+                               if((this.weapons & (it.m_wepset)) && (it.spawnflags & WEP_FLAG_RELOADABLE) && (this.weapon_load[it.m_id] < it.reloading_ammo))
+                                       PS(this).m_switchweapon = it;
+                       ));
+               }
+       }
+}
+
+void havocbot_keyboard_movement(entity this, vector destorg)
+{
+       vector keyboard;
+       float blend, maxspeed;
+       float sk;
+
+       sk = skill + this.bot_moveskill;
+
+       maxspeed = autocvar_sv_maxspeed;
+
+       if (time < this.havocbot_keyboardtime)
+               return;
+
+       this.havocbot_keyboardtime =
+               max(
+                       this.havocbot_keyboardtime
+                               + 0.05/max(1, sk+this.havocbot_keyboardskill)
+                               + random()*0.025/max(0.00025, skill+this.havocbot_keyboardskill)
+               , time);
+       keyboard = this.movement * (1.0 / maxspeed);
+
+       float trigger, trigger1;
+       blend = bound(0,sk*0.1,1);
+       trigger = autocvar_bot_ai_keyboard_threshold;
+       trigger1 = 0 - trigger;
+
+       // categorize forward movement
+       // at skill < 1.5 only forward
+       // at skill < 2.5 only individual directions
+       // at skill < 4.5 only individual directions, and forward diagonals
+       // at skill >= 4.5, all cases allowed
+       if (keyboard.x > trigger)
+       {
+               keyboard.x = 1;
+               if (sk < 2.5)
+                       keyboard.y = 0;
+       }
+       else if (keyboard.x < trigger1 && sk > 1.5)
+       {
+               keyboard.x = -1;
+               if (sk < 4.5)
+                       keyboard.y = 0;
+       }
+       else
+       {
+               keyboard.x = 0;
+               if (sk < 1.5)
+                       keyboard.y = 0;
+       }
+       if (sk < 4.5)
+               keyboard.z = 0;
+
+       if (keyboard.y > trigger)
+               keyboard.y = 1;
+       else if (keyboard.y < trigger1)
+               keyboard.y = -1;
+       else
+               keyboard.y = 0;
+
+       if (keyboard.z > trigger)
+               keyboard.z = 1;
+       else if (keyboard.z < trigger1)
+               keyboard.z = -1;
+       else
+               keyboard.z = 0;
+
+       this.havocbot_keyboard = keyboard * maxspeed;
+       if (this.havocbot_ducktime>time) PHYS_INPUT_BUTTON_CROUCH(this) = true;
+
+       keyboard = this.havocbot_keyboard;
+       blend = bound(0,vlen(destorg-this.origin)/autocvar_bot_ai_keyboard_distance,1); // When getting close move with 360 degree
+       //dprint("movement ", vtos(this.movement), " keyboard ", vtos(keyboard), " blend ", ftos(blend), "\n");
+       this.movement = this.movement + (keyboard - this.movement) * blend;
+}
+
+void havocbot_bunnyhop(entity this, vector dir)
+{
+       float bunnyhopdistance;
+       vector deviation;
+       float maxspeed;
+       vector gco, gno;
+
+       // Don't jump when attacking
+       if(this.aistatus & AI_STATUS_ATTACKING)
+               return;
+
+       if(IS_PLAYER(this.goalcurrent))
+               return;
+
+       maxspeed = autocvar_sv_maxspeed;
+
+       if(this.aistatus & AI_STATUS_DANGER_AHEAD)
+       {
+               this.aistatus &= ~AI_STATUS_RUNNING;
+               PHYS_INPUT_BUTTON_JUMP(this) = false;
+               this.bot_canruntogoal = 0;
+               this.bot_timelastseengoal = 0;
+               return;
+       }
+
+       if(this.waterlevel > WATERLEVEL_WETFEET)
+       {
+               this.aistatus &= ~AI_STATUS_RUNNING;
+               return;
+       }
+
+       if(this.bot_lastseengoal != this.goalcurrent && !(this.aistatus & AI_STATUS_RUNNING))
+       {
+               this.bot_canruntogoal = 0;
+               this.bot_timelastseengoal = 0;
+       }
+
+       gco = (this.goalcurrent.absmin + this.goalcurrent.absmax) * 0.5;
+       bunnyhopdistance = vlen(this.origin - gco);
+
+       // Run only to visible goals
+       if(IS_ONGROUND(this))
+       if(this.speed==maxspeed)
+       if(checkpvs(this.origin + this.view_ofs, this.goalcurrent))
+       {
+                       this.bot_lastseengoal = this.goalcurrent;
+
+                       // seen it before
+                       if(this.bot_timelastseengoal)
+                       {
+                               // for a period of time
+                               if(time - this.bot_timelastseengoal > autocvar_bot_ai_bunnyhop_firstjumpdelay)
+                               {
+                                       float checkdistance;
+                                       checkdistance = true;
+
+                                       // don't run if it is too close
+                                       if(this.bot_canruntogoal==0)
+                                       {
+                                               if(bunnyhopdistance > autocvar_bot_ai_bunnyhop_startdistance)
+                                                       this.bot_canruntogoal = 1;
+                                               else
+                                                       this.bot_canruntogoal = -1;
+                                       }
+
+                                       if(this.bot_canruntogoal != 1)
+                                               return;
+
+                                       if(this.aistatus & AI_STATUS_ROAMING)
+                                       if(this.goalcurrent.classname=="waypoint")
+                                       if (!(this.goalcurrent.wpflags & WAYPOINTFLAG_PERSONAL))
+                                       if(fabs(gco.z - this.origin.z) < this.maxs.z - this.mins.z)
+                                       if(this.goalstack01!=NULL)
+                                       {
+                                               gno = (this.goalstack01.absmin + this.goalstack01.absmax) * 0.5;
+                                               deviation = vectoangles(gno - this.origin) - vectoangles(gco - this.origin);
+                                               while (deviation.y < -180) deviation.y = deviation.y + 360;
+                                               while (deviation.y > 180) deviation.y = deviation.y - 360;
+
+                                               if(fabs(deviation.y) < 20)
+                                               if(bunnyhopdistance < vlen(this.origin - gno))
+                                               if(fabs(gno.z - gco.z) < this.maxs.z - this.mins.z)
+                                               {
+                                                       if(vdist(gco - gno, >, autocvar_bot_ai_bunnyhop_startdistance))
+                                                       if(checkpvs(this.origin + this.view_ofs, this.goalstack01))
+                                                       {
+                                                               checkdistance = false;
+                                                       }
+                                               }
+                                       }
+
+                                       if(checkdistance)
+                                       {
+                                               this.aistatus &= ~AI_STATUS_RUNNING;
+                                               if(bunnyhopdistance > autocvar_bot_ai_bunnyhop_stopdistance)
+                                                       PHYS_INPUT_BUTTON_JUMP(this) = true;
+                                       }
+                                       else
+                                       {
+                                               this.aistatus |= AI_STATUS_RUNNING;
+                                               PHYS_INPUT_BUTTON_JUMP(this) = true;
+                                       }
+                               }
+                       }
+                       else
+                       {
+                               this.bot_timelastseengoal = time;
+                       }
+       }
+       else
+       {
+               this.bot_timelastseengoal = 0;
+       }
+
+#if 0
+       // Release jump button
+       if(!cvar("sv_pogostick"))
+       if((IS_ONGROUND(this)) == 0)
+       {
+               if(this.velocity.z < 0 || vlen(this.velocity)<maxspeed)
+                       PHYS_INPUT_BUTTON_JUMP(this) = false;
+
+               // Strafe
+               if(this.aistatus & AI_STATUS_RUNNING)
+               if(vlen(this.velocity)>maxspeed)
+               {
+                       deviation = vectoangles(dir) - vectoangles(this.velocity);
+                       while (deviation.y < -180) deviation.y = deviation.y + 360;
+                       while (deviation.y > 180) deviation.y = deviation.y - 360;
+
+                       if(fabs(deviation.y)>10)
+                               this.movement_x = 0;
+
+                       if(deviation.y>10)
+                               this.movement_y = maxspeed * -1;
+                       else if(deviation.y<10)
+                               this.movement_y = maxspeed;
+
+               }
+       }
+#endif
+}
+
+void havocbot_movetogoal(entity this)
+{
+       vector destorg;
+       vector diff;
+       vector dir;
+       vector flatdir;
+       vector m1;
+       vector m2;
+       vector evadeobstacle;
+       vector evadelava;
+       float s;
+       float maxspeed;
+       vector gco;
+       //float dist;
+       vector dodge;
+       //if (this.goalentity)
+       //      te_lightning2(this, this.origin, (this.goalentity.absmin + this.goalentity.absmax) * 0.5);
+       this.movement = '0 0 0';
+       maxspeed = autocvar_sv_maxspeed;
+
+       // Jetpack navigation
+       if(this.goalcurrent)
+       if(this.navigation_jetpack_goal)
+       if(this.goalcurrent==this.navigation_jetpack_goal)
+       if(this.ammo_fuel)
+       {
+               if(autocvar_bot_debug_goalstack)
+               {
+                       debuggoalstack(this);
+                       te_wizspike(this.navigation_jetpack_point);
+               }
+
+               // Take off
+               if (!(this.aistatus & AI_STATUS_JETPACK_FLYING))
+               {
+                       // Brake almost completely so it can get a good direction
+                       if(vdist(this.velocity, >, 10))
+                               return;
+                       this.aistatus |= AI_STATUS_JETPACK_FLYING;
+               }
+
+               makevectors(this.v_angle.y * '0 1 0');
+               dir = normalize(this.navigation_jetpack_point - this.origin);
+
+               // Landing
+               if(this.aistatus & AI_STATUS_JETPACK_LANDING)
+               {
+                       // Calculate brake distance in xy
+                       float db, v, d;
+                       vector dxy;
+
+                       dxy = this.origin - ( ( this.goalcurrent.absmin + this.goalcurrent.absmax ) * 0.5 ); dxy.z = 0;
+                       d = vlen(dxy);
+                       v = vlen(this.velocity -  this.velocity.z * '0 0 1');
+                       db = (pow(v,2) / (autocvar_g_jetpack_acceleration_side * 2)) + 100;
+               //      dprint("distance ", ftos(ceil(d)), " velocity ", ftos(ceil(v)), " brake at ", ftos(ceil(db)), "\n");
+                       if(d < db || d < 500)
+                       {
+                               // Brake
+                               if(fabs(this.velocity.x)>maxspeed*0.3)
+                               {
+                                       this.movement_x = dir * v_forward * -maxspeed;
+                                       return;
+                               }
+                               // Switch to normal mode
+                               this.navigation_jetpack_goal = NULL;
+                               this.aistatus &= ~AI_STATUS_JETPACK_LANDING;
+                               this.aistatus &= ~AI_STATUS_JETPACK_FLYING;
+                               return;
+                       }
+               }
+               else if(checkpvs(this.origin,this.goalcurrent))
+               {
+                       // If I can see the goal switch to landing code
+                       this.aistatus &= ~AI_STATUS_JETPACK_FLYING;
+                       this.aistatus |= AI_STATUS_JETPACK_LANDING;
+                       return;
+               }
+
+               // Flying
+               PHYS_INPUT_BUTTON_HOOK(this) = true;
+               if(this.navigation_jetpack_point.z - STAT(PL_MAX, NULL).z + STAT(PL_MIN, NULL).z < this.origin.z)
+               {
+                       this.movement_x = dir * v_forward * maxspeed;
+                       this.movement_y = dir * v_right * maxspeed;
+               }
+               return;
+       }
+
+       // Handling of jump pads
+       if(this.jumppadcount)
+       {
+               // If got stuck on the jump pad try to reach the farthest visible waypoint
+               if(this.aistatus & AI_STATUS_OUT_JUMPPAD)
+               {
+                       if(fabs(this.velocity.z)<50)
+                       {
+                               entity newgoal = NULL;
+                               IL_EACH(g_waypoints, vdist(it.origin - this.origin, <=, 1000),
+                               {
+                                       traceline(this.origin + this.view_ofs, ((it.absmin + it.absmax) * 0.5), true, this);
+
+                                       if(trace_fraction < 1)
+                                               continue;
+
+                                       if(!newgoal || vlen2(it.origin - this.origin) > vlen2(newgoal.origin - this.origin))
+                                               newgoal = it;
+                               });
+
+                               if(newgoal)
+                               {
+                                       this.ignoregoal = this.goalcurrent;
+                                       this.ignoregoaltime = time + autocvar_bot_ai_ignoregoal_timeout;
+                                       navigation_clearroute(this);
+                                       navigation_routetogoal(this, newgoal, this.origin);
+                                       this.aistatus &= ~AI_STATUS_OUT_JUMPPAD;
+                               }
+                       }
+                       else
+                               return;
+               }
+               else
+               {
+                       if(this.velocity.z>0)
+                       {
+                               float threshold;
+                               vector velxy = this.velocity; velxy_z = 0;
+                               threshold = maxspeed * 0.2;
+                               if(vdist(velxy, <, threshold))
+                               {
+                                       LOG_TRACE("Warning: ", this.netname, " got stuck on a jumppad (velocity in xy is ", vtos(velxy), "), trying to get out of it now");
+                                       this.aistatus |= AI_STATUS_OUT_JUMPPAD;
+                               }
+                               return;
+                       }
+
+                       // Don't chase players while using a jump pad
+                       if(IS_PLAYER(this.goalcurrent) || IS_PLAYER(this.goalstack01))
+                               return;
+               }
+       }
+       else if(this.aistatus & AI_STATUS_OUT_JUMPPAD)
+               this.aistatus &= ~AI_STATUS_OUT_JUMPPAD;
+
+       // If there is a trigger_hurt right below try to use the jetpack or make a rocketjump
+       if(skill>6)
+       if (!(IS_ONGROUND(this)))
+       {
+               tracebox(this.origin, this.mins, this.maxs, this.origin + '0 0 -65536', MOVE_NOMONSTERS, this);
+               if(tracebox_hits_trigger_hurt(this.origin, this.mins, this.maxs, trace_endpos ))
+               if(this.items & IT_JETPACK)
+               {
+                       tracebox(this.origin, this.mins, this.maxs, this.origin + '0 0 65536', MOVE_NOMONSTERS, this);
+                       if(tracebox_hits_trigger_hurt(this.origin, this.mins, this.maxs, trace_endpos + '0 0 1' ))
+                       {
+                               if(this.velocity.z<0)
+                               {
+                                       PHYS_INPUT_BUTTON_HOOK(this) = true;
+                               }
+                       }
+                       else
+                               PHYS_INPUT_BUTTON_HOOK(this) = true;
+
+                       // If there is no goal try to move forward
+
+                       if(this.goalcurrent==NULL)
+                               dir = v_forward;
+                       else
+                               dir = normalize(( ( this.goalcurrent.absmin + this.goalcurrent.absmax ) * 0.5 ) - this.origin);
+
+                       vector xyvelocity = this.velocity; xyvelocity_z = 0;
+                       float xyspeed = xyvelocity * dir;
+
+                       if(xyspeed < (maxspeed / 2))
+                       {
+                               makevectors(this.v_angle.y * '0 1 0');
+                               tracebox(this.origin, this.mins, this.maxs, this.origin + (dir * maxspeed * 3), MOVE_NOMONSTERS, this);
+                               if(trace_fraction==1)
+                               {
+                                       this.movement_x = dir * v_forward * maxspeed;
+                                       this.movement_y = dir * v_right * maxspeed;
+                                       if (skill < 10)
+                                               havocbot_keyboard_movement(this, this.origin + dir * 100);
+                               }
+                       }
+
+                       this.havocbot_blockhead = true;
+
+                       return;
+               }
+               else if(this.health>WEP_CVAR(devastator, damage)*0.5)
+               {
+                       if(this.velocity.z < 0)
+                       if(client_hasweapon(this, WEP_DEVASTATOR, true, false))
+                       {
+                               this.movement_x = maxspeed;
+
+                               if(this.rocketjumptime)
+                               {
+                                       if(time > this.rocketjumptime)
+                                       {
+                                               PHYS_INPUT_BUTTON_ATCK2(this) = true;
+                                               this.rocketjumptime = 0;
+                                       }
+                                       return;
+                               }
+
+                               PS(this).m_switchweapon = WEP_DEVASTATOR;
+                               this.v_angle_x = 90;
+                               PHYS_INPUT_BUTTON_ATCK(this) = true;
+                               this.rocketjumptime = time + WEP_CVAR(devastator, detonatedelay);
+                               return;
+                       }
+               }
+               else
+               {
+                       // If there is no goal try to move forward
+                       if(this.goalcurrent==NULL)
+                               this.movement_x = maxspeed;
+               }
+       }
+
+       // If we are under water with no goals, swim up
+       if(this.waterlevel)
+       if(this.goalcurrent==NULL)
+       {
+               dir = '0 0 0';
+               if(this.waterlevel>WATERLEVEL_SWIMMING)
+                       dir.z = 1;
+               else if(this.velocity.z >= 0 && !(this.waterlevel == WATERLEVEL_WETFEET && this.watertype == CONTENT_WATER))
+                       PHYS_INPUT_BUTTON_JUMP(this) = true;
+               else
+                       PHYS_INPUT_BUTTON_JUMP(this) = false;
+               makevectors(this.v_angle.y * '0 1 0');
+               this.movement_x = dir * v_forward * maxspeed;
+               this.movement_y = dir * v_right * maxspeed;
+               this.movement_z = dir * v_up * maxspeed;
+       }
+
+       // if there is nowhere to go, exit
+       if (this.goalcurrent == NULL)
+               return;
+
+       if (this.goalcurrent)
+               navigation_poptouchedgoals(this);
+
+       // if ran out of goals try to use an alternative goal or get a new strategy asap
+       if(this.goalcurrent == NULL)
+       {
+               this.bot_strategytime = 0;
+               return;
+       }
+
+
+       if(autocvar_bot_debug_goalstack)
+               debuggoalstack(this);
+
+       m1 = this.goalcurrent.origin + this.goalcurrent.mins;
+       m2 = this.goalcurrent.origin + this.goalcurrent.maxs;
+       destorg = this.origin;
+       destorg.x = bound(m1_x, destorg.x, m2_x);
+       destorg.y = bound(m1_y, destorg.y, m2_y);
+       destorg.z = bound(m1_z, destorg.z, m2_z);
+       diff = destorg - this.origin;
+       //dist = vlen(diff);
+       dir = normalize(diff);
+       flatdir = diff;flatdir.z = 0;
+       flatdir = normalize(flatdir);
+       gco = (this.goalcurrent.absmin + this.goalcurrent.absmax) * 0.5;
+
+       //if (this.bot_dodgevector_time < time)
+       {
+       //      this.bot_dodgevector_time = time + cvar("bot_ai_dodgeupdateinterval");
+       //      this.bot_dodgevector_jumpbutton = 1;
+               evadeobstacle = '0 0 0';
+               evadelava = '0 0 0';
+
+               if (this.waterlevel)
+               {
+                       if(this.waterlevel>WATERLEVEL_SWIMMING)
+                       {
+                       //      flatdir_z = 1;
+                               this.aistatus |= AI_STATUS_OUT_WATER;
+                       }
+                       else
+                       {
+                               if(this.velocity.z >= 0 && !(this.watertype == CONTENT_WATER && gco.z < this.origin.z) &&
+                                       ( !(this.waterlevel == WATERLEVEL_WETFEET && this.watertype == CONTENT_WATER) || this.aistatus & AI_STATUS_OUT_WATER))
+                                       PHYS_INPUT_BUTTON_JUMP(this) = true;
+                               else
+                                       PHYS_INPUT_BUTTON_JUMP(this) = false;
+                       }
+                       dir = normalize(flatdir);
+                       makevectors(this.v_angle.y * '0 1 0');
+               }
+               else
+               {
+                       if(this.aistatus & AI_STATUS_OUT_WATER)
+                               this.aistatus &= ~AI_STATUS_OUT_WATER;
+
+                       // jump if going toward an obstacle that doesn't look like stairs we
+                       // can walk up directly
+                       tracebox(this.origin, this.mins, this.maxs, this.origin + this.velocity * 0.2, false, this);
+                       if (trace_fraction < 1)
+                       if (trace_plane_normal.z < 0.7)
+                       {
+                               s = trace_fraction;
+                               tracebox(this.origin + stepheightvec, this.mins, this.maxs, this.origin + this.velocity * 0.2 + stepheightvec, false, this);
+                               if (trace_fraction < s + 0.01)
+                               if (trace_plane_normal.z < 0.7)
+                               {
+                                       s = trace_fraction;
+                                       tracebox(this.origin + jumpstepheightvec, this.mins, this.maxs, this.origin + this.velocity * 0.2 + jumpstepheightvec, false, this);
+                                       if (trace_fraction > s)
+                                               PHYS_INPUT_BUTTON_JUMP(this) = true;
+                               }
+                       }
+
+                       // avoiding dangers and obstacles
+                       vector dst_ahead, dst_down;
+                       makevectors(this.v_angle.y * '0 1 0');
+                       dst_ahead = this.origin + this.view_ofs + (this.velocity * 0.4) + (v_forward * 32 * 3);
+                       dst_down = dst_ahead - '0 0 1500';
+
+                       // Look ahead
+                       traceline(this.origin + this.view_ofs, dst_ahead, true, NULL);
+
+                       // Check head-banging against walls
+                       if(vdist(this.origin + this.view_ofs - trace_endpos, <, 25) && !(this.aistatus & AI_STATUS_OUT_WATER))
+                       {
+                               PHYS_INPUT_BUTTON_JUMP(this) = true;
+                               if(this.facingwalltime && time > this.facingwalltime)
+                               {
+                                       this.ignoregoal = this.goalcurrent;
+                                       this.ignoregoaltime = time + autocvar_bot_ai_ignoregoal_timeout;
+                                       this.bot_strategytime = 0;
+                                       return;
+                               }
+                               else
+                               {
+                                       this.facingwalltime = time + 0.05;
+                               }
+                       }
+                       else
+                       {
+                               this.facingwalltime = 0;
+
+                               if(this.ignoregoal != NULL && time > this.ignoregoaltime)
+                               {
+                                       this.ignoregoal = NULL;
+                                       this.ignoregoaltime = 0;
+                               }
+                       }
+
+                       // Check for water/slime/lava and dangerous edges
+                       // (only when the bot is on the ground or jumping intentionally)
+                       this.aistatus &= ~AI_STATUS_DANGER_AHEAD;
+
+                       if(trace_fraction == 1 && this.jumppadcount == 0 && !this.goalcurrent.wphardwired )
+                       if((IS_ONGROUND(this)) || (this.aistatus & AI_STATUS_RUNNING) || PHYS_INPUT_BUTTON_JUMP(this))
+                       {
+                               // Look downwards
+                               traceline(dst_ahead , dst_down, true, NULL);
+                       //      te_lightning2(NULL, this.origin, dst_ahead);    // Draw "ahead" look
+                       //      te_lightning2(NULL, dst_ahead, dst_down);               // Draw "downwards" look
+                               if(trace_endpos.z < this.origin.z + this.mins.z)
+                               {
+                                       s = pointcontents(trace_endpos + '0 0 1');
+                                       if (s != CONTENT_SOLID)
+                                       if (s == CONTENT_LAVA || s == CONTENT_SLIME)
+                                               evadelava = normalize(this.velocity) * -1;
+                                       else if (s == CONTENT_SKY)
+                                               evadeobstacle = normalize(this.velocity) * -1;
+                                       else if (!boxesoverlap(dst_ahead - this.view_ofs + this.mins, dst_ahead - this.view_ofs + this.maxs,
+                                                               this.goalcurrent.absmin, this.goalcurrent.absmax))
+                                       {
+                                               // if ain't a safe goal with "holes" (like the jumpad on soylent)
+                                               // and there is a trigger_hurt below
+                                               if(tracebox_hits_trigger_hurt(dst_ahead, this.mins, this.maxs, trace_endpos))
+                                               {
+                                                       // Remove dangerous dynamic goals from stack
+                                                       LOG_TRACE("bot ", this.netname, " avoided the goal ", this.goalcurrent.classname, " ", etos(this.goalcurrent), " because it led to a dangerous path; goal stack cleared");
+                                                       navigation_clearroute(this);
+                                                       return;
+                                               }
+                                       }
+                               }
+                       }
+
+                       dir = flatdir;
+                       evadeobstacle.z = 0;
+                       evadelava.z = 0;
+                       makevectors(this.v_angle.y * '0 1 0');
+
+                       if(evadeobstacle!='0 0 0'||evadelava!='0 0 0')
+                               this.aistatus |= AI_STATUS_DANGER_AHEAD;
+               }
+
+               dodge = havocbot_dodge(this);
+               dodge = dodge * bound(0,0.5+(skill+this.bot_dodgeskill)*0.1,1);
+               evadelava = evadelava * bound(1,3-(skill+this.bot_dodgeskill),3); //Noobs fear lava a lot and take more distance from it
+               traceline(this.origin, ( ( this.enemy.absmin + this.enemy.absmax ) * 0.5 ), true, NULL);
+               if(IS_PLAYER(trace_ent))
+                       dir = dir * bound(0,(skill+this.bot_dodgeskill)/7,1);
+
+               dir = normalize(dir + dodge + evadeobstacle + evadelava);
+       //      this.bot_dodgevector = dir;
+       //      this.bot_dodgevector_jumpbutton = PHYS_INPUT_BUTTON_JUMP(this);
+       }
+
+       if(time < this.ladder_time)
+       {
+               if(this.goalcurrent.origin.z + this.goalcurrent.mins.z > this.origin.z + this.mins.z)
+               {
+                       if(this.origin.z + this.mins.z  < this.ladder_entity.origin.z + this.ladder_entity.maxs.z)
+                               dir.z = 1;
+               }
+               else
+               {
+                       if(this.origin.z + this.mins.z  > this.ladder_entity.origin.z + this.ladder_entity.mins.z)
+                               dir.z = -1;
+               }
+       }
+
+       //dir = this.bot_dodgevector;
+       //if (this.bot_dodgevector_jumpbutton)
+       //      PHYS_INPUT_BUTTON_JUMP(this) = true;
+       this.movement_x = dir * v_forward * maxspeed;
+       this.movement_y = dir * v_right * maxspeed;
+       this.movement_z = dir * v_up * maxspeed;
+
+       // Emulate keyboard interface
+       if (skill < 10)
+               havocbot_keyboard_movement(this, destorg);
+
+       // Bunnyhop!
+//     if(this.aistatus & AI_STATUS_ROAMING)
+       if(this.goalcurrent)
+       if(skill+this.bot_moveskill >= autocvar_bot_ai_bunnyhop_skilloffset)
+               havocbot_bunnyhop(this, dir);
+
+       if ((dir * v_up) >= autocvar_sv_jumpvelocity*0.5 && (IS_ONGROUND(this))) PHYS_INPUT_BUTTON_JUMP(this) = true;
+       if (((dodge * v_up) > 0) && random()*frametime >= 0.2*bound(0,(10-skill-this.bot_dodgeskill)*0.1,1)) PHYS_INPUT_BUTTON_JUMP(this) = true;
+       if (((dodge * v_up) < 0) && random()*frametime >= 0.5*bound(0,(10-skill-this.bot_dodgeskill)*0.1,1)) this.havocbot_ducktime=time+0.3/bound(0.1,skill+this.bot_dodgeskill,10);
+}
+
+void havocbot_chooseenemy(entity this)
+{
+       entity head, best, head2;
+       float rating, bestrating, hf;
+       vector eye, v;
+       if (autocvar_bot_nofire || IS_INDEPENDENT_PLAYER(this))
+       {
+               this.enemy = NULL;
+               return;
+       }
+       if (this.enemy)
+       {
+               if (!bot_shouldattack(this, this.enemy))
+               {
+                       // enemy died or something, find a new target
+                       this.enemy = NULL;
+                       this.havocbot_chooseenemy_finished = time;
+               }
+               else if (this.havocbot_stickenemy)
+               {
+                       // tracking last chosen enemy
+                       // if enemy is visible
+                       // and not really really far away
+                       // and we're not severely injured
+                       // then keep tracking for a half second into the future
+                       traceline(this.origin+this.view_ofs, ( this.enemy.absmin + this.enemy.absmax ) * 0.5,false,NULL);
+                       if (trace_ent == this.enemy || trace_fraction == 1)
+                       if (vdist(((this.enemy.absmin + this.enemy.absmax) * 0.5) - this.origin, <, 1000))
+                       if (this.health > 30)
+                       {
+                               // remain tracking him for a shot while (case he went after a small corner or pilar
+                               this.havocbot_chooseenemy_finished = time + 0.5;
+                               return;
+                       }
+                       // enemy isn't visible, or is far away, or we're injured severely
+                       // so stop preferring this enemy
+                       // (it will still take a half second until a new one is chosen)
+                       this.havocbot_stickenemy = 0;
+               }
+       }
+       if (time < this.havocbot_chooseenemy_finished)
+               return;
+       this.havocbot_chooseenemy_finished = time + autocvar_bot_ai_enemydetectioninterval;
+       eye = this.origin + this.view_ofs;
+       best = NULL;
+       bestrating = 100000000;
+       head = head2 = findchainfloat(bot_attack, true);
+
+       // Backup hit flags
+       hf = this.dphitcontentsmask;
+
+       // Search for enemies, if no enemy can be seen directly try to look through transparent objects
+
+       this.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_CORPSE;
+
+       bool scan_transparent = false;
+       bool scan_secondary_targets = false;
+       bool have_secondary_targets = false;
+       while(true)
+       {
+               scan_secondary_targets = false;
+LABEL(scan_targets)
+               for( ; head; head = head.chain)
+               {
+                       if(!scan_secondary_targets)
+                       {
+                               if(head.classname == "misc_breakablemodel")
+                               {
+                                       have_secondary_targets = true;
+                                       continue;
+                               }
+                       }
+                       else
+                       {
+                               if(head.classname != "misc_breakablemodel")
+                                       continue;
+                       }
+
+                       v = (head.absmin + head.absmax) * 0.5;
+                       rating = vlen(v - eye);
+                       if (rating<autocvar_bot_ai_enemydetectionradius)
+                       if (bestrating > rating)
+                       if (bot_shouldattack(this, head))
+                       {
+                               traceline(eye, v, true, this);
+                               if (trace_ent == head || trace_fraction >= 1)
+                               {
+                                       best = head;
+                                       bestrating = rating;
+                               }
+                       }
+               }
+
+               if(!best && have_secondary_targets && !scan_secondary_targets)
+               {
+                       scan_secondary_targets = true;
+                       // restart the loop
+                       head = head2;
+                       bestrating = 100000000;
+                       goto scan_targets;
+               }
+
+               // I want to do a second scan if no enemy was found or I don't have weapons
+               // TODO: Perform the scan when using the rifle (requires changes on the rifle code)
+               if(best || this.weapons) // || this.weapon == WEP_RIFLE.m_id
+                       break;
+               if(scan_transparent)
+                       break;
+
+               // Set flags to see through transparent objects
+               this.dphitcontentsmask |= DPCONTENTS_OPAQUE;
+
+               head = head2;
+               scan_transparent = true;
+       }
+
+       // Restore hit flags
+       this.dphitcontentsmask = hf;
+
+       this.enemy = best;
+       this.havocbot_stickenemy = true;
+       if(best && best.classname == "misc_breakablemodel")
+               this.havocbot_stickenemy = false;
+}
+
+float havocbot_chooseweapon_checkreload(entity this, int new_weapon)
+{
+       // bots under this skill cannot find unloaded weapons to reload idly when not in combat,
+       // so skip this for them, or they'll never get to reload their weapons at all.
+       // this also allows bots under this skill to be more stupid, and reload more often during combat :)
+       if(skill < 5)
+               return false;
+
+       // if this weapon is scheduled for reloading, don't switch to it during combat
+       if (this.weapon_load[new_weapon] < 0)
+       {
+               bool other_weapon_available = false;
+               FOREACH(Weapons, it != WEP_Null, LAMBDA(
+                       if(it.wr_checkammo1(it, this) + it.wr_checkammo2(it, this))
+                               other_weapon_available = true;
+               ));
+               if(other_weapon_available)
+                       return true;
+       }
+
+       return false;
+}
+
+void havocbot_chooseweapon(entity this)
+{
+       int i;
+
+       // ;)
+       if(g_weaponarena_weapons == WEPSET(TUBA))
+       {
+               PS(this).m_switchweapon = WEP_TUBA;
+               return;
+       }
+
+       // TODO: clean this up by moving it to weapon code
+       if(this.enemy==NULL)
+       {
+               // If no weapon was chosen get the first available weapon
+               if(PS(this).m_weapon==WEP_Null)
+               FOREACH(Weapons, it != WEP_Null, LAMBDA(
+                       if(client_hasweapon(this, it, true, false))
+                       {
+                               PS(this).m_switchweapon = it;
+                               return;
+                       }
+               ));
+               return;
+       }
+
+       // Do not change weapon during the next second after a combo
+       float f = time - this.lastcombotime;
+       if(f < 1)
+               return;
+
+       float w;
+       float distance; distance=bound(10,vlen(this.origin-this.enemy.origin)-200,10000);
+
+       // Should it do a weapon combo?
+       float af, ct, combo_time, combo;
+
+       af = ATTACK_FINISHED(this, 0);
+       ct = autocvar_bot_ai_weapon_combo_threshold;
+
+       // Bots with no skill will be 4 times more slower than "godlike" bots when doing weapon combos
+       // Ideally this 4 should be calculated as longest_weapon_refire / bot_ai_weapon_combo_threshold
+       combo_time = time + ct + (ct * ((-0.3*(skill+this.bot_weaponskill))+3));
+
+       combo = false;
+
+       if(autocvar_bot_ai_weapon_combo)
+       if(PS(this).m_weapon.m_id == this.lastfiredweapon)
+       if(af > combo_time)
+       {
+               combo = true;
+               this.lastcombotime = time;
+       }
+
+       distance *= pow(2, this.bot_rangepreference);
+
+       // Custom weapon list based on distance to the enemy
+       if(bot_custom_weapon){
+
+               // Choose weapons for far distance
+               if ( distance > bot_distance_far ) {
+                       for(i=0; i < Weapons_COUNT && bot_weapons_far[i] != -1 ; ++i){
+                               w = bot_weapons_far[i];
+                               if ( client_hasweapon(this, Weapons_from(w), true, false) )
+                               {
+                                       if ((PS(this).m_weapon.m_id == w && combo) || havocbot_chooseweapon_checkreload(this, w))
+                                               continue;
+                                       PS(this).m_switchweapon = Weapons_from(w);
+                                       return;
+                               }
+                       }
+               }
+
+               // Choose weapons for mid distance
+               if ( distance > bot_distance_close) {
+                       for(i=0; i < Weapons_COUNT && bot_weapons_mid[i] != -1 ; ++i){
+                               w = bot_weapons_mid[i];
+                               if ( client_hasweapon(this, Weapons_from(w), true, false) )
+                               {
+                                       if ((PS(this).m_weapon.m_id == w && combo) || havocbot_chooseweapon_checkreload(this, w))
+                                               continue;
+                                       PS(this).m_switchweapon = Weapons_from(w);
+                                       return;
+                               }
+                       }
+               }
+
+               // Choose weapons for close distance
+               for(i=0; i < Weapons_COUNT && bot_weapons_close[i] != -1 ; ++i){
+                       w = bot_weapons_close[i];
+                       if ( client_hasweapon(this, Weapons_from(w), true, false) )
+                       {
+                               if ((PS(this).m_weapon.m_id == w && combo) || havocbot_chooseweapon_checkreload(this, w))
+                                       continue;
+                               PS(this).m_switchweapon = Weapons_from(w);
+                               return;
+                       }
+               }
+       }
+}
+
+void havocbot_aim(entity this)
+{
+       vector myvel, enemyvel;
+//     if(this.flags & FL_INWATER)
+//             return;
+       if (time < this.nextaim)
+               return;
+       this.nextaim = time + 0.1;
+       myvel = this.velocity;
+       if (!this.waterlevel)
+               myvel.z = 0;
+       if (this.enemy)
+       {
+               enemyvel = this.enemy.velocity;
+               if (!this.enemy.waterlevel)
+                       enemyvel.z = 0;
+               lag_additem(this, time + this.ping, 0, 0, this.enemy, this.origin, myvel, (this.enemy.absmin + this.enemy.absmax) * 0.5, enemyvel);
+       }
+       else
+               lag_additem(this, time + this.ping, 0, 0, NULL, this.origin, myvel, ( this.goalcurrent.absmin + this.goalcurrent.absmax ) * 0.5, '0 0 0');
+}
+
+bool havocbot_moveto_refresh_route(entity this)
+{
+       // Refresh path to goal if necessary
+       entity wp;
+       wp = this.havocbot_personal_waypoint;
+       navigation_goalrating_start(this);
+       navigation_routerating(this, wp, 10000, 10000);
+       navigation_goalrating_end(this);
+       return this.navigation_hasgoals;
+}
+
+float havocbot_moveto(entity this, vector pos)
+{
+       entity wp;
+
+       if(this.aistatus & AI_STATUS_WAYPOINT_PERSONAL_GOING)
+       {
+               // Step 4: Move to waypoint
+               if(this.havocbot_personal_waypoint==NULL)
+               {
+                       LOG_TRACE("Error: ", this.netname, " trying to walk to a non existent personal waypoint");
+                       this.aistatus &= ~AI_STATUS_WAYPOINT_PERSONAL_GOING;
+                       return CMD_STATUS_ERROR;
+               }
+
+               if (!bot_strategytoken_taken)
+               if(this.havocbot_personal_waypoint_searchtime<time)
+               {
+                       bot_strategytoken_taken = true;
+                       if(havocbot_moveto_refresh_route(this))
+                       {
+                               LOG_TRACE(this.netname, " walking to its personal waypoint (after ", ftos(this.havocbot_personal_waypoint_failcounter), " failed attempts)");
+                               this.havocbot_personal_waypoint_searchtime = time + 10;
+                               this.havocbot_personal_waypoint_failcounter = 0;
+                       }
+                       else
+                       {
+                               this.havocbot_personal_waypoint_failcounter += 1;
+                               this.havocbot_personal_waypoint_searchtime = time + 2;
+                               if(this.havocbot_personal_waypoint_failcounter >= 30)
+                               {
+                                       LOG_TRACE("Warning: can't walk to the personal waypoint located at ", vtos(this.havocbot_personal_waypoint.origin));
+                                       this.aistatus &= ~AI_STATUS_WAYPOINT_PERSONAL_LINKING;
+                                       delete(this.havocbot_personal_waypoint);
+                                       return CMD_STATUS_ERROR;
+                               }
+                               else
+                                       LOG_TRACE(this.netname, " can't walk to its personal waypoint (after ", ftos(this.havocbot_personal_waypoint_failcounter), " failed attempts), trying later");
+                       }
+               }
+
+               if(autocvar_bot_debug_goalstack)
+                       debuggoalstack(this);
+
+               // Heading
+               vector dir = ( ( this.goalcurrent.absmin + this.goalcurrent.absmax ) * 0.5 ) - (this.origin + this.view_ofs);
+               dir.z = 0;
+               bot_aimdir(this, dir, -1);
+
+               // Go!
+               havocbot_movetogoal(this);
+
+               if(this.aistatus & AI_STATUS_WAYPOINT_PERSONAL_REACHED)
+               {
+                       // Step 5: Waypoint reached
+                       LOG_TRACE(this.netname, "'s personal waypoint reached");
+                       delete(this.havocbot_personal_waypoint);
+                       this.aistatus &= ~AI_STATUS_WAYPOINT_PERSONAL_REACHED;
+                       return CMD_STATUS_FINISHED;
+               }
+
+               return CMD_STATUS_EXECUTING;
+       }
+
+       // Step 2: Linking waypoint
+       if(this.aistatus & AI_STATUS_WAYPOINT_PERSONAL_LINKING)
+       {
+               // Wait until it is linked
+               if(!this.havocbot_personal_waypoint.wplinked)
+               {
+                       LOG_TRACE(this.netname, " waiting for personal waypoint to be linked");
+                       return CMD_STATUS_EXECUTING;
+               }
+
+               this.havocbot_personal_waypoint_searchtime = time; // so we set the route next frame
+               this.aistatus &= ~AI_STATUS_WAYPOINT_PERSONAL_LINKING;
+               this.aistatus |= AI_STATUS_WAYPOINT_PERSONAL_GOING;
+
+               // Step 3: Route to waypoint
+               LOG_TRACE(this.netname, " walking to its personal waypoint");
+
+               return CMD_STATUS_EXECUTING;
+       }
+
+       // Step 1: Spawning waypoint
+       wp = waypoint_spawnpersonal(this, pos);
+       if(wp==NULL)
+       {
+               LOG_TRACE("Error: Can't spawn personal waypoint at ",vtos(pos));
+               return CMD_STATUS_ERROR;
+       }
+
+       this.havocbot_personal_waypoint = wp;
+       this.havocbot_personal_waypoint_failcounter = 0;
+       this.aistatus |= AI_STATUS_WAYPOINT_PERSONAL_LINKING;
+
+       // if pos is inside a teleport, then let's mark it as teleport waypoint
+       FOREACH_ENTITY_CLASS("trigger_teleport", WarpZoneLib_BoxTouchesBrush(pos, pos, it, NULL),
+       {
+               wp.wpflags |= WAYPOINTFLAG_TELEPORT;
+               this.lastteleporttime = 0;
+       });
+
+/*
+       if(wp.wpflags & WAYPOINTFLAG_TELEPORT)
+               print("routing to a teleporter\n");
+       else
+               print("routing to a non-teleporter\n");
+*/
+
+       return CMD_STATUS_EXECUTING;
+}
+
+float havocbot_resetgoal(entity this)
+{
+       navigation_clearroute(this);
+       return CMD_STATUS_FINISHED;
+}
+
+void havocbot_setupbot(entity this)
+{
+       this.bot_ai = havocbot_ai;
+       this.cmd_moveto = havocbot_moveto;
+       this.cmd_resetgoal = havocbot_resetgoal;
+
+       havocbot_chooserole(this);
+}
+
+vector havocbot_dodge(entity this)
+{
+       // LordHavoc: disabled because this is too expensive
+       return '0 0 0';
+#if 0
+       entity head;
+       vector dodge, v, n;
+       float danger, bestdanger, vl, d;
+       dodge = '0 0 0';
+       bestdanger = -20;
+       // check for dangerous objects near bot or approaching bot
+       head = findchainfloat(bot_dodge, true);
+       while(head)
+       {
+               if (head.owner != this)
+               {
+                       vl = vlen(head.velocity);
+                       if (vl > autocvar_sv_maxspeed * 0.3)
+                       {
+                               n = normalize(head.velocity);
+                               v = this.origin - head.origin;
+                               d = v * n;
+                               if (d > (0 - head.bot_dodgerating))
+                               if (d < (vl * 0.2 + head.bot_dodgerating))
+                               {
+                                       // calculate direction and distance from the flight path, by removing the forward axis
+                                       v = v - (n * (v * n));
+                                       danger = head.bot_dodgerating - vlen(v);
+                                       if (bestdanger < danger)
+                                       {
+                                               bestdanger = danger;
+                                               // dodge to the side of the object
+                                               dodge = normalize(v);
+                                       }
+                               }
+                       }
+                       else
+                       {
+                               danger = head.bot_dodgerating - vlen(head.origin - this.origin);
+                               if (bestdanger < danger)
+                               {
+                                       bestdanger = danger;
+                                       dodge = normalize(this.origin - head.origin);
+                               }
+                       }
+               }
+               head = head.chain;
+       }
+       return dodge;
+#endif
+}
diff --git a/qcsrc/server/bot/default/havocbot/havocbot.qh b/qcsrc/server/bot/default/havocbot/havocbot.qh
new file mode 100644 (file)
index 0000000..4a391b6
--- /dev/null
@@ -0,0 +1,64 @@
+#pragma once
+
+/*
+ * Globals and Fields
+ */
+
+.float havocbot_keyboardskill;
+.float facingwalltime, ignoregoaltime;
+.float lastfiredweapon;
+.float lastcombotime;
+.float havocbot_blockhead;
+
+.float havocbot_keyboardtime;
+.float havocbot_ducktime;
+.float bot_timelastseengoal;
+.float bot_canruntogoal;
+.float bot_chooseweapontime;
+.float rocketjumptime;
+.float nextaim;
+.float havocbot_personal_waypoint_searchtime;
+.float havocbot_personal_waypoint_failcounter;
+.float havocbot_chooseenemy_finished;
+.float havocbot_stickenemy;
+.float havocbot_role_timeout;
+
+.entity ignoregoal;
+.entity bot_lastseengoal;
+.entity havocbot_personal_waypoint;
+
+.vector havocbot_keyboard;
+
+/*
+ * Functions
+ */
+
+void havocbot_ai(entity this);
+void havocbot_aim(entity this);
+void havocbot_setupbot(entity this);
+void havocbot_movetogoal(entity this);
+void havocbot_chooserole(entity this);
+void havocbot_chooseenemy(entity this);
+void havocbot_chooseweapon(entity this);
+void havocbot_bunnyhop(entity this, vector dir);
+void havocbot_keyboard_movement(entity this, vector destorg);
+
+float havocbot_resetgoal(entity this);
+float havocbot_moveto(entity this, vector pos);
+float havocbot_moveto_refresh_route(entity this);
+
+vector havocbot_dodge(entity this);
+
+.void(entity this) havocbot_role;
+.void(entity this) havocbot_previous_role;
+
+void(entity this, float ratingscale, vector org, float sradius) havocbot_goalrating_items;
+void(entity this, float ratingscale, vector org, float sradius) havocbot_goalrating_enemyplayers;
+
+/*
+ * Imports
+ */
+
+.entity draggedby;
+.float ladder_time;
+.entity ladder_entity;
diff --git a/qcsrc/server/bot/default/havocbot/roles.qc b/qcsrc/server/bot/default/havocbot/roles.qc
new file mode 100644 (file)
index 0000000..771ab28
--- /dev/null
@@ -0,0 +1,210 @@
+#include "roles.qh"
+
+#include "havocbot.qh"
+
+#include "../cvars.qh"
+
+#include "../bot.qh"
+#include "../navigation.qh"
+
+.float max_armorvalue;
+.float havocbot_role_timeout;
+
+.void(entity this) havocbot_previous_role;
+.void(entity this) havocbot_role;
+
+void havocbot_goalrating_items(entity this, float ratingscale, vector org, float sradius)
+{
+       float rating, d, discard, friend_distance, enemy_distance;
+       vector o;
+       ratingscale = ratingscale * 0.0001; // items are rated around 10000 already
+
+       FOREACH_ENTITY_FLOAT(bot_pickup, true,
+       {
+               o = (it.absmin + it.absmax) * 0.5;
+               friend_distance = 10000; enemy_distance = 10000;
+               rating = 0;
+
+               if(!it.solid || vdist(o - org, >, sradius) || (it == this.ignoregoal && time < this.ignoregoaltime) )
+                       continue;
+
+               // Check if the item can be picked up safely
+               if(it.classname == "droppedweapon")
+               {
+                       traceline(o, o + '0 0 -1500', true, NULL);
+
+                       d = pointcontents(trace_endpos + '0 0 1');
+                       if(d & CONTENT_WATER || d & CONTENT_SLIME || d & CONTENT_LAVA)
+                               continue;
+                       if(tracebox_hits_trigger_hurt(it.origin, it.mins, it.maxs, trace_endpos))
+                               continue;
+               }
+               else
+               {
+                       // Ignore items under water
+                       traceline(it.origin + it.maxs, it.origin + it.maxs, MOVE_NORMAL, it);
+                       if(trace_dpstartcontents & DPCONTENTS_LIQUIDSMASK)
+                               continue;
+               }
+
+               if(teamplay)
+               {
+                       discard = false;
+
+                       entity picker = it;
+                       FOREACH_CLIENT(IS_PLAYER(it) && it != this && !IS_DEAD(it),
+                       {
+                               d = vlen(it.origin - o); // distance between player and item
+
+                               if ( it.team == this.team )
+                               {
+                                       if ( !IS_REAL_CLIENT(it) || discard )
+                                               continue;
+
+                                       if( d > friend_distance)
+                                               continue;
+
+                                       friend_distance = d;
+
+                                       discard = true;
+
+                                       if( picker.health && it.health > this.health )
+                                               continue;
+
+                                       if( picker.armorvalue && it.armorvalue > this.armorvalue)
+                                               continue;
+
+                                       if( picker.weapons )
+                                       if( picker.weapons & ~it.weapons )
+                                               continue;
+
+                                       if (picker.ammo_shells && it.ammo_shells > this.ammo_shells)
+                                               continue;
+
+                                       if (picker.ammo_nails && it.ammo_nails > this.ammo_nails)
+                                               continue;
+
+                                       if (picker.ammo_rockets && it.ammo_rockets > this.ammo_rockets)
+                                               continue;
+
+                                       if (picker.ammo_cells && it.ammo_cells > this.ammo_cells)
+                                               continue;
+
+                                       if (picker.ammo_plasma && it.ammo_plasma > this.ammo_plasma)
+                                               continue;
+
+                                       discard = false;
+                               }
+                               else
+                               {
+                                       // If enemy only track distances
+                                       // TODO: track only if visible ?
+                                       if( d < enemy_distance )
+                                               enemy_distance = d;
+                               }
+                       });
+
+                       // Rate the item only if no one needs it, or if an enemy is closer to it
+                       if ( (enemy_distance < friend_distance && vdist(o - org, <, enemy_distance)) ||
+                               (friend_distance > autocvar_bot_ai_friends_aware_pickup_radius ) || !discard )
+                               rating = it.bot_pickupevalfunc(this, it);
+
+               }
+               else
+                       rating = it.bot_pickupevalfunc(this, it);
+
+               if(rating > 0)
+                       navigation_routerating(this, it, rating * ratingscale, 2000);
+       });
+}
+
+void havocbot_goalrating_controlpoints(entity this, float ratingscale, vector org, float sradius)
+{
+       FOREACH_ENTITY_CLASS("dom_controlpoint", vdist((((it.absmin + it.absmax) * 0.5) - org), <, sradius),
+       {
+               if(it.cnt > -1) // this is just being fought
+                       navigation_routerating(this, it, ratingscale, 5000);
+               else if(it.goalentity.cnt == 0) // unclaimed
+                       navigation_routerating(this, it, ratingscale * 0.5, 5000);
+               else if(it.goalentity.team != this.team) // other team's point
+                       navigation_routerating(this, it, ratingscale * 0.2, 5000);
+       });
+}
+
+void havocbot_goalrating_enemyplayers(entity this, float ratingscale, vector org, float sradius)
+{
+       if (autocvar_bot_nofire)
+               return;
+
+       // don't chase players if we're under water
+       if(this.waterlevel>WATERLEVEL_WETFEET)
+               return;
+
+       int t;
+
+       FOREACH_CLIENT(IS_PLAYER(it) && bot_shouldattack(this, it), LAMBDA(
+               // TODO: Merge this logic with the bot_shouldattack function
+               if(vdist(it.origin - org, <, 100) || vdist(it.origin - org, >, sradius))
+                       continue;
+
+               // rate only visible enemies
+               /*
+               traceline(this.origin + this.view_ofs, it.origin, MOVE_NOMONSTERS, this);
+               if (trace_fraction < 1 || trace_ent != it)
+                       continue;
+               */
+
+               if((it.flags & FL_INWATER) || (it.flags & FL_PARTIALGROUND))
+                       continue;
+
+               // not falling
+               if((IS_ONGROUND(it)) == 0)
+               {
+                       traceline(it.origin, it.origin + '0 0 -1500', true, NULL);
+                       t = pointcontents(trace_endpos + '0 0 1');
+                       if(t != CONTENT_SOLID )
+                       if(t & CONTENT_WATER || t & CONTENT_SLIME || t & CONTENT_LAVA)
+                               continue;
+                       if(tracebox_hits_trigger_hurt(it.origin, it.mins, it.maxs, trace_endpos))
+                               continue;
+               }
+
+               // TODO: rate waypoints near the targetted player at that moment, instead of the player itthis
+               //               adding a player as a goal seems to be quite dangerous, especially on space maps
+               //               remove hack in navigation_poptouchedgoals() after performing this change
+
+               t = (this.health + this.armorvalue ) / (it.health + it.armorvalue );
+               navigation_routerating(this, it, t * ratingscale, 2000);
+       ));
+}
+
+// legacy bot role for standard gamemodes
+// go to best items
+void havocbot_role_generic(entity this)
+{
+       if(IS_DEAD(this))
+               return;
+
+       if (this.bot_strategytime < time)
+       {
+               this.bot_strategytime = time + autocvar_bot_ai_strategyinterval;
+               navigation_goalrating_start(this);
+               havocbot_goalrating_items(this, 10000, this.origin, 10000);
+               havocbot_goalrating_enemyplayers(this, 20000, this.origin, 10000);
+               //havocbot_goalrating_waypoints(1, this.origin, 1000);
+               navigation_goalrating_end(this);
+       }
+}
+
+void havocbot_chooserole_generic(entity this)
+{
+       this.havocbot_role = havocbot_role_generic;
+}
+
+void havocbot_chooserole(entity this)
+{
+       LOG_TRACE("choosing a role...");
+       this.bot_strategytime = 0;
+       if(!MUTATOR_CALLHOOK(HavocBot_ChooseRole, this))
+               havocbot_chooserole_generic(this);
+}
diff --git a/qcsrc/server/bot/default/havocbot/roles.qh b/qcsrc/server/bot/default/havocbot/roles.qh
new file mode 100644 (file)
index 0000000..5b1f2b5
--- /dev/null
@@ -0,0 +1,2 @@
+#pragma once
+void havocbot_goalrating_controlpoints(entity this, float ratingscale, vector org, float sradius);
diff --git a/qcsrc/server/bot/default/havocbot/scripting.qh b/qcsrc/server/bot/default/havocbot/scripting.qh
new file mode 100644 (file)
index 0000000..07cb4d6
--- /dev/null
@@ -0,0 +1,3 @@
+#pragma once
+
+void bot_clearqueue(entity bot);
diff --git a/qcsrc/server/bot/default/navigation.qc b/qcsrc/server/bot/default/navigation.qc
new file mode 100644 (file)
index 0000000..1d18a58
--- /dev/null
@@ -0,0 +1,1213 @@
+#include "navigation.qh"
+
+#include "cvars.qh"
+
+#include "bot.qh"
+#include "waypoints.qh"
+
+#include <common/t_items.qh>
+
+#include <common/items/all.qh>
+
+#include <common/constants.qh>
+#include <common/triggers/trigger/jumppads.qh>
+
+.float speed;
+
+// rough simulation of walking from one point to another to test if a path
+// can be traveled, used for waypoint linking and havocbot
+
+bool tracewalk(entity e, vector start, vector m1, vector m2, vector end, float movemode)
+{
+       vector org;
+       vector move;
+       vector dir;
+       float dist;
+       float totaldist;
+       float stepdist;
+       float yaw;
+       float ignorehazards;
+       float swimming;
+
+       if(autocvar_bot_debug_tracewalk)
+       {
+               debugresetnodes();
+               debugnode(e, start);
+       }
+
+       move = end - start;
+       move.z = 0;
+       org = start;
+       dist = totaldist = vlen(move);
+       dir = normalize(move);
+       stepdist = 32;
+       ignorehazards = false;
+       swimming = false;
+
+       // Analyze starting point
+       traceline(start, start, MOVE_NORMAL, e);
+       if (trace_dpstartcontents & (DPCONTENTS_SLIME | DPCONTENTS_LAVA))
+               ignorehazards = true;
+       else
+       {
+               traceline( start, start + '0 0 -65536', MOVE_NORMAL, e);
+               if (trace_dpstartcontents & (DPCONTENTS_SLIME | DPCONTENTS_LAVA))
+               {
+                       ignorehazards = true;
+                       swimming = true;
+               }
+       }
+       tracebox(start, m1, m2, start, MOVE_NOMONSTERS, e);
+       if (trace_startsolid)
+       {
+               // Bad start
+               if(autocvar_bot_debug_tracewalk)
+                       debugnodestatus(start, DEBUG_NODE_FAIL);
+
+               //print("tracewalk: ", vtos(start), " is a bad start\n");
+               return false;
+       }
+
+       // Movement loop
+       yaw = vectoyaw(move);
+       move = end - org;
+       for (;;)
+       {
+               if (boxesoverlap(end, end, org + m1 + '-1 -1 -1', org + m2 + '1 1 1'))
+               {
+                       // Succeeded
+                       if(autocvar_bot_debug_tracewalk)
+                               debugnodestatus(org, DEBUG_NODE_SUCCESS);
+
+                       //print("tracewalk: ", vtos(start), " can reach ", vtos(end), "\n");
+                       return true;
+               }
+               if(autocvar_bot_debug_tracewalk)
+                       debugnode(e, org);
+
+               if (dist <= 0)
+                       break;
+               if (stepdist > dist)
+                       stepdist = dist;
+               dist = dist - stepdist;
+               traceline(org, org, MOVE_NORMAL, e);
+               if (!ignorehazards)
+               {
+                       if (trace_dpstartcontents & (DPCONTENTS_SLIME | DPCONTENTS_LAVA))
+                       {
+                               // hazards blocking path
+                               if(autocvar_bot_debug_tracewalk)
+                                       debugnodestatus(org, DEBUG_NODE_FAIL);
+
+                               //print("tracewalk: ", vtos(start), " hits a hazard when trying to reach ", vtos(end), "\n");
+                               return false;
+                       }
+               }
+               if (trace_dpstartcontents & DPCONTENTS_LIQUIDSMASK)
+               {
+                       move = normalize(end - org);
+                       tracebox(org, m1, m2, org + move * stepdist, movemode, e);
+
+                       if(autocvar_bot_debug_tracewalk)
+                               debugnode(e, trace_endpos);
+
+                       if (trace_fraction < 1)
+                       {
+                               swimming = true;
+                               org = trace_endpos - normalize(org - trace_endpos) * stepdist;
+                               for (; org.z < end.z + e.maxs.z; org.z += stepdist)
+                               {
+                                               if(autocvar_bot_debug_tracewalk)
+                                                       debugnode(e, org);
+
+                                       if(pointcontents(org) == CONTENT_EMPTY)
+                                                       break;
+                               }
+
+                               if(pointcontents(org + '0 0 1') != CONTENT_EMPTY)
+                               {
+                                       if(autocvar_bot_debug_tracewalk)
+                                               debugnodestatus(org, DEBUG_NODE_FAIL);
+
+                                       return false;
+                                       //print("tracewalk: ", vtos(start), " failed under water\n");
+                               }
+                               continue;
+
+                       }
+                       else
+                               org = trace_endpos;
+               }
+               else
+               {
+                       move = dir * stepdist + org;
+                       tracebox(org, m1, m2, move, movemode, e);
+
+                       if(autocvar_bot_debug_tracewalk)
+                               debugnode(e, trace_endpos);
+
+                       // hit something
+                       if (trace_fraction < 1)
+                       {
+                               // check if we can walk over this obstacle, possibly by jumpstepping
+                               tracebox(org + stepheightvec, m1, m2, move + stepheightvec, movemode, e);
+                               if (trace_fraction < 1 || trace_startsolid)
+                               {
+                                       tracebox(org + jumpstepheightvec, m1, m2, move + jumpstepheightvec, movemode, e);
+                                       if (trace_fraction < 1 || trace_startsolid)
+                                       {
+                                               if(autocvar_bot_debug_tracewalk)
+                                                       debugnodestatus(trace_endpos, DEBUG_NODE_WARNING);
+
+                                               // check for doors
+                                               traceline( org, move, movemode, e);
+                                               if ( trace_ent.classname == "door_rotating" || trace_ent.classname == "door")
+                                               {
+                                                       vector nextmove;
+                                                       move = trace_endpos;
+                                                       while(trace_ent.classname == "door_rotating" || trace_ent.classname == "door")
+                                                       {
+                                                               nextmove = move + (dir * stepdist);
+                                                               traceline( move, nextmove, movemode, e);
+                                                               move = nextmove;
+                                                       }
+                                               }
+                                               else
+                                               {
+                                                       if(autocvar_bot_debug_tracewalk)
+                                                               debugnodestatus(trace_endpos, DEBUG_NODE_FAIL);
+
+                                                       //print("tracewalk: ", vtos(start), " hit something when trying to reach ", vtos(end), "\n");
+                                                       //te_explosion(trace_endpos);
+                                                       //print(ftos(e.dphitcontentsmask), "\n");
+                                                       return false; // failed
+                                               }
+                                       }
+                                       else
+                                               move = trace_endpos;
+                               }
+                               else
+                                       move = trace_endpos;
+                       }
+                       else
+                               move = trace_endpos;
+
+                       // trace down from stepheight as far as possible and move there,
+                       // if this starts in solid we try again without the stepup, and
+                       // if that also fails we assume it is a wall
+                       // (this is the same logic as the Quake walkmove function used)
+                       tracebox(move, m1, m2, move + '0 0 -65536', movemode, e);
+
+                       // moved successfully
+                       if(swimming)
+                       {
+                               float c;
+                               c = pointcontents(org + '0 0 1');
+                               if (!(c == CONTENT_WATER || c == CONTENT_LAVA || c == CONTENT_SLIME))
+                                       swimming = false;
+                               else
+                                       continue;
+                       }
+
+                       org = trace_endpos;
+               }
+       }
+
+       //print("tracewalk: ", vtos(start), " did not arrive at ", vtos(end), " but at ", vtos(org), "\n");
+
+       // moved but didn't arrive at the intended destination
+       if(autocvar_bot_debug_tracewalk)
+               debugnodestatus(org, DEBUG_NODE_FAIL);
+
+       return false;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// goal stack
+/////////////////////////////////////////////////////////////////////////////
+
+// completely empty the goal stack, used when deciding where to go
+void navigation_clearroute(entity this)
+{
+       //print("bot ", etos(this), " clear\n");
+       this.navigation_hasgoals = false;
+       this.goalcurrent = NULL;
+       this.goalstack01 = NULL;
+       this.goalstack02 = NULL;
+       this.goalstack03 = NULL;
+       this.goalstack04 = NULL;
+       this.goalstack05 = NULL;
+       this.goalstack06 = NULL;
+       this.goalstack07 = NULL;
+       this.goalstack08 = NULL;
+       this.goalstack09 = NULL;
+       this.goalstack10 = NULL;
+       this.goalstack11 = NULL;
+       this.goalstack12 = NULL;
+       this.goalstack13 = NULL;
+       this.goalstack14 = NULL;
+       this.goalstack15 = NULL;
+       this.goalstack16 = NULL;
+       this.goalstack17 = NULL;
+       this.goalstack18 = NULL;
+       this.goalstack19 = NULL;
+       this.goalstack20 = NULL;
+       this.goalstack21 = NULL;
+       this.goalstack22 = NULL;
+       this.goalstack23 = NULL;
+       this.goalstack24 = NULL;
+       this.goalstack25 = NULL;
+       this.goalstack26 = NULL;
+       this.goalstack27 = NULL;
+       this.goalstack28 = NULL;
+       this.goalstack29 = NULL;
+       this.goalstack30 = NULL;
+       this.goalstack31 = NULL;
+}
+
+// add a new goal at the beginning of the stack
+// (in other words: add a new prerequisite before going to the later goals)
+// NOTE: when a waypoint is added, the WP gets pushed first, then the
+// next-closest WP on the shortest path to the WP
+// That means, if the stack overflows, the bot will know how to do the FIRST 32
+// steps to the goal, and then recalculate the path.
+void navigation_pushroute(entity this, entity e)
+{
+       //print("bot ", etos(this), " push ", etos(e), "\n");
+       this.goalstack31 = this.goalstack30;
+       this.goalstack30 = this.goalstack29;
+       this.goalstack29 = this.goalstack28;
+       this.goalstack28 = this.goalstack27;
+       this.goalstack27 = this.goalstack26;
+       this.goalstack26 = this.goalstack25;
+       this.goalstack25 = this.goalstack24;
+       this.goalstack24 = this.goalstack23;
+       this.goalstack23 = this.goalstack22;
+       this.goalstack22 = this.goalstack21;
+       this.goalstack21 = this.goalstack20;
+       this.goalstack20 = this.goalstack19;
+       this.goalstack19 = this.goalstack18;
+       this.goalstack18 = this.goalstack17;
+       this.goalstack17 = this.goalstack16;
+       this.goalstack16 = this.goalstack15;
+       this.goalstack15 = this.goalstack14;
+       this.goalstack14 = this.goalstack13;
+       this.goalstack13 = this.goalstack12;
+       this.goalstack12 = this.goalstack11;
+       this.goalstack11 = this.goalstack10;
+       this.goalstack10 = this.goalstack09;
+       this.goalstack09 = this.goalstack08;
+       this.goalstack08 = this.goalstack07;
+       this.goalstack07 = this.goalstack06;
+       this.goalstack06 = this.goalstack05;
+       this.goalstack05 = this.goalstack04;
+       this.goalstack04 = this.goalstack03;
+       this.goalstack03 = this.goalstack02;
+       this.goalstack02 = this.goalstack01;
+       this.goalstack01 = this.goalcurrent;
+       this.goalcurrent = e;
+}
+
+// remove first goal from stack
+// (in other words: remove a prerequisite for reaching the later goals)
+// (used when a spawnfunc_waypoint is reached)
+void navigation_poproute(entity this)
+{
+       //print("bot ", etos(this), " pop\n");
+       this.goalcurrent = this.goalstack01;
+       this.goalstack01 = this.goalstack02;
+       this.goalstack02 = this.goalstack03;
+       this.goalstack03 = this.goalstack04;
+       this.goalstack04 = this.goalstack05;
+       this.goalstack05 = this.goalstack06;
+       this.goalstack06 = this.goalstack07;
+       this.goalstack07 = this.goalstack08;
+       this.goalstack08 = this.goalstack09;
+       this.goalstack09 = this.goalstack10;
+       this.goalstack10 = this.goalstack11;
+       this.goalstack11 = this.goalstack12;
+       this.goalstack12 = this.goalstack13;
+       this.goalstack13 = this.goalstack14;
+       this.goalstack14 = this.goalstack15;
+       this.goalstack15 = this.goalstack16;
+       this.goalstack16 = this.goalstack17;
+       this.goalstack17 = this.goalstack18;
+       this.goalstack18 = this.goalstack19;
+       this.goalstack19 = this.goalstack20;
+       this.goalstack20 = this.goalstack21;
+       this.goalstack21 = this.goalstack22;
+       this.goalstack22 = this.goalstack23;
+       this.goalstack23 = this.goalstack24;
+       this.goalstack24 = this.goalstack25;
+       this.goalstack25 = this.goalstack26;
+       this.goalstack26 = this.goalstack27;
+       this.goalstack27 = this.goalstack28;
+       this.goalstack28 = this.goalstack29;
+       this.goalstack29 = this.goalstack30;
+       this.goalstack30 = this.goalstack31;
+       this.goalstack31 = NULL;
+}
+
+float navigation_waypoint_will_link(vector v, vector org, entity ent, float walkfromwp, float bestdist)
+{
+       float dist;
+       dist = vlen(v - org);
+       if (bestdist > dist)
+       {
+               traceline(v, org, true, ent);
+               if (trace_fraction == 1)
+               {
+                       if (walkfromwp)
+                       {
+                               if (tracewalk(ent, v, STAT(PL_MIN, NULL), STAT(PL_MAX, NULL), org, bot_navigation_movemode))
+                                       return true;
+                       }
+                       else
+                       {
+                               if (tracewalk(ent, org, STAT(PL_MIN, NULL), STAT(PL_MAX, NULL), v, bot_navigation_movemode))
+                                       return true;
+                       }
+               }
+       }
+       return false;
+}
+
+// find the spawnfunc_waypoint near a dynamic goal such as a dropped weapon
+entity navigation_findnearestwaypoint_withdist_except(entity ent, float walkfromwp, float bestdist, entity except)
+{
+       vector pm1 = ent.origin + ent.mins;
+       vector pm2 = ent.origin + ent.maxs;
+
+       // do two scans, because box test is cheaper
+       IL_EACH(g_waypoints, it != ent && it != except,
+       {
+               if(boxesoverlap(pm1, pm2, it.absmin, it.absmax))
+                       return it;
+       });
+
+       vector org = ent.origin + 0.5 * (ent.mins + ent.maxs);
+       org.z = ent.origin.z + ent.mins.z - STAT(PL_MIN, NULL).z; // player height
+       // TODO possibly make other code have the same support for bboxes
+       if(ent.tag_entity)
+               org = org + ent.tag_entity.origin;
+       if (navigation_testtracewalk)
+               te_plasmaburn(org);
+
+       entity best = NULL;
+       vector v;
+
+       // box check failed, try walk
+       IL_EACH(g_waypoints, it != ent,
+       {
+               if(it.wpisbox)
+               {
+                       vector wm1 = it.origin + it.mins;
+                       vector wm2 = it.origin + it.maxs;
+                       v.x = bound(wm1_x, org.x, wm2_x);
+                       v.y = bound(wm1_y, org.y, wm2_y);
+                       v.z = bound(wm1_z, org.z, wm2_z);
+               }
+               else
+                       v = it.origin;
+               if(navigation_waypoint_will_link(v, org, ent, walkfromwp, bestdist))
+               {
+                       bestdist = vlen(v - org);
+                       best = it;
+               }
+       });
+       return best;
+}
+entity navigation_findnearestwaypoint(entity ent, float walkfromwp)
+{
+       entity wp = navigation_findnearestwaypoint_withdist_except(ent, walkfromwp, 1050, NULL);
+       if (autocvar_g_waypointeditor_auto)
+       {
+               entity wp2 = navigation_findnearestwaypoint_withdist_except(ent, walkfromwp, 1050, wp);
+               if (wp && !wp2)
+                       wp.wpflags |= WAYPOINTFLAG_PROTECTED;
+       }
+       return wp;
+}
+
+// finds the waypoints near the bot initiating a navigation query
+float navigation_markroutes_nearestwaypoints(entity this, float maxdist)
+{
+       vector v, m1, m2;
+//     navigation_testtracewalk = true;
+       int c = 0;
+       IL_EACH(g_waypoints, !it.wpconsidered,
+       {
+               if (it.wpisbox)
+               {
+                       m1 = it.origin + it.mins;
+                       m2 = it.origin + it.maxs;
+                       v = this.origin;
+                       v.x = bound(m1_x, v.x, m2_x);
+                       v.y = bound(m1_y, v.y, m2_y);
+                       v.z = bound(m1_z, v.z, m2_z);
+               }
+               else
+                       v = it.origin;
+               vector diff = v - this.origin;
+               diff.z = max(0, diff.z);
+               if(vdist(diff, <, maxdist))
+               {
+                       it.wpconsidered = true;
+                       if (tracewalk(this, this.origin, this.mins, this.maxs, v, bot_navigation_movemode))
+                       {
+                               it.wpnearestpoint = v;
+                               it.wpcost = vlen(v - this.origin) + it.dmg;
+                               it.wpfire = 1;
+                               it.enemy = NULL;
+                               c = c + 1;
+                       }
+               }
+       });
+       //navigation_testtracewalk = false;
+       return c;
+}
+
+// updates a path link if a spawnfunc_waypoint link is better than the current one
+void navigation_markroutes_checkwaypoint(entity w, entity wp, float cost2, vector p)
+{
+       vector m1;
+       vector m2;
+       vector v;
+       if (wp.wpisbox)
+       {
+               m1 = wp.absmin;
+               m2 = wp.absmax;
+               v.x = bound(m1_x, p.x, m2_x);
+               v.y = bound(m1_y, p.y, m2_y);
+               v.z = bound(m1_z, p.z, m2_z);
+       }
+       else
+               v = wp.origin;
+       cost2 = cost2 + vlen(v - p);
+       if (wp.wpcost > cost2)
+       {
+               wp.wpcost = cost2;
+               wp.enemy = w;
+               wp.wpfire = 1;
+               wp.wpnearestpoint = v;
+       }
+}
+
+// queries the entire spawnfunc_waypoint network for pathes leading away from the bot
+void navigation_markroutes(entity this, entity fixed_source_waypoint)
+{
+       float cost, cost2;
+       vector p;
+
+       IL_EACH(g_waypoints, true,
+       {
+               it.wpconsidered = false;
+               it.wpnearestpoint = '0 0 0';
+               it.wpcost = 10000000;
+               it.wpfire = 0;
+               it.enemy = NULL;
+       });
+
+       if(fixed_source_waypoint)
+       {
+               fixed_source_waypoint.wpconsidered = true;
+               fixed_source_waypoint.wpnearestpoint = fixed_source_waypoint.origin + 0.5 * (fixed_source_waypoint.mins + fixed_source_waypoint.maxs);
+               fixed_source_waypoint.wpcost = fixed_source_waypoint.dmg;
+               fixed_source_waypoint.wpfire = 1;
+               fixed_source_waypoint.enemy = NULL;
+       }
+       else
+       {
+               // try a short range search for the nearest waypoints, and expand the search repeatedly if none are found
+               // as this search is expensive we will use lower values if the bot is on the air
+               float increment, maxdistance;
+               if(IS_ONGROUND(this))
+               {
+                       increment = 750;
+                       maxdistance = 50000;
+               }
+               else
+               {
+                       increment = 500;
+                       maxdistance = 1500;
+               }
+
+               for(int j = increment; !navigation_markroutes_nearestwaypoints(this, j) && j < maxdistance; j += increment);
+       }
+
+       bool searching = true;
+       while (searching)
+       {
+               searching = false;
+               IL_EACH(g_waypoints, it.wpfire,
+               {
+                       searching = true;
+                       it.wpfire = 0;
+                       cost = it.wpcost;
+                       p = it.wpnearestpoint;
+                       entity wp;
+                       wp = it.wp00;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp00mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
+                       wp = it.wp01;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp01mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
+                       wp = it.wp02;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp02mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
+                       wp = it.wp03;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp03mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
+                       wp = it.wp04;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp04mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
+                       wp = it.wp05;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp05mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
+                       wp = it.wp06;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp06mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
+                       wp = it.wp07;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp07mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
+                       wp = it.wp08;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp08mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
+                       wp = it.wp09;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp09mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
+                       wp = it.wp10;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp10mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
+                       wp = it.wp11;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp11mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
+                       wp = it.wp12;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp12mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
+                       wp = it.wp13;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp13mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
+                       wp = it.wp14;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp14mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
+                       wp = it.wp15;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp15mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
+                       wp = it.wp16;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp16mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
+                       wp = it.wp17;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp17mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
+                       wp = it.wp18;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp18mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
+                       wp = it.wp19;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp19mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
+                       wp = it.wp20;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp20mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
+                       wp = it.wp21;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp21mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
+                       wp = it.wp22;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp22mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
+                       wp = it.wp23;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp23mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
+                       wp = it.wp24;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp24mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
+                       wp = it.wp25;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp25mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
+                       wp = it.wp26;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp26mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
+                       wp = it.wp27;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp27mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
+                       wp = it.wp28;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp28mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
+                       wp = it.wp29;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp29mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
+                       wp = it.wp30;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp30mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
+                       wp = it.wp31;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp31mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
+                       }}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}
+               });
+       }
+}
+
+// queries the entire spawnfunc_waypoint network for pathes leading to the bot
+void navigation_markroutes_inverted(entity fixed_source_waypoint)
+{
+       float cost, cost2;
+       vector p;
+       IL_EACH(g_waypoints, true,
+       {
+               it.wpconsidered = false;
+               it.wpnearestpoint = '0 0 0';
+               it.wpcost = 10000000;
+               it.wpfire = 0;
+               it.enemy = NULL;
+       });
+
+       if(fixed_source_waypoint)
+       {
+               fixed_source_waypoint.wpconsidered = true;
+               fixed_source_waypoint.wpnearestpoint = fixed_source_waypoint.origin + 0.5 * (fixed_source_waypoint.mins + fixed_source_waypoint.maxs);
+               fixed_source_waypoint.wpcost = fixed_source_waypoint.dmg; // the cost to get from X to fixed_source_waypoint
+               fixed_source_waypoint.wpfire = 1;
+               fixed_source_waypoint.enemy = NULL;
+       }
+       else
+       {
+               error("need to start with a waypoint\n");
+       }
+
+       bool searching = true;
+       while (searching)
+       {
+               searching = false;
+               IL_EACH(g_waypoints, it.wpfire,
+               {
+                       searching = true;
+                       it.wpfire = 0;
+                       cost = it.wpcost; // cost to walk from it to home
+                       p = it.wpnearestpoint;
+                       entity wp = it;
+                       IL_EACH(g_waypoints, true,
+                       {
+                               if(wp != it.wp00) if(wp != it.wp01) if(wp != it.wp02) if(wp != it.wp03)
+                               if(wp != it.wp04) if(wp != it.wp05) if(wp != it.wp06) if(wp != it.wp07)
+                               if(wp != it.wp08) if(wp != it.wp09) if(wp != it.wp10) if(wp != it.wp11)
+                               if(wp != it.wp12) if(wp != it.wp13) if(wp != it.wp14) if(wp != it.wp15)
+                               if(wp != it.wp16) if(wp != it.wp17) if(wp != it.wp18) if(wp != it.wp19)
+                               if(wp != it.wp20) if(wp != it.wp21) if(wp != it.wp22) if(wp != it.wp23)
+                               if(wp != it.wp24) if(wp != it.wp25) if(wp != it.wp26) if(wp != it.wp27)
+                               if(wp != it.wp28) if(wp != it.wp29) if(wp != it.wp30) if(wp != it.wp31)
+                                       continue;
+                               cost2 = cost + it.dmg;
+                               navigation_markroutes_checkwaypoint(wp, it, cost2, p);
+                       });
+               });
+       }
+}
+
+// updates the best goal according to a weighted calculation of travel cost and item value of a new proposed item
+void navigation_routerating(entity this, entity e, float f, float rangebias)
+{
+       entity nwp;
+       vector o;
+       if (!e)
+               return;
+
+       if(e.blacklisted)
+               return;
+
+       o = (e.absmin + e.absmax) * 0.5;
+
+       //print("routerating ", etos(e), " = ", ftos(f), " - ", ftos(rangebias), "\n");
+
+       // Evaluate path using jetpack
+       if(g_jetpack)
+       if(this.items & IT_JETPACK)
+       if(autocvar_bot_ai_navigation_jetpack)
+       if(vdist(this.origin - o, >, autocvar_bot_ai_navigation_jetpack_mindistance))
+       {
+               vector pointa, pointb;
+
+               LOG_DEBUG("jetpack ai: evaluating path for ", e.classname);
+
+               // Point A
+               traceline(this.origin, this.origin + '0 0 65535', MOVE_NORMAL, this);
+               pointa = trace_endpos - '0 0 1';
+
+               // Point B
+               traceline(o, o + '0 0 65535', MOVE_NORMAL, e);
+               pointb = trace_endpos - '0 0 1';
+
+               // Can I see these two points from the sky?
+               traceline(pointa, pointb, MOVE_NORMAL, this);
+
+               if(trace_fraction==1)
+               {
+                       LOG_DEBUG("jetpack ai: can bridge these two points");
+
+                       // Lower the altitude of these points as much as possible
+                       float zdistance, xydistance, cost, t, fuel;
+                       vector down, npa, npb;
+
+                       down = '0 0 -1' * (STAT(PL_MAX, NULL).z - STAT(PL_MIN, NULL).z) * 10;
+
+                       do{
+                               npa = pointa + down;
+                               npb = pointb + down;
+
+                               if(npa.z<=this.absmax.z)
+                                       break;
+
+                               if(npb.z<=e.absmax.z)
+                                       break;
+
+                               traceline(npa, npb, MOVE_NORMAL, this);
+                               if(trace_fraction==1)
+                               {
+                                       pointa = npa;
+                                       pointb = npb;
+                               }
+                       }
+                       while(trace_fraction == 1);
+
+
+                       // Rough estimation of fuel consumption
+                       // (ignores acceleration and current xyz velocity)
+                       xydistance = vlen(pointa - pointb);
+                       zdistance = fabs(pointa.z - this.origin.z);
+
+                       t = zdistance / autocvar_g_jetpack_maxspeed_up;
+                       t += xydistance / autocvar_g_jetpack_maxspeed_side;
+                       fuel = t * autocvar_g_jetpack_fuel * 0.8;
+
+                       LOG_DEBUG("jetpack ai: required fuel ", ftos(fuel), " this.ammo_fuel ", ftos(this.ammo_fuel));
+
+                       // enough fuel ?
+                       if(this.ammo_fuel>fuel)
+                       {
+                               // Estimate cost
+                               // (as onground costs calculation is mostly based on distances, here we do the same establishing some relationship
+                               //  - between air and ground speeds)
+
+                               cost = xydistance / (autocvar_g_jetpack_maxspeed_side/autocvar_sv_maxspeed);
+                               cost += zdistance / (autocvar_g_jetpack_maxspeed_up/autocvar_sv_maxspeed);
+                               cost *= 1.5;
+
+                               // Compare against other goals
+                               f = f * rangebias / (rangebias + cost);
+
+                               if (navigation_bestrating < f)
+                               {
+                                       LOG_DEBUG("jetpack path: added goal ", e.classname, " (with rating ", ftos(f), ")");
+                                       navigation_bestrating = f;
+                                       navigation_bestgoal = e;
+                                       this.navigation_jetpack_goal = e;
+                                       this.navigation_jetpack_point = pointb;
+                               }
+                               return;
+                       }
+               }
+       }
+
+       //te_wizspike(e.origin);
+       //bprint(etos(e));
+       //bprint("\n");
+       // update the cached spawnfunc_waypoint link on a dynamic item entity
+       if(e.classname == "waypoint" && !(e.wpflags & WAYPOINTFLAG_PERSONAL))
+       {
+               nwp = e;
+       }
+       else
+       {
+               float search;
+
+               search = true;
+
+               if(e.flags & FL_ITEM)
+               {
+                       if (!(e.flags & FL_WEAPON))
+                       if(e.nearestwaypoint)
+                               search = false;
+               }
+               else if (e.flags & FL_WEAPON)
+               {
+                       if(e.classname != "droppedweapon")
+                       if(e.nearestwaypoint)
+                               search = false;
+               }
+
+               if(search)
+               if (time > e.nearestwaypointtimeout)
+               {
+                       nwp = navigation_findnearestwaypoint(e, true);
+                       if(nwp)
+                               e.nearestwaypoint = nwp;
+                       else
+                       {
+                               LOG_DEBUG("FAILED to find a nearest waypoint to '", e.classname, "' #", etos(e));
+
+                               if(e.flags & FL_ITEM)
+                                       e.blacklisted = true;
+                               else if (e.flags & FL_WEAPON)
+                               {
+                                       if(e.classname != "droppedweapon")
+                                               e.blacklisted = true;
+                               }
+
+                               if(e.blacklisted)
+                               {
+                                       LOG_DEBUG("The entity '", e.classname, "' is going to be excluded from path finding during this match");
+                                       return;
+                               }
+                       }
+
+                       // TODO: Cleaner solution, probably handling this timeout from ctf.qc
+                       if(e.classname=="item_flag_team")
+                               e.nearestwaypointtimeout = time + 2;
+                       else
+                               e.nearestwaypointtimeout = time + random() * 3 + 5;
+               }
+               nwp = e.nearestwaypoint;
+       }
+
+       LOG_DEBUG("-- checking ", e.classname, " (with cost ", ftos(nwp.wpcost), ")");
+       if (nwp)
+       if (nwp.wpcost < 10000000)
+       {
+               //te_wizspike(nwp.wpnearestpoint);
+               LOG_DEBUG(e.classname, " ", ftos(f), "/(1+", ftos((nwp.wpcost + vlen(e.origin - nwp.wpnearestpoint))), "/", ftos(rangebias), ") = ");
+               f = f * rangebias / (rangebias + (nwp.wpcost + vlen(o - nwp.wpnearestpoint)));
+               LOG_DEBUG("considering ", e.classname, " (with rating ", ftos(f), ")");
+               if (navigation_bestrating < f)
+               {
+                       LOG_DEBUG("ground path: added goal ", e.classname, " (with rating ", ftos(f), ")");
+                       navigation_bestrating = f;
+                       navigation_bestgoal = e;
+               }
+       }
+}
+
+// adds an item to the the goal stack with the path to a given item
+bool navigation_routetogoal(entity this, entity e, vector startposition)
+{
+       this.goalentity = e;
+
+       // if there is no goal, just exit
+       if (!e)
+               return false;
+
+       this.navigation_hasgoals = true;
+
+       // put the entity on the goal stack
+       //print("routetogoal ", etos(e), "\n");
+       navigation_pushroute(this, e);
+
+       if(g_jetpack)
+       if(e==this.navigation_jetpack_goal)
+               return true;
+
+       // if it can reach the goal there is nothing more to do
+       if (tracewalk(this, startposition, STAT(PL_MIN, NULL), STAT(PL_MAX, NULL), (e.absmin + e.absmax) * 0.5, bot_navigation_movemode))
+               return true;
+
+       // see if there are waypoints describing a path to the item
+       if(e.classname != "waypoint" || (e.wpflags & WAYPOINTFLAG_PERSONAL))
+               e = e.nearestwaypoint;
+       else
+               e = e.enemy; // we already have added it, so...
+
+       if(e == NULL)
+               return false;
+
+       for (;;)
+       {
+               // add the spawnfunc_waypoint to the path
+               navigation_pushroute(this, e);
+               e = e.enemy;
+
+               if(e==NULL)
+                       break;
+       }
+
+       return false;
+}
+
+// removes any currently touching waypoints from the goal stack
+// (this is how bots detect if they reached a goal)
+void navigation_poptouchedgoals(entity this)
+{
+       vector org, m1, m2;
+       org = this.origin;
+       m1 = org + this.mins;
+       m2 = org + this.maxs;
+
+       if(this.goalcurrent.wpflags & WAYPOINTFLAG_TELEPORT)
+       {
+               if(this.lastteleporttime>0)
+               if(time-this.lastteleporttime<(this.goalcurrent.wpflags & WAYPOINTFLAG_PERSONAL)?2:0.15)
+               {
+                       if(this.aistatus & AI_STATUS_WAYPOINT_PERSONAL_GOING)
+                       if(this.goalcurrent.wpflags & WAYPOINTFLAG_PERSONAL && this.goalcurrent.owner==this)
+                       {
+                               this.aistatus &= ~AI_STATUS_WAYPOINT_PERSONAL_GOING;
+                               this.aistatus |= AI_STATUS_WAYPOINT_PERSONAL_REACHED;
+                       }
+                       navigation_poproute(this);
+                       return;
+               }
+       }
+
+       // If for some reason the bot is closer to the next goal, pop the current one
+       if(this.goalstack01)
+       if(vlen2(this.goalcurrent.origin - this.origin) > vlen2(this.goalstack01.origin - this.origin))
+       if(checkpvs(this.origin + this.view_ofs, this.goalstack01))
+       if(tracewalk(this, this.origin, this.mins, this.maxs, (this.goalstack01.absmin + this.goalstack01.absmax) * 0.5, bot_navigation_movemode))
+       {
+               LOG_DEBUG("path optimized for ", this.netname, ", removed a goal from the queue");
+               navigation_poproute(this);
+               // TODO this may also be a nice idea to do "early" (e.g. by
+               // manipulating the vlen() comparisons) to shorten paths in
+               // general - this would make bots walk more "on rails" than
+               // "zigzagging" which they currently do with sufficiently
+               // random-like waypoints, and thus can make a nice bot
+               // personality property
+       }
+
+       // HACK: remove players/bots as goals, they can lead a bot to unexpected places (cliffs, lava, etc)
+       // TODO: rate waypoints near the targetted player at that moment, instead of the player itthis
+       if(IS_PLAYER(this.goalcurrent))
+               navigation_poproute(this);
+
+       // aid for detecting jump pads better (distance based check fails sometimes)
+       if(this.goalcurrent.wpflags & WAYPOINTFLAG_TELEPORT && this.jumppadcount > 0 )
+               navigation_poproute(this);
+
+       // Loose goal touching check when running
+       if(this.aistatus & AI_STATUS_RUNNING)
+       if(this.speed >= autocvar_sv_maxspeed) // if -really- running
+       if(this.goalcurrent.classname=="waypoint")
+       {
+               if(vdist(this.origin - this.goalcurrent.origin, <, 150))
+               {
+                       traceline(this.origin + this.view_ofs , this.goalcurrent.origin, true, NULL);
+                       if(trace_fraction==1)
+                       {
+                               // Detect personal waypoints
+                               if(this.aistatus & AI_STATUS_WAYPOINT_PERSONAL_GOING)
+                               if(this.goalcurrent.wpflags & WAYPOINTFLAG_PERSONAL && this.goalcurrent.owner==this)
+                               {
+                                       this.aistatus &= ~AI_STATUS_WAYPOINT_PERSONAL_GOING;
+                                       this.aistatus |= AI_STATUS_WAYPOINT_PERSONAL_REACHED;
+                               }
+
+                               navigation_poproute(this);
+                       }
+               }
+       }
+
+       while (this.goalcurrent && boxesoverlap(m1, m2, this.goalcurrent.absmin, this.goalcurrent.absmax))
+       {
+               // Detect personal waypoints
+               if(this.aistatus & AI_STATUS_WAYPOINT_PERSONAL_GOING)
+               if(this.goalcurrent.wpflags & WAYPOINTFLAG_PERSONAL && this.goalcurrent.owner==this)
+               {
+                       this.aistatus &= ~AI_STATUS_WAYPOINT_PERSONAL_GOING;
+                       this.aistatus |= AI_STATUS_WAYPOINT_PERSONAL_REACHED;
+               }
+
+               navigation_poproute(this);
+       }
+}
+
+// begin a goal selection session (queries spawnfunc_waypoint network)
+void navigation_goalrating_start(entity this)
+{
+       if(this.aistatus & AI_STATUS_STUCK)
+               return;
+
+       this.navigation_jetpack_goal = NULL;
+       navigation_bestrating = -1;
+       this.navigation_hasgoals = false;
+       navigation_clearroute(this);
+       navigation_bestgoal = NULL;
+       navigation_markroutes(this, NULL);
+}
+
+// ends a goal selection session (updates goal stack to the best goal)
+void navigation_goalrating_end(entity this)
+{
+       if(this.aistatus & AI_STATUS_STUCK)
+               return;
+
+       navigation_routetogoal(this, navigation_bestgoal, this.origin);
+       LOG_DEBUG("best goal ", this.goalcurrent.classname);
+
+       // If the bot got stuck then try to reach the farthest waypoint
+       if (!this.navigation_hasgoals)
+       if (autocvar_bot_wander_enable)
+       {
+               if (!(this.aistatus & AI_STATUS_STUCK))
+               {
+                       LOG_DEBUG(this.netname, " cannot walk to any goal");
+                       this.aistatus |= AI_STATUS_STUCK;
+               }
+
+               this.navigation_hasgoals = false; // Reset this value
+       }
+}
+
+void botframe_updatedangerousobjects(float maxupdate)
+{
+       vector m1, m2, v, o;
+       float c, d, danger;
+       c = 0;
+       IL_EACH(g_waypoints, true,
+       {
+               danger = 0;
+               m1 = it.mins;
+               m2 = it.maxs;
+               FOREACH_ENTITY_FLOAT(bot_dodge, true,
+               {
+                       v = it.origin;
+                       v.x = bound(m1_x, v.x, m2_x);
+                       v.y = bound(m1_y, v.y, m2_y);
+                       v.z = bound(m1_z, v.z, m2_z);
+                       o = (it.absmin + it.absmax) * 0.5;
+                       d = it.bot_dodgerating - vlen(o - v);
+                       if (d > 0)
+                       {
+                               traceline(o, v, true, NULL);
+                               if (trace_fraction == 1)
+                                       danger = danger + d;
+                       }
+               });
+               it.dmg = danger;
+               c = c + 1;
+               if (c >= maxupdate)
+                       break;
+       });
+}
+
+void navigation_unstuck(entity this)
+{
+       float search_radius = 1000;
+
+       if (!autocvar_bot_wander_enable)
+               return;
+
+       if (!bot_waypoint_queue_owner)
+       {
+               LOG_DEBUG(this.netname, " sutck, taking over the waypoints queue");
+               bot_waypoint_queue_owner = this;
+               bot_waypoint_queue_bestgoal = NULL;
+               bot_waypoint_queue_bestgoalrating = 0;
+       }
+
+       if(bot_waypoint_queue_owner!=this)
+               return;
+
+       if (bot_waypoint_queue_goal)
+       {
+               // evaluate the next goal on the queue
+               float d = vlen(this.origin - bot_waypoint_queue_goal.origin);
+               LOG_DEBUG(this.netname, " evaluating ", bot_waypoint_queue_goal.classname, " with distance ", ftos(d));
+               if(tracewalk(bot_waypoint_queue_goal, this.origin, STAT(PL_MIN, NULL), STAT(PL_MAX, NULL), bot_waypoint_queue_goal.origin, bot_navigation_movemode))
+               {
+                       if( d > bot_waypoint_queue_bestgoalrating)
+                       {
+                               bot_waypoint_queue_bestgoalrating = d;
+                               bot_waypoint_queue_bestgoal = bot_waypoint_queue_goal;
+                       }
+               }
+               bot_waypoint_queue_goal = bot_waypoint_queue_goal.bot_waypoint_queue_nextgoal;
+
+               if (!bot_waypoint_queue_goal)
+               {
+                       if (bot_waypoint_queue_bestgoal)
+                       {
+                               LOG_DEBUG(this.netname, " stuck, reachable waypoint found, heading to it");
+                               navigation_routetogoal(this, bot_waypoint_queue_bestgoal, this.origin);
+                               this.bot_strategytime = time + autocvar_bot_ai_strategyinterval;
+                               this.aistatus &= ~AI_STATUS_STUCK;
+                       }
+                       else
+                       {
+                               LOG_DEBUG(this.netname, " stuck, cannot walk to any waypoint at all");
+                       }
+
+                       bot_waypoint_queue_owner = NULL;
+               }
+       }
+       else
+       {
+               if(bot_strategytoken!=this)
+                       return;
+
+               // build a new queue
+               LOG_DEBUG(this.netname, " stuck, scanning reachable waypoints within ", ftos(search_radius)," qu");
+
+               entity first = NULL;
+
+               FOREACH_ENTITY_RADIUS(this.origin, search_radius, it.classname == "waypoint" && !(it.wpflags & WAYPOINTFLAG_GENERATED),
+               {
+                       if(bot_waypoint_queue_goal)
+                               bot_waypoint_queue_goal.bot_waypoint_queue_nextgoal = it;
+                       else
+                               first = it;
+
+                       bot_waypoint_queue_goal = it;
+                       bot_waypoint_queue_goal.bot_waypoint_queue_nextgoal = NULL;
+               });
+
+               if (first)
+                       bot_waypoint_queue_goal = first;
+               else
+               {
+                       LOG_DEBUG(this.netname, " stuck, cannot walk to any waypoint at all");
+                       bot_waypoint_queue_owner = NULL;
+               }
+       }
+}
+
+// Support for debugging tracewalk visually
+
+void debugresetnodes()
+{
+       debuglastnode = '0 0 0';
+}
+
+void debugnode(entity this, vector node)
+{
+       if (!IS_PLAYER(this))
+               return;
+
+       if(debuglastnode=='0 0 0')
+       {
+               debuglastnode = node;
+               return;
+       }
+
+       te_lightning2(NULL, node, debuglastnode);
+       debuglastnode = node;
+}
+
+void debugnodestatus(vector position, float status)
+{
+       vector c;
+
+       switch (status)
+       {
+               case DEBUG_NODE_SUCCESS:
+                       c = '0 15 0';
+                       break;
+               case DEBUG_NODE_WARNING:
+                       c = '15 15 0';
+                       break;
+               case DEBUG_NODE_FAIL:
+                       c = '15 0 0';
+                       break;
+               default:
+                       c = '15 15 15';
+       }
+
+       te_customflash(position, 40,  2, c);
+}
+
+// Support for debugging the goal stack visually
+
+.float goalcounter;
+.vector lastposition;
+
+// Debug the goal stack visually
+void debuggoalstack(entity this)
+{
+       entity goal;
+       vector org, go;
+
+       if(this.goalcounter==0)goal=this.goalcurrent;
+       else if(this.goalcounter==1)goal=this.goalstack01;
+       else if(this.goalcounter==2)goal=this.goalstack02;
+       else if(this.goalcounter==3)goal=this.goalstack03;
+       else if(this.goalcounter==4)goal=this.goalstack04;
+       else if(this.goalcounter==5)goal=this.goalstack05;
+       else if(this.goalcounter==6)goal=this.goalstack06;
+       else if(this.goalcounter==7)goal=this.goalstack07;
+       else if(this.goalcounter==8)goal=this.goalstack08;
+       else if(this.goalcounter==9)goal=this.goalstack09;
+       else if(this.goalcounter==10)goal=this.goalstack10;
+       else if(this.goalcounter==11)goal=this.goalstack11;
+       else if(this.goalcounter==12)goal=this.goalstack12;
+       else if(this.goalcounter==13)goal=this.goalstack13;
+       else if(this.goalcounter==14)goal=this.goalstack14;
+       else if(this.goalcounter==15)goal=this.goalstack15;
+       else if(this.goalcounter==16)goal=this.goalstack16;
+       else if(this.goalcounter==17)goal=this.goalstack17;
+       else if(this.goalcounter==18)goal=this.goalstack18;
+       else if(this.goalcounter==19)goal=this.goalstack19;
+       else if(this.goalcounter==20)goal=this.goalstack20;
+       else if(this.goalcounter==21)goal=this.goalstack21;
+       else if(this.goalcounter==22)goal=this.goalstack22;
+       else if(this.goalcounter==23)goal=this.goalstack23;
+       else if(this.goalcounter==24)goal=this.goalstack24;
+       else if(this.goalcounter==25)goal=this.goalstack25;
+       else if(this.goalcounter==26)goal=this.goalstack26;
+       else if(this.goalcounter==27)goal=this.goalstack27;
+       else if(this.goalcounter==28)goal=this.goalstack28;
+       else if(this.goalcounter==29)goal=this.goalstack29;
+       else if(this.goalcounter==30)goal=this.goalstack30;
+       else if(this.goalcounter==31)goal=this.goalstack31;
+       else goal=NULL;
+
+       if(goal==NULL)
+       {
+               this.goalcounter = 0;
+               this.lastposition='0 0 0';
+               return;
+       }
+
+       if(this.lastposition=='0 0 0')
+               org = this.origin;
+       else
+               org = this.lastposition;
+
+
+       go = ( goal.absmin + goal.absmax ) * 0.5;
+       te_lightning2(NULL, org, go);
+       this.lastposition = go;
+
+       this.goalcounter++;
+}
diff --git a/qcsrc/server/bot/default/navigation.qh b/qcsrc/server/bot/default/navigation.qh
new file mode 100644 (file)
index 0000000..ad01776
--- /dev/null
@@ -0,0 +1,77 @@
+#pragma once
+/*
+ * Globals and Fields
+ */
+
+float navigation_bestrating;
+float bot_navigation_movemode;
+float navigation_testtracewalk;
+
+vector jumpstepheightvec;
+vector stepheightvec;
+
+entity navigation_bestgoal;
+
+// stack of current goals (the last one of which may be an item or other
+// desirable object, the rest are typically waypoints to reach it)
+.entity goalcurrent, goalstack01, goalstack02, goalstack03;
+.entity goalstack04, goalstack05, goalstack06, goalstack07;
+.entity goalstack08, goalstack09, goalstack10, goalstack11;
+.entity goalstack12, goalstack13, goalstack14, goalstack15;
+.entity goalstack16, goalstack17, goalstack18, goalstack19;
+.entity goalstack20, goalstack21, goalstack22, goalstack23;
+.entity goalstack24, goalstack25, goalstack26, goalstack27;
+.entity goalstack28, goalstack29, goalstack30, goalstack31;
+.entity nearestwaypoint;
+
+.float nearestwaypointtimeout;
+.float navigation_hasgoals;
+.float lastteleporttime;
+
+.float blacklisted;
+
+.entity navigation_jetpack_goal;
+.vector navigation_jetpack_point;
+
+const float DEBUG_NODE_SUCCESS        = 1;
+const float DEBUG_NODE_WARNING        = 2;
+const float DEBUG_NODE_FAIL           = 3;
+vector debuglastnode;
+
+entity bot_waypoint_queue_owner;       // Owner of the temporary list of goals
+entity bot_waypoint_queue_goal;                // Head of the temporary list of goals
+.entity bot_waypoint_queue_nextgoal;
+entity bot_waypoint_queue_bestgoal;
+float bot_waypoint_queue_bestgoalrating;
+
+/*
+ * Functions
+ */
+
+void debugresetnodes();
+void debugnode(entity this, vector node);
+void debugnodestatus(vector position, float status);
+
+void debuggoalstack(entity this);
+
+float tracewalk(entity e, vector start, vector m1, vector m2, vector end, float movemode);
+
+float navigation_markroutes_nearestwaypoints(entity this, float maxdist);
+float navigation_routetogoal(entity this, entity e, vector startposition);
+
+void navigation_clearroute(entity this);
+void navigation_pushroute(entity this, entity e);
+void navigation_poproute(entity this);
+void navigation_markroutes_checkwaypoint(entity w, entity wp, float cost2, vector p);
+void navigation_markroutes(entity this, entity fixed_source_waypoint);
+void navigation_markroutes_inverted(entity fixed_source_waypoint);
+void navigation_routerating(entity this, entity e, float f, float rangebias);
+void navigation_poptouchedgoals(entity this);
+void navigation_goalrating_start(entity this);
+void navigation_goalrating_end(entity this);
+void navigation_unstuck(entity this);
+
+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);
diff --git a/qcsrc/server/bot/default/scripting.qc b/qcsrc/server/bot/default/scripting.qc
new file mode 100644 (file)
index 0000000..e111b2a
--- /dev/null
@@ -0,0 +1,1342 @@
+#include "scripting.qh"
+
+#include "cvars.qh"
+
+#include <common/state.qh>
+#include <common/physics/player.qh>
+
+#include "bot.qh"
+
+.int state;
+
+.float bot_cmdqueuebuf_allocated;
+.float bot_cmdqueuebuf;
+.float bot_cmdqueuebuf_start;
+.float bot_cmdqueuebuf_end;
+
+void bot_clearqueue(entity bot)
+{
+       if(!bot.bot_cmdqueuebuf_allocated)
+               return;
+       buf_del(bot.bot_cmdqueuebuf);
+       bot.bot_cmdqueuebuf_allocated = false;
+       LOG_TRACE("bot ", bot.netname, " queue cleared");
+}
+
+void bot_queuecommand(entity bot, string cmdstring)
+{
+       if(!bot.bot_cmdqueuebuf_allocated)
+       {
+               bot.bot_cmdqueuebuf = buf_create();
+               bot.bot_cmdqueuebuf_allocated = true;
+               bot.bot_cmdqueuebuf_start = 0;
+               bot.bot_cmdqueuebuf_end = 0;
+       }
+
+       bufstr_set(bot.bot_cmdqueuebuf, bot.bot_cmdqueuebuf_end, cmdstring);
+
+       // if the command was a "sound" command, precache the sound NOW
+       // this prevents lagging!
+       {
+               float sp;
+               string parm;
+               string cmdstr;
+
+               sp = strstrofs(cmdstring, " ", 0);
+               if(sp >= 0)
+               {
+                       parm = substring(cmdstring, sp + 1, -1);
+                       cmdstr = substring(cmdstring, 0, sp);
+                       if(cmdstr == "sound")
+                       {
+                               // find the LAST word
+                               for (;;)
+                               {
+                                       sp = strstrofs(parm, " ", 0);
+                                       if(sp < 0)
+                                               break;
+                                       parm = substring(parm, sp + 1, -1);
+                               }
+                               precache_sound(parm);
+                       }
+               }
+       }
+
+       bot.bot_cmdqueuebuf_end += 1;
+}
+
+void bot_dequeuecommand(entity bot, float idx)
+{
+       if(!bot.bot_cmdqueuebuf_allocated)
+               error("dequeuecommand but no queue allocated");
+       if(idx < bot.bot_cmdqueuebuf_start)
+               error("dequeueing a command in the past");
+       if(idx >= bot.bot_cmdqueuebuf_end)
+               error("dequeueing a command in the future");
+       bufstr_set(bot.bot_cmdqueuebuf, idx, "");
+       if(idx == bot.bot_cmdqueuebuf_start)
+               bot.bot_cmdqueuebuf_start += 1;
+       if(bot.bot_cmdqueuebuf_start >= bot.bot_cmdqueuebuf_end)
+               bot_clearqueue(bot);
+}
+
+string bot_readcommand(entity bot, float idx)
+{
+       if(!bot.bot_cmdqueuebuf_allocated)
+               error("readcommand but no queue allocated");
+       if(idx < bot.bot_cmdqueuebuf_start)
+               error("reading a command in the past");
+       if(idx >= bot.bot_cmdqueuebuf_end)
+               error("reading a command in the future");
+       return bufstr_get(bot.bot_cmdqueuebuf, idx);
+}
+
+bool bot_havecommand(entity this, int idx)
+{
+       if(!this.bot_cmdqueuebuf_allocated)
+               return false;
+       if(idx < this.bot_cmdqueuebuf_start)
+               return false;
+       if(idx >= this.bot_cmdqueuebuf_end)
+               return false;
+       return true;
+}
+
+const int MAX_BOT_PLACES = 4;
+.float bot_places_count;
+.entity bot_places[MAX_BOT_PLACES];
+.string bot_placenames[MAX_BOT_PLACES];
+entity bot_getplace(entity this, string placename)
+{
+       entity e;
+       if(substring(placename, 0, 1) == "@")
+       {
+               int i, p;
+               placename = substring(placename, 1, -1);
+               string s, s2;
+               for(i = 0; i < this.bot_places_count; ++i)
+                       if(this.(bot_placenames[i]) == placename)
+                               return this.(bot_places[i]);
+               // now: i == this.bot_places_count
+               s = s2 = cvar_string(placename);
+               p = strstrofs(s2, " ", 0);
+               if(p >= 0)
+               {
+                       s = substring(s2, 0, p);
+                       //print("places: ", placename, " -> ", cvar_string(placename), "\n");
+                       cvar_set(placename, strcat(substring(s2, p+1, -1), " ", s));
+                       //print("places: ", placename, " := ", cvar_string(placename), "\n");
+               }
+               e = find(NULL, targetname, s);
+               if(!e)
+                       LOG_INFO("invalid place ", s, "\n");
+               if(i < MAX_BOT_PLACES)
+               {
+                       this.(bot_placenames[i]) = strzone(placename);
+                       this.(bot_places[i]) = e;
+                       this.bot_places_count += 1;
+               }
+               return e;
+       }
+       else
+       {
+               e = find(NULL, targetname, placename);
+               if(!e)
+                       LOG_INFO("invalid place ", placename, "\n");
+               return e;
+       }
+}
+
+
+// Initialize global commands list
+// NOTE: New commands should be initialized here
+void bot_commands_init()
+{
+       bot_cmd_string[BOT_CMD_NULL] = "";
+       bot_cmd_parm_type[BOT_CMD_NULL] = BOT_CMD_PARAMETER_NONE;
+
+       bot_cmd_string[BOT_CMD_PAUSE] = "pause";
+       bot_cmd_parm_type[BOT_CMD_PAUSE] = BOT_CMD_PARAMETER_NONE;
+
+       bot_cmd_string[BOT_CMD_CONTINUE] = "continue";
+       bot_cmd_parm_type[BOT_CMD_CONTINUE] = BOT_CMD_PARAMETER_NONE;
+
+       bot_cmd_string[BOT_CMD_WAIT] = "wait";
+       bot_cmd_parm_type[BOT_CMD_WAIT] = BOT_CMD_PARAMETER_FLOAT;
+
+       bot_cmd_string[BOT_CMD_TURN] = "turn";
+       bot_cmd_parm_type[BOT_CMD_TURN] = BOT_CMD_PARAMETER_FLOAT;
+
+       bot_cmd_string[BOT_CMD_MOVETO] = "moveto";
+       bot_cmd_parm_type[BOT_CMD_MOVETO] = BOT_CMD_PARAMETER_VECTOR;
+
+       bot_cmd_string[BOT_CMD_MOVETOTARGET] = "movetotarget";
+       bot_cmd_parm_type[BOT_CMD_MOVETOTARGET] = BOT_CMD_PARAMETER_STRING;
+
+       bot_cmd_string[BOT_CMD_RESETGOAL] = "resetgoal";
+       bot_cmd_parm_type[BOT_CMD_RESETGOAL] = BOT_CMD_PARAMETER_NONE;
+
+       bot_cmd_string[BOT_CMD_CC] = "cc";
+       bot_cmd_parm_type[BOT_CMD_CC] = BOT_CMD_PARAMETER_STRING;
+
+       bot_cmd_string[BOT_CMD_IF] = "if";
+       bot_cmd_parm_type[BOT_CMD_IF] = BOT_CMD_PARAMETER_STRING;
+
+       bot_cmd_string[BOT_CMD_ELSE] = "else";
+       bot_cmd_parm_type[BOT_CMD_ELSE] = BOT_CMD_PARAMETER_NONE;
+
+       bot_cmd_string[BOT_CMD_FI] = "fi";
+       bot_cmd_parm_type[BOT_CMD_FI] = BOT_CMD_PARAMETER_NONE;
+
+       bot_cmd_string[BOT_CMD_RESETAIM] = "resetaim";
+       bot_cmd_parm_type[BOT_CMD_RESETAIM] = BOT_CMD_PARAMETER_NONE;
+
+       bot_cmd_string[BOT_CMD_AIM] = "aim";
+       bot_cmd_parm_type[BOT_CMD_AIM] = BOT_CMD_PARAMETER_STRING;
+
+       bot_cmd_string[BOT_CMD_AIMTARGET] = "aimtarget";
+       bot_cmd_parm_type[BOT_CMD_AIMTARGET] = BOT_CMD_PARAMETER_STRING;
+
+       bot_cmd_string[BOT_CMD_PRESSKEY] = "presskey";
+       bot_cmd_parm_type[BOT_CMD_PRESSKEY] = BOT_CMD_PARAMETER_STRING;
+
+       bot_cmd_string[BOT_CMD_RELEASEKEY] = "releasekey";
+       bot_cmd_parm_type[BOT_CMD_RELEASEKEY] = BOT_CMD_PARAMETER_STRING;
+
+       bot_cmd_string[BOT_CMD_SELECTWEAPON] = "selectweapon";
+       bot_cmd_parm_type[BOT_CMD_SELECTWEAPON] = BOT_CMD_PARAMETER_FLOAT;
+
+       bot_cmd_string[BOT_CMD_IMPULSE] = "impulse";
+       bot_cmd_parm_type[BOT_CMD_IMPULSE] = BOT_CMD_PARAMETER_FLOAT;
+
+       bot_cmd_string[BOT_CMD_WAIT_UNTIL] = "wait_until";
+       bot_cmd_parm_type[BOT_CMD_WAIT_UNTIL] = BOT_CMD_PARAMETER_FLOAT;
+
+       bot_cmd_string[BOT_CMD_BARRIER] = "barrier";
+       bot_cmd_parm_type[BOT_CMD_BARRIER] = BOT_CMD_PARAMETER_NONE;
+
+       bot_cmd_string[BOT_CMD_CONSOLE] = "console";
+       bot_cmd_parm_type[BOT_CMD_CONSOLE] = BOT_CMD_PARAMETER_STRING;
+
+       bot_cmd_string[BOT_CMD_SOUND] = "sound";
+       bot_cmd_parm_type[BOT_CMD_SOUND] = BOT_CMD_PARAMETER_STRING;
+
+       bot_cmd_string[BOT_CMD_DEBUG_ASSERT_CANFIRE] = "debug_assert_canfire";
+       bot_cmd_parm_type[BOT_CMD_DEBUG_ASSERT_CANFIRE] = BOT_CMD_PARAMETER_FLOAT;
+
+       bot_cmds_initialized = true;
+}
+
+// Returns first bot with matching name
+entity find_bot_by_name(string name)
+{
+       entity bot;
+
+       bot = findchainflags(flags, FL_CLIENT);
+       while (bot)
+       {
+               if(IS_BOT_CLIENT(bot))
+               if(bot.netname==name)
+                       return bot;
+
+               bot = bot.chain;
+       }
+
+       return NULL;
+}
+
+// Returns a bot by number on list
+entity find_bot_by_number(float number)
+{
+       entity bot;
+       float c = 0;
+
+       if(!number)
+               return NULL;
+
+       bot = findchainflags(flags, FL_CLIENT); // TODO: doesn't findchainflags loop backwards through entities?
+       while (bot)
+       {
+               if(IS_BOT_CLIENT(bot))
+               {
+                       if(++c==number)
+                               return bot;
+               }
+               bot = bot.chain;
+       }
+
+       return NULL;
+}
+
+float bot_decodecommand(string cmdstring)
+{
+       float cmd_parm_type;
+       float sp;
+       string parm;
+
+       sp = strstrofs(cmdstring, " ", 0);
+       if(sp < 0)
+       {
+               parm = "";
+       }
+       else
+       {
+               parm = substring(cmdstring, sp + 1, -1);
+               cmdstring = substring(cmdstring, 0, sp);
+       }
+
+       if(!bot_cmds_initialized)
+               bot_commands_init();
+
+       int i;
+       for(i=1;i<BOT_CMD_COUNTER;++i)
+       {
+               if(bot_cmd_string[i]!=cmdstring)
+                       continue;
+
+               cmd_parm_type = bot_cmd_parm_type[i];
+
+               if(cmd_parm_type!=BOT_CMD_PARAMETER_NONE&&parm=="")
+               {
+                       LOG_INFO("ERROR: A parameter is required for this command\n");
+                       return 0;
+               }
+
+               // Load command into queue
+               bot_cmd.bot_cmd_type = i;
+
+               // Attach parameter
+               switch(cmd_parm_type)
+               {
+                       case BOT_CMD_PARAMETER_FLOAT:
+                               bot_cmd.bot_cmd_parm_float = stof(parm);
+                               break;
+                       case BOT_CMD_PARAMETER_STRING:
+                               if(bot_cmd.bot_cmd_parm_string)
+                                       strunzone(bot_cmd.bot_cmd_parm_string);
+                               bot_cmd.bot_cmd_parm_string = strzone(parm);
+                               break;
+                       case BOT_CMD_PARAMETER_VECTOR:
+                               bot_cmd.bot_cmd_parm_vector = stov(parm);
+                               break;
+                       default:
+                               break;
+               }
+               return 1;
+       }
+       LOG_INFO("ERROR: No such command '", cmdstring, "'\n");
+       return 0;
+}
+
+void bot_cmdhelp(string scmd)
+{
+       int i, ntype;
+       string stype;
+
+       if(!bot_cmds_initialized)
+               bot_commands_init();
+
+       for(i=1;i<BOT_CMD_COUNTER;++i)
+       {
+               if(bot_cmd_string[i]!=scmd)
+                       continue;
+
+               ntype = bot_cmd_parm_type[i];
+
+               switch(ntype)
+               {
+                       case BOT_CMD_PARAMETER_FLOAT:
+                               stype = "float number";
+                               break;
+                       case BOT_CMD_PARAMETER_STRING:
+                               stype = "string";
+                               break;
+                       case BOT_CMD_PARAMETER_VECTOR:
+                               stype = "vector";
+                               break;
+                       default:
+                               stype = "none";
+                               break;
+               }
+
+               LOG_INFO(strcat("Command: ",bot_cmd_string[i],"\nParameter: <",stype,"> \n"));
+
+               LOG_INFO("Description: ");
+               switch(i)
+               {
+                       case BOT_CMD_PAUSE:
+                               LOG_INFO("Stops the bot completely. Any command other than 'continue' will be ignored.");
+                               break;
+                       case BOT_CMD_CONTINUE:
+                               LOG_INFO("Disable paused status");
+                               break;
+                       case BOT_CMD_WAIT:
+                               LOG_INFO("Pause command parsing and bot ai for N seconds. Pressed key will remain pressed");
+                               break;
+                       case BOT_CMD_WAIT_UNTIL:
+                               LOG_INFO("Pause command parsing and bot ai until time is N from the last barrier. Pressed key will remain pressed");
+                               break;
+                       case BOT_CMD_BARRIER:
+                               LOG_INFO("Waits till all bots that have a command queue reach this command. Pressed key will remain pressed");
+                               break;
+                       case BOT_CMD_TURN:
+                               LOG_INFO("Look to the right or left N degrees. For turning to the left use positive numbers.");
+                               break;
+                       case BOT_CMD_MOVETO:
+                               LOG_INFO("Walk to an specific coordinate on the map. Usage: moveto \"x y z\"");
+                               break;
+                       case BOT_CMD_MOVETOTARGET:
+                               LOG_INFO("Walk to the specific target on the map");
+                               break;
+                       case BOT_CMD_RESETGOAL:
+                               LOG_INFO("Resets the goal stack");
+                               break;
+                       case BOT_CMD_CC:
+                               LOG_INFO("Execute client command. Examples: cc \"say something\"; cc god; cc \"name newnickname\"; cc kill;");
+                               break;
+                       case BOT_CMD_IF:
+                               LOG_INFO("Perform simple conditional execution.\n");
+                               LOG_INFO("Syntax: \n");
+                               LOG_INFO("        sv_cmd .. if \"condition\"\n");
+                               LOG_INFO("        sv_cmd ..     <instruction if true>\n");
+                               LOG_INFO("        sv_cmd ..     <instruction if true>\n");
+                               LOG_INFO("        sv_cmd .. else\n");
+                               LOG_INFO("        sv_cmd ..     <instruction if false>\n");
+                               LOG_INFO("        sv_cmd ..     <instruction if false>\n");
+                               LOG_INFO("        sv_cmd .. fi\n");
+                               LOG_INFO("Conditions: a=b, a>b, a<b, a\t\t(spaces not allowed)\n");
+                               LOG_INFO("            Values in conditions can be numbers, cvars in the form cvar.cvar_string or special fields\n");
+                               LOG_INFO("Fields: health, speed, flagcarrier\n");
+                               LOG_INFO("Examples: if health>50; if health>cvar.g_balance_laser_primary_damage; if flagcarrier;");
+                               break;
+                       case BOT_CMD_RESETAIM:
+                               LOG_INFO("Points the aim to the coordinates x,y 0,0");
+                               break;
+                       case BOT_CMD_AIM:
+                               LOG_INFO("Move the aim x/y (horizontal/vertical) degrees relatives to the bot\n");
+                               LOG_INFO("There is a 3rd optional parameter telling in how many seconds the aim has to reach the new position\n");
+                               LOG_INFO("Examples: aim \"90 0\"        // Turn 90 degrees inmediately (positive numbers move to the left/up)\n");
+                               LOG_INFO("          aim \"0 90 2\"      // Will gradually look to the sky in the next two seconds");
+                               break;
+                       case BOT_CMD_AIMTARGET:
+                               LOG_INFO("Points the aim to given target");
+                               break;
+                       case BOT_CMD_PRESSKEY:
+                               LOG_INFO("Press one of the following keys: forward, backward, left, right, jump, crouch, attack1, attack2, use\n");
+                               LOG_INFO("Multiple keys can be pressed at time (with many presskey calls) and it will remain pressed until the command \"releasekey\" is called");
+                               LOG_INFO("Note: The script will not return the control to the bot ai until all keys are released");
+                               break;
+                       case BOT_CMD_RELEASEKEY:
+                               LOG_INFO("Release previoulsy used keys. Use the parameter \"all\" to release all keys");
+                               break;
+                       case BOT_CMD_SOUND:
+                               LOG_INFO("play sound file at bot location");
+                               break;
+                       case BOT_CMD_DEBUG_ASSERT_CANFIRE:
+                               LOG_INFO("verify the state of the weapon entity");
+                               break;
+                       default:
+                               LOG_INFO("This command has no description yet.");
+                               break;
+               }
+               LOG_INFO("\n");
+       }
+}
+
+void bot_list_commands()
+{
+       int i;
+       string ptype;
+
+       if(!bot_cmds_initialized)
+               bot_commands_init();
+
+       LOG_INFO("List of all available commands:\n");
+       LOG_INFO("  Command - Parameter Type\n");
+
+       for(i=1;i<BOT_CMD_COUNTER;++i)
+       {
+               switch(bot_cmd_parm_type[i])
+               {
+                       case BOT_CMD_PARAMETER_FLOAT:
+                               ptype = "float number";
+                               break;
+                       case BOT_CMD_PARAMETER_STRING:
+                               ptype = "string";
+                               break;
+                       case BOT_CMD_PARAMETER_VECTOR:
+                               ptype = "vector";
+                               break;
+                       default:
+                               ptype = "none";
+                               break;
+               }
+               LOG_INFO(strcat("  ",bot_cmd_string[i]," - <",ptype,"> \n"));
+       }
+}
+
+// Commands code
+.int bot_exec_status;
+
+float bot_cmd_cc(entity this)
+{
+       SV_ParseClientCommand(this, bot_cmd.bot_cmd_parm_string);
+       return CMD_STATUS_FINISHED;
+}
+
+float bot_cmd_impulse(entity this)
+{
+       this.impulse = bot_cmd.bot_cmd_parm_float;
+       return CMD_STATUS_FINISHED;
+}
+
+float bot_cmd_continue(entity this)
+{
+       this.bot_exec_status &= ~BOT_EXEC_STATUS_PAUSED;
+       return CMD_STATUS_FINISHED;
+}
+
+.float bot_cmd_wait_time;
+float bot_cmd_wait(entity this)
+{
+       if(this.bot_exec_status & BOT_EXEC_STATUS_WAITING)
+       {
+               if(time>=this.bot_cmd_wait_time)
+               {
+                       this.bot_exec_status &= ~BOT_EXEC_STATUS_WAITING;
+                       return CMD_STATUS_FINISHED;
+               }
+               else
+                       return CMD_STATUS_EXECUTING;
+       }
+
+       this.bot_cmd_wait_time = time + bot_cmd.bot_cmd_parm_float;
+       this.bot_exec_status |= BOT_EXEC_STATUS_WAITING;
+       return CMD_STATUS_EXECUTING;
+}
+
+float bot_cmd_wait_until(entity this)
+{
+       if(time < bot_cmd.bot_cmd_parm_float + bot_barriertime)
+       {
+               this.bot_exec_status |= BOT_EXEC_STATUS_WAITING;
+               return CMD_STATUS_EXECUTING;
+       }
+       this.bot_exec_status &= ~BOT_EXEC_STATUS_WAITING;
+       return CMD_STATUS_FINISHED;
+}
+
+float bot_cmd_barrier(entity this)
+{
+       // 0 = no barrier, 1 = waiting, 2 = waiting finished
+
+       if(this.bot_barrier == 0) // initialization
+       {
+               this.bot_barrier = 1;
+
+               //this.colormod = '4 4 0';
+       }
+
+       if(this.bot_barrier == 1) // find other bots
+       {
+               FOREACH_CLIENT(it.isbot, LAMBDA(
+                       if(it.bot_cmdqueuebuf_allocated)
+                       if(it.bot_barrier != 1)
+                               return CMD_STATUS_EXECUTING; // not all are at the barrier yet
+               ));
+
+               // all bots hit the barrier!
+
+               // acknowledge barrier
+               FOREACH_CLIENT(it.isbot, LAMBDA(it.bot_barrier = 2));
+
+               bot_barriertime = time;
+       }
+
+       // if we get here, the barrier is finished
+       // so end it...
+       this.bot_barrier = 0;
+       //this.colormod = '0 0 0';
+
+       return CMD_STATUS_FINISHED;
+}
+
+float bot_cmd_turn(entity this)
+{
+       this.v_angle_y = this.v_angle.y + bot_cmd.bot_cmd_parm_float;
+       this.v_angle_y = this.v_angle.y - floor(this.v_angle.y / 360) * 360;
+       return CMD_STATUS_FINISHED;
+}
+
+float bot_cmd_select_weapon(entity this)
+{
+       float id = bot_cmd.bot_cmd_parm_float;
+
+       if(id < WEP_FIRST || id > WEP_LAST)
+               return CMD_STATUS_ERROR;
+
+       if(client_hasweapon(this, Weapons_from(id), true, false))
+               PS(this).m_switchweapon = Weapons_from(id);
+       else
+               return CMD_STATUS_ERROR;
+
+       return CMD_STATUS_FINISHED;
+}
+
+.int bot_cmd_condition_status;
+
+const int CMD_CONDITION_NONE = 0;
+const int CMD_CONDITION_true = 1;
+const int CMD_CONDITION_false = 2;
+const int CMD_CONDITION_true_BLOCK = 4;
+const int CMD_CONDITION_false_BLOCK = 8;
+
+float bot_cmd_eval(entity this, string expr)
+{
+       // Search for numbers
+       if(strstrofs("0123456789", substring(expr, 0, 1), 0) >= 0)
+       {
+               return stof(expr);
+       }
+
+       // Search for cvars
+       if(substring(expr, 0, 5)=="cvar.")
+       {
+               return cvar(substring(expr, 5, strlen(expr)));
+       }
+
+       // Search for fields
+       switch(expr)
+       {
+               case "health":
+                       return this.health;
+               case "speed":
+                       return vlen(this.velocity);
+               case "flagcarrier":
+                       return ((this.flagcarried!=NULL));
+       }
+
+       LOG_INFO(strcat("ERROR: Unable to convert the expression '",expr,"' into a numeric value\n"));
+       return 0;
+}
+
+float bot_cmd_if(entity this)
+{
+       string expr, val_a, val_b;
+       float cmpofs;
+
+       if(this.bot_cmd_condition_status != CMD_CONDITION_NONE)
+       {
+               // Only one "if" block is allowed at time
+               LOG_INFO("ERROR: Only one conditional block can be processed at time");
+               bot_clearqueue(this);
+               return CMD_STATUS_ERROR;
+       }
+
+       this.bot_cmd_condition_status |= CMD_CONDITION_true_BLOCK;
+
+       // search for operators
+       expr = bot_cmd.bot_cmd_parm_string;
+
+       cmpofs = strstrofs(expr,"=",0);
+
+       if(cmpofs>0)
+       {
+               val_a = substring(expr,0,cmpofs);
+               val_b = substring(expr,cmpofs+1,strlen(expr));
+
+               if(bot_cmd_eval(this, val_a)==bot_cmd_eval(this, val_b))
+                       this.bot_cmd_condition_status |= CMD_CONDITION_true;
+               else
+                       this.bot_cmd_condition_status |= CMD_CONDITION_false;
+
+               return CMD_STATUS_FINISHED;
+       }
+
+       cmpofs = strstrofs(expr,">",0);
+
+       if(cmpofs>0)
+       {
+               val_a = substring(expr,0,cmpofs);
+               val_b = substring(expr,cmpofs+1,strlen(expr));
+
+               if(bot_cmd_eval(this, val_a)>bot_cmd_eval(this, val_b))
+                       this.bot_cmd_condition_status |= CMD_CONDITION_true;
+               else
+                       this.bot_cmd_condition_status |= CMD_CONDITION_false;
+
+               return CMD_STATUS_FINISHED;
+       }
+
+       cmpofs = strstrofs(expr,"<",0);
+
+       if(cmpofs>0)
+       {
+               val_a = substring(expr,0,cmpofs);
+               val_b = substring(expr,cmpofs+1,strlen(expr));
+
+               if(bot_cmd_eval(this, val_a)<bot_cmd_eval(this, val_b))
+                       this.bot_cmd_condition_status |= CMD_CONDITION_true;
+               else
+                       this.bot_cmd_condition_status |= CMD_CONDITION_false;
+
+               return CMD_STATUS_FINISHED;
+       }
+
+       if(bot_cmd_eval(this, expr))
+               this.bot_cmd_condition_status |= CMD_CONDITION_true;
+       else
+               this.bot_cmd_condition_status |= CMD_CONDITION_false;
+
+       return CMD_STATUS_FINISHED;
+}
+
+float bot_cmd_else(entity this)
+{
+       this.bot_cmd_condition_status &= ~CMD_CONDITION_true_BLOCK;
+       this.bot_cmd_condition_status |= CMD_CONDITION_false_BLOCK;
+       return CMD_STATUS_FINISHED;
+}
+
+float bot_cmd_fi(entity this)
+{
+       this.bot_cmd_condition_status = CMD_CONDITION_NONE;
+       return CMD_STATUS_FINISHED;
+}
+
+float bot_cmd_resetaim(entity this)
+{
+       this.v_angle = '0 0 0';
+       return CMD_STATUS_FINISHED;
+}
+
+.float bot_cmd_aim_begintime;
+.float bot_cmd_aim_endtime;
+.vector bot_cmd_aim_begin;
+.vector bot_cmd_aim_end;
+
+float bot_cmd_aim(entity this)
+{
+       // Current direction
+       if(this.bot_cmd_aim_endtime)
+       {
+               float progress;
+
+               progress = min(1 - (this.bot_cmd_aim_endtime - time) / (this.bot_cmd_aim_endtime - this.bot_cmd_aim_begintime),1);
+               this.v_angle = this.bot_cmd_aim_begin + ((this.bot_cmd_aim_end - this.bot_cmd_aim_begin) * progress);
+
+               if(time>=this.bot_cmd_aim_endtime)
+               {
+                       this.bot_cmd_aim_endtime = 0;
+                       return CMD_STATUS_FINISHED;
+               }
+               else
+                       return CMD_STATUS_EXECUTING;
+       }
+
+       // New aiming direction
+       string parms;
+       float tokens, step;
+
+       parms = bot_cmd.bot_cmd_parm_string;
+
+       tokens = tokenizebyseparator(parms, " ");
+
+       if(tokens<2||tokens>3)
+               return CMD_STATUS_ERROR;
+
+       step = (tokens == 3) ? stof(argv(2)) : 0;
+
+       if(step == 0)
+       {
+               this.v_angle_x -= stof(argv(1));
+               this.v_angle_y += stof(argv(0));
+               return CMD_STATUS_FINISHED;
+       }
+
+       this.bot_cmd_aim_begin = this.v_angle;
+
+       this.bot_cmd_aim_end_x = this.v_angle.x - stof(argv(1));
+       this.bot_cmd_aim_end_y = this.v_angle.y + stof(argv(0));
+       this.bot_cmd_aim_end_z = 0;
+
+       this.bot_cmd_aim_begintime = time;
+       this.bot_cmd_aim_endtime = time + step;
+
+       return CMD_STATUS_EXECUTING;
+}
+
+float bot_cmd_aimtarget(entity this)
+{
+       if(this.bot_cmd_aim_endtime)
+       {
+               return bot_cmd_aim(this);
+       }
+
+       entity e;
+       string parms;
+       vector v;
+       float tokens, step;
+
+       parms = bot_cmd.bot_cmd_parm_string;
+
+       tokens = tokenizebyseparator(parms, " ");
+
+       e = bot_getplace(this, argv(0));
+       if(!e)
+               return CMD_STATUS_ERROR;
+
+       v = e.origin + (e.mins + e.maxs) * 0.5;
+
+       if(tokens==1)
+       {
+               this.v_angle = vectoangles(v - (this.origin + this.view_ofs));
+               this.v_angle_x = -this.v_angle.x;
+               return CMD_STATUS_FINISHED;
+       }
+
+       if(tokens<1||tokens>2)
+               return CMD_STATUS_ERROR;
+
+       step = stof(argv(1));
+
+       this.bot_cmd_aim_begin = this.v_angle;
+       this.bot_cmd_aim_end = vectoangles(v - (this.origin + this.view_ofs));
+       this.bot_cmd_aim_end_x = -this.bot_cmd_aim_end.x;
+
+       this.bot_cmd_aim_begintime = time;
+       this.bot_cmd_aim_endtime = time + step;
+
+       return CMD_STATUS_EXECUTING;
+}
+
+.int bot_cmd_keys;
+
+const int BOT_CMD_KEY_NONE             = 0;
+const int BOT_CMD_KEY_FORWARD  = BIT(0);
+const int BOT_CMD_KEY_BACKWARD         = BIT(1);
+const int BOT_CMD_KEY_RIGHT    = BIT(2);
+const int BOT_CMD_KEY_LEFT             = BIT(3);
+const int BOT_CMD_KEY_JUMP             = BIT(4);
+const int BOT_CMD_KEY_ATTACK1  = BIT(5);
+const int BOT_CMD_KEY_ATTACK2  = BIT(6);
+const int BOT_CMD_KEY_USE              = BIT(7);
+const int BOT_CMD_KEY_HOOK             = BIT(8);
+const int BOT_CMD_KEY_CROUCH   = BIT(9);
+const int BOT_CMD_KEY_CHAT             = BIT(10);
+
+bool bot_presskeys(entity this)
+{
+       this.movement = '0 0 0';
+       PHYS_INPUT_BUTTON_JUMP(this) = false;
+       PHYS_INPUT_BUTTON_CROUCH(this) = false;
+       PHYS_INPUT_BUTTON_ATCK(this) = false;
+       PHYS_INPUT_BUTTON_ATCK2(this) = false;
+       PHYS_INPUT_BUTTON_USE(this) = false;
+       PHYS_INPUT_BUTTON_HOOK(this) = false;
+       PHYS_INPUT_BUTTON_CHAT(this) = false;
+
+       if(this.bot_cmd_keys == BOT_CMD_KEY_NONE)
+               return false;
+
+       if(this.bot_cmd_keys & BOT_CMD_KEY_FORWARD)
+               this.movement_x = autocvar_sv_maxspeed;
+       else if(this.bot_cmd_keys & BOT_CMD_KEY_BACKWARD)
+               this.movement_x = -autocvar_sv_maxspeed;
+
+       if(this.bot_cmd_keys & BOT_CMD_KEY_RIGHT)
+               this.movement_y = autocvar_sv_maxspeed;
+       else if(this.bot_cmd_keys & BOT_CMD_KEY_LEFT)
+               this.movement_y = -autocvar_sv_maxspeed;
+
+       if(this.bot_cmd_keys & BOT_CMD_KEY_JUMP)
+               PHYS_INPUT_BUTTON_JUMP(this) = true;
+
+       if(this.bot_cmd_keys & BOT_CMD_KEY_CROUCH)
+               PHYS_INPUT_BUTTON_CROUCH(this) = true;
+
+       if(this.bot_cmd_keys & BOT_CMD_KEY_ATTACK1)
+               PHYS_INPUT_BUTTON_ATCK(this) = true;
+
+       if(this.bot_cmd_keys & BOT_CMD_KEY_ATTACK2)
+               PHYS_INPUT_BUTTON_ATCK2(this) = true;
+
+       if(this.bot_cmd_keys & BOT_CMD_KEY_USE)
+               PHYS_INPUT_BUTTON_USE(this) = true;
+
+       if(this.bot_cmd_keys & BOT_CMD_KEY_HOOK)
+               PHYS_INPUT_BUTTON_HOOK(this) = true;
+
+       if(this.bot_cmd_keys & BOT_CMD_KEY_CHAT)
+               PHYS_INPUT_BUTTON_CHAT(this) = true;
+
+       return true;
+}
+
+
+float bot_cmd_keypress_handler(entity this, string key, float enabled)
+{
+       switch(key)
+       {
+               case "all":
+                       if(enabled)
+                               this.bot_cmd_keys = power2of(20) - 1; // >:)
+                       else
+                               this.bot_cmd_keys = BOT_CMD_KEY_NONE;
+               case "forward":
+                       if(enabled)
+                       {
+                               this.bot_cmd_keys |= BOT_CMD_KEY_FORWARD;
+                               this.bot_cmd_keys &= ~BOT_CMD_KEY_BACKWARD;
+                       }
+                       else
+                               this.bot_cmd_keys &= ~BOT_CMD_KEY_FORWARD;
+                       break;
+               case "backward":
+                       if(enabled)
+                       {
+                               this.bot_cmd_keys |= BOT_CMD_KEY_BACKWARD;
+                               this.bot_cmd_keys &= ~BOT_CMD_KEY_FORWARD;
+                       }
+                       else
+                               this.bot_cmd_keys &= ~BOT_CMD_KEY_BACKWARD;
+                       break;
+               case "left":
+                       if(enabled)
+                       {
+                               this.bot_cmd_keys |= BOT_CMD_KEY_LEFT;
+                               this.bot_cmd_keys &= ~BOT_CMD_KEY_RIGHT;
+                       }
+                       else
+                               this.bot_cmd_keys &= ~BOT_CMD_KEY_LEFT;
+                       break;
+               case "right":
+                       if(enabled)
+                       {
+                               this.bot_cmd_keys |= BOT_CMD_KEY_RIGHT;
+                               this.bot_cmd_keys &= ~BOT_CMD_KEY_LEFT;
+                       }
+                       else
+                               this.bot_cmd_keys &= ~BOT_CMD_KEY_RIGHT;
+                       break;
+               case "jump":
+                       if(enabled)
+                               this.bot_cmd_keys |= BOT_CMD_KEY_JUMP;
+                       else
+                               this.bot_cmd_keys &= ~BOT_CMD_KEY_JUMP;
+                       break;
+               case "crouch":
+                       if(enabled)
+                               this.bot_cmd_keys |= BOT_CMD_KEY_CROUCH;
+                       else
+                               this.bot_cmd_keys &= ~BOT_CMD_KEY_CROUCH;
+                       break;
+               case "attack1":
+                       if(enabled)
+                               this.bot_cmd_keys |= BOT_CMD_KEY_ATTACK1;
+                       else
+                               this.bot_cmd_keys &= ~BOT_CMD_KEY_ATTACK1;
+                       break;
+               case "attack2":
+                       if(enabled)
+                               this.bot_cmd_keys |= BOT_CMD_KEY_ATTACK2;
+                       else
+                               this.bot_cmd_keys &= ~BOT_CMD_KEY_ATTACK2;
+                       break;
+               case "use":
+                       if(enabled)
+                               this.bot_cmd_keys |= BOT_CMD_KEY_USE;
+                       else
+                               this.bot_cmd_keys &= ~BOT_CMD_KEY_USE;
+                       break;
+               case "hook":
+                       if(enabled)
+                               this.bot_cmd_keys |= BOT_CMD_KEY_HOOK;
+                       else
+                               this.bot_cmd_keys &= ~BOT_CMD_KEY_HOOK;
+                       break;
+               case "chat":
+                       if(enabled)
+                               this.bot_cmd_keys |= BOT_CMD_KEY_CHAT;
+                       else
+                               this.bot_cmd_keys &= ~BOT_CMD_KEY_CHAT;
+                       break;
+               default:
+                       break;
+       }
+
+       return CMD_STATUS_FINISHED;
+}
+
+float bot_cmd_presskey(entity this)
+{
+       string key;
+
+       key = bot_cmd.bot_cmd_parm_string;
+
+       bot_cmd_keypress_handler(this, key,true);
+
+       return CMD_STATUS_FINISHED;
+}
+
+float bot_cmd_releasekey(entity this)
+{
+       string key;
+
+       key = bot_cmd.bot_cmd_parm_string;
+
+       return bot_cmd_keypress_handler(this, key,false);
+}
+
+float bot_cmd_pause(entity this)
+{
+       PHYS_INPUT_BUTTON_DRAG(this) = false;
+       PHYS_INPUT_BUTTON_USE(this) = false;
+       PHYS_INPUT_BUTTON_ATCK(this) = false;
+       PHYS_INPUT_BUTTON_JUMP(this) = false;
+       PHYS_INPUT_BUTTON_HOOK(this) = false;
+       PHYS_INPUT_BUTTON_CHAT(this) = false;
+       PHYS_INPUT_BUTTON_ATCK2(this) = false;
+       PHYS_INPUT_BUTTON_CROUCH(this) = false;
+
+       this.movement = '0 0 0';
+       this.bot_cmd_keys = BOT_CMD_KEY_NONE;
+
+       this.bot_exec_status |= BOT_EXEC_STATUS_PAUSED;
+       return CMD_STATUS_FINISHED;
+}
+
+float bot_cmd_moveto(entity this)
+{
+       return this.cmd_moveto(this, bot_cmd.bot_cmd_parm_vector);
+}
+
+float bot_cmd_movetotarget(entity this)
+{
+       entity e;
+       e = bot_getplace(this, bot_cmd.bot_cmd_parm_string);
+       if(!e)
+               return CMD_STATUS_ERROR;
+       return this.cmd_moveto(this, e.origin + (e.mins + e.maxs) * 0.5);
+}
+
+float bot_cmd_resetgoal(entity this)
+{
+       return this.cmd_resetgoal(this);
+}
+
+
+float bot_cmd_sound(entity this)
+{
+       string f;
+       f = bot_cmd.bot_cmd_parm_string;
+
+       float n = tokenizebyseparator(f, " ");
+
+       string sample = f;
+       float chan = CH_WEAPON_B;
+       float vol = VOL_BASE;
+       float atten = ATTEN_MIN;
+
+       if(n >= 1)
+               sample = argv(n - 1);
+       if(n >= 2)
+               chan = stof(argv(0));
+       if(n >= 3)
+               vol = stof(argv(1));
+       if(n >= 4)
+               atten = stof(argv(2));
+
+       precache_sound(f);
+       _sound(this, chan, sample, vol, atten);
+
+       return CMD_STATUS_FINISHED;
+}
+
+.entity tuba_note;
+float bot_cmd_debug_assert_canfire(entity this)
+{
+       float f = bot_cmd.bot_cmd_parm_float;
+
+       int slot = 0; // TODO: unhardcode?
+       .entity weaponentity = weaponentities[slot];
+       if(this.(weaponentity).state != WS_READY)
+       {
+               if(f)
+               {
+                       this.colormod = '0 8 8';
+                       LOG_INFO("Bot ", this.netname, " using ", this.weaponname, " wants to fire, inhibited by weaponentity state\n");
+               }
+       }
+       else if(ATTACK_FINISHED(this, slot) > time)
+       {
+               if(f)
+               {
+                       this.colormod = '8 0 8';
+                       LOG_INFO("Bot ", this.netname, " using ", this.weaponname, " wants to fire, inhibited by ATTACK_FINISHED (", ftos(ATTACK_FINISHED(this, slot) - time), " seconds left)\n");
+               }
+       }
+       else if(this.tuba_note)
+       {
+               if(f)
+               {
+                       this.colormod = '8 0 0';
+                       LOG_INFO("Bot ", this.netname, " using ", this.weaponname, " wants to fire, bot still has an active tuba note\n");
+               }
+       }
+       else
+       {
+               if(!f)
+               {
+                       this.colormod = '8 8 0';
+                       LOG_INFO("Bot ", this.netname, " using ", this.weaponname, " thinks it has fired, but apparently did not; ATTACK_FINISHED says ", ftos(ATTACK_FINISHED(this, slot) - time), " seconds left\n");
+               }
+       }
+
+       return CMD_STATUS_FINISHED;
+}
+
+//
+
+void bot_command_executed(entity this, bool rm)
+{
+       entity cmd;
+
+       cmd = bot_cmd;
+
+       if(rm)
+               bot_dequeuecommand(this, this.bot_cmd_execution_index);
+
+       this.bot_cmd_execution_index++;
+}
+
+void bot_setcurrentcommand(entity this)
+{
+       bot_cmd = NULL;
+
+       if(!this.bot_cmd_current)
+       {
+               this.bot_cmd_current = new_pure(bot_cmd);
+               this.bot_cmd_current.is_bot_cmd = true;
+       }
+
+       bot_cmd = this.bot_cmd_current;
+       if(bot_cmd.bot_cmd_index != this.bot_cmd_execution_index || this.bot_cmd_execution_index == 0)
+       {
+               if(bot_havecommand(this, this.bot_cmd_execution_index))
+               {
+                       string cmdstring;
+                       cmdstring = bot_readcommand(this, this.bot_cmd_execution_index);
+                       if(bot_decodecommand(cmdstring))
+                       {
+                               bot_cmd.owner = this;
+                               bot_cmd.bot_cmd_index = this.bot_cmd_execution_index;
+                       }
+                       else
+                       {
+                               // Invalid command, remove from queue
+                               bot_cmd = NULL;
+                               bot_dequeuecommand(this, this.bot_cmd_execution_index);
+                               this.bot_cmd_execution_index++;
+                       }
+               }
+               else
+                       bot_cmd = NULL;
+       }
+}
+
+void bot_resetqueues()
+{
+       FOREACH_CLIENT(it.isbot, LAMBDA(
+               it.bot_cmd_execution_index = 0;
+               bot_clearqueue(it);
+               // also, cancel all barriers
+               it.bot_barrier = 0;
+               for(int i = 0; i < it.bot_places_count; ++i)
+               {
+                       strunzone(it.(bot_placenames[i]));
+                       it.(bot_placenames[i]) = string_null;
+               }
+               it.bot_places_count = 0;
+       ));
+
+       bot_barriertime = time;
+}
+
+// Here we map commands to functions and deal with complex interactions between commands and execution states
+// NOTE: Of course you need to include your commands here too :)
+float bot_execute_commands_once(entity this)
+{
+       float status, ispressingkey;
+
+       // Find command
+       bot_setcurrentcommand(this);
+
+       // if we have no bot command, better return
+       // old logic kept pressing previously pressed keys, but that has problems
+       // (namely, it means you cannot make a bot "normal" ever again)
+       // to keep a bot walking for a while, use the "wait" bot command
+       if(bot_cmd == NULL)
+               return false;
+
+       // Ignore all commands except continue when the bot is paused
+       if(this.bot_exec_status & BOT_EXEC_STATUS_PAUSED)
+       if(bot_cmd.bot_cmd_type!=BOT_CMD_CONTINUE)
+       {
+               if(bot_cmd.bot_cmd_type!=BOT_CMD_NULL)
+               {
+                       bot_command_executed(this, true);
+                       LOG_INFO( "WARNING: Commands are ignored while the bot is paused. Use the command 'continue' instead.\n");
+               }
+               return 1;
+       }
+
+       // Keep pressing keys raised by the "presskey" command
+       ispressingkey = boolean(bot_presskeys(this));
+
+       // Handle conditions
+       if (!(bot_cmd.bot_cmd_type==BOT_CMD_FI||bot_cmd.bot_cmd_type==BOT_CMD_ELSE))
+       if(this.bot_cmd_condition_status & CMD_CONDITION_true && this.bot_cmd_condition_status & CMD_CONDITION_false_BLOCK)
+       {
+               bot_command_executed(this, true);
+               return -1;
+       }
+       else if(this.bot_cmd_condition_status & CMD_CONDITION_false && this.bot_cmd_condition_status & CMD_CONDITION_true_BLOCK)
+       {
+               bot_command_executed(this, true);
+               return -1;
+       }
+
+       // Map commands to functions
+       switch(bot_cmd.bot_cmd_type)
+       {
+               case BOT_CMD_NULL:
+                       return ispressingkey;
+                       //break;
+               case BOT_CMD_PAUSE:
+                       status = bot_cmd_pause(this);
+                       break;
+               case BOT_CMD_CONTINUE:
+                       status = bot_cmd_continue(this);
+                       break;
+               case BOT_CMD_WAIT:
+                       status = bot_cmd_wait(this);
+                       break;
+               case BOT_CMD_WAIT_UNTIL:
+                       status = bot_cmd_wait_until(this);
+                       break;
+               case BOT_CMD_TURN:
+                       status = bot_cmd_turn(this);
+                       break;
+               case BOT_CMD_MOVETO:
+                       status = bot_cmd_moveto(this);
+                       break;
+               case BOT_CMD_MOVETOTARGET:
+                       status = bot_cmd_movetotarget(this);
+                       break;
+               case BOT_CMD_RESETGOAL:
+                       status = bot_cmd_resetgoal(this);
+                       break;
+               case BOT_CMD_CC:
+                       status = bot_cmd_cc(this);
+                       break;
+               case BOT_CMD_IF:
+                       status = bot_cmd_if(this);
+                       break;
+               case BOT_CMD_ELSE:
+                       status = bot_cmd_else(this);
+                       break;
+               case BOT_CMD_FI:
+                       status = bot_cmd_fi(this);
+                       break;
+               case BOT_CMD_RESETAIM:
+                       status = bot_cmd_resetaim(this);
+                       break;
+               case BOT_CMD_AIM:
+                       status = bot_cmd_aim(this);
+                       break;
+               case BOT_CMD_AIMTARGET:
+                       status = bot_cmd_aimtarget(this);
+                       break;
+               case BOT_CMD_PRESSKEY:
+                       status = bot_cmd_presskey(this);
+                       break;
+               case BOT_CMD_RELEASEKEY:
+                       status = bot_cmd_releasekey(this);
+                       break;
+               case BOT_CMD_SELECTWEAPON:
+                       status = bot_cmd_select_weapon(this);
+                       break;
+               case BOT_CMD_IMPULSE:
+                       status = bot_cmd_impulse(this);
+                       break;
+               case BOT_CMD_BARRIER:
+                       status = bot_cmd_barrier(this);
+                       break;
+               case BOT_CMD_CONSOLE:
+                       localcmd(strcat(bot_cmd.bot_cmd_parm_string, "\n"));
+                       status = CMD_STATUS_FINISHED;
+                       break;
+               case BOT_CMD_SOUND:
+                       status = bot_cmd_sound(this);
+                       break;
+               case BOT_CMD_DEBUG_ASSERT_CANFIRE:
+                       status = bot_cmd_debug_assert_canfire(this);
+                       break;
+               default:
+                       LOG_INFO(strcat("ERROR: Invalid command on queue with id '",ftos(bot_cmd.bot_cmd_type),"'\n"));
+                       return 0;
+       }
+
+       if (status==CMD_STATUS_ERROR)
+               LOG_INFO(strcat("ERROR: The command '",bot_cmd_string[bot_cmd.bot_cmd_type],"' returned an error status\n"));
+
+       // Move execution pointer
+       if(status==CMD_STATUS_EXECUTING)
+       {
+               return 1;
+       }
+       else
+       {
+               if(autocvar_g_debug_bot_commands)
+               {
+                       string parms;
+
+                       switch(bot_cmd_parm_type[bot_cmd.bot_cmd_type])
+                       {
+                               case BOT_CMD_PARAMETER_FLOAT:
+                                       parms = ftos(bot_cmd.bot_cmd_parm_float);
+                                       break;
+                               case BOT_CMD_PARAMETER_STRING:
+                                       parms = bot_cmd.bot_cmd_parm_string;
+                                       break;
+                               case BOT_CMD_PARAMETER_VECTOR:
+                                       parms = vtos(bot_cmd.bot_cmd_parm_vector);
+                                       break;
+                               default:
+                                       parms = "";
+                                       break;
+                       }
+                       clientcommand(this,strcat("say ^7", bot_cmd_string[bot_cmd.bot_cmd_type]," ",parms,"\n"));
+               }
+
+               bot_command_executed(this, true);
+       }
+
+       if(status == CMD_STATUS_FINISHED)
+               return -1;
+
+       return CMD_STATUS_ERROR;
+}
+
+// This function should be (the only) called directly from the bot ai loop
+int bot_execute_commands(entity this)
+{
+       int f;
+       do
+       {
+               f = bot_execute_commands_once(this);
+       }
+       while(f < 0);
+       return f;
+}
diff --git a/qcsrc/server/bot/default/scripting.qh b/qcsrc/server/bot/default/scripting.qh
new file mode 100644 (file)
index 0000000..cb6cd87
--- /dev/null
@@ -0,0 +1,81 @@
+#pragma once
+
+#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(entity, vector) cmd_moveto;
+.float(entity) 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 this);
+entity find_bot_by_name(string name);
+entity find_bot_by_number(float number);
diff --git a/qcsrc/server/bot/default/waypoints.qc b/qcsrc/server/bot/default/waypoints.qc
new file mode 100644 (file)
index 0000000..8475640
--- /dev/null
@@ -0,0 +1,1104 @@
+#include "waypoints.qh"
+
+#include "cvars.qh"
+
+#include "bot.qh"
+#include "navigation.qh"
+
+#include <common/state.qh>
+
+#include "../../antilag.qh"
+
+#include <common/constants.qh>
+
+#include <lib/warpzone/common.qh>
+#include <lib/warpzone/util_server.qh>
+
+// create a new spawnfunc_waypoint and automatically link it to other waypoints, and link
+// them back to it as well
+// (suitable for spawnfunc_waypoint editor)
+entity waypoint_spawn(vector m1, vector m2, float f)
+{
+       if(!(f & WAYPOINTFLAG_PERSONAL))
+       {
+               IL_EACH(g_waypoints, boxesoverlap(m1, m2, it.absmin, it.absmax),
+               {
+                       return it;
+               });
+       }
+
+       entity w = new(waypoint);
+       IL_PUSH(g_waypoints, w);
+       w.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_PLAYERCLIP | DPCONTENTS_BOTCLIP;
+       w.wpflags = f;
+       w.solid = SOLID_TRIGGER;
+       setorigin(w, (m1 + m2) * 0.5);
+       setsize(w, m1 - w.origin, m2 - w.origin);
+       if (vlen(w.size) > 0)
+               w.wpisbox = true;
+
+       if(!w.wpisbox)
+       {
+               setsize(w, STAT(PL_MIN, NULL) - '1 1 0', STAT(PL_MAX, NULL) + '1 1 0');
+               if(!move_out_of_solid(w))
+               {
+                       if(!(f & WAYPOINTFLAG_GENERATED))
+                       {
+                               LOG_TRACE("Killed a waypoint that was stuck in solid at ", vtos(w.origin));
+                               delete(w);
+                               return NULL;
+                       }
+                       else
+                       {
+                               if(autocvar_developer)
+                               {
+                                       LOG_INFO("A generated waypoint is stuck in solid at ", vtos(w.origin), "\n");
+                                       backtrace("Waypoint stuck");
+                               }
+                       }
+               }
+               setsize(w, '0 0 0', '0 0 0');
+       }
+
+       waypoint_clearlinks(w);
+       //waypoint_schedulerelink(w);
+
+       if (autocvar_g_waypointeditor)
+       {
+               m1 = w.mins;
+               m2 = w.maxs;
+               setmodel(w, MDL_WAYPOINT); w.effects = EF_LOWPRECISION;
+               setsize(w, m1, m2);
+               if (w.wpflags & WAYPOINTFLAG_ITEM)
+                       w.colormod = '1 0 0';
+               else if (w.wpflags & WAYPOINTFLAG_GENERATED)
+                       w.colormod = '1 1 0';
+               else
+                       w.colormod = '1 1 1';
+       }
+       else
+               w.model = "";
+
+       return w;
+}
+
+// add a new link to the spawnfunc_waypoint, replacing the furthest link it already has
+void waypoint_addlink(entity from, entity to)
+{
+       float c;
+
+       if (from == to)
+               return;
+       if (from.wpflags & WAYPOINTFLAG_NORELINK)
+               return;
+
+       if (from.wp00 == to) return;if (from.wp01 == to) return;if (from.wp02 == to) return;if (from.wp03 == to) return;
+       if (from.wp04 == to) return;if (from.wp05 == to) return;if (from.wp06 == to) return;if (from.wp07 == to) return;
+       if (from.wp08 == to) return;if (from.wp09 == to) return;if (from.wp10 == to) return;if (from.wp11 == to) return;
+       if (from.wp12 == to) return;if (from.wp13 == to) return;if (from.wp14 == to) return;if (from.wp15 == to) return;
+       if (from.wp16 == to) return;if (from.wp17 == to) return;if (from.wp18 == to) return;if (from.wp19 == to) return;
+       if (from.wp20 == to) return;if (from.wp21 == to) return;if (from.wp22 == to) return;if (from.wp23 == to) return;
+       if (from.wp24 == to) return;if (from.wp25 == to) return;if (from.wp26 == to) return;if (from.wp27 == to) return;
+       if (from.wp28 == to) return;if (from.wp29 == to) return;if (from.wp30 == to) return;if (from.wp31 == to) return;
+
+       if (to.wpisbox || from.wpisbox)
+       {
+               // if either is a box we have to find the nearest points on them to
+               // calculate the distance properly
+               vector v1, v2, m1, m2;
+               v1 = from.origin;
+               m1 = to.absmin;
+               m2 = to.absmax;
+               v1_x = bound(m1_x, v1_x, m2_x);
+               v1_y = bound(m1_y, v1_y, m2_y);
+               v1_z = bound(m1_z, v1_z, m2_z);
+               v2 = to.origin;
+               m1 = from.absmin;
+               m2 = from.absmax;
+               v2_x = bound(m1_x, v2_x, m2_x);
+               v2_y = bound(m1_y, v2_y, m2_y);
+               v2_z = bound(m1_z, v2_z, m2_z);
+               v2 = to.origin;
+               c = vlen(v2 - v1);
+       }
+       else
+               c = vlen(to.origin - from.origin);
+
+       if (from.wp31mincost < c) return;
+       if (from.wp30mincost < c) {from.wp31 = to;from.wp31mincost = c;return;} from.wp31 = from.wp30;from.wp31mincost = from.wp30mincost;
+       if (from.wp29mincost < c) {from.wp30 = to;from.wp30mincost = c;return;} from.wp30 = from.wp29;from.wp30mincost = from.wp29mincost;
+       if (from.wp28mincost < c) {from.wp29 = to;from.wp29mincost = c;return;} from.wp29 = from.wp28;from.wp29mincost = from.wp28mincost;
+       if (from.wp27mincost < c) {from.wp28 = to;from.wp28mincost = c;return;} from.wp28 = from.wp27;from.wp28mincost = from.wp27mincost;
+       if (from.wp26mincost < c) {from.wp27 = to;from.wp27mincost = c;return;} from.wp27 = from.wp26;from.wp27mincost = from.wp26mincost;
+       if (from.wp25mincost < c) {from.wp26 = to;from.wp26mincost = c;return;} from.wp26 = from.wp25;from.wp26mincost = from.wp25mincost;
+       if (from.wp24mincost < c) {from.wp25 = to;from.wp25mincost = c;return;} from.wp25 = from.wp24;from.wp25mincost = from.wp24mincost;
+       if (from.wp23mincost < c) {from.wp24 = to;from.wp24mincost = c;return;} from.wp24 = from.wp23;from.wp24mincost = from.wp23mincost;
+       if (from.wp22mincost < c) {from.wp23 = to;from.wp23mincost = c;return;} from.wp23 = from.wp22;from.wp23mincost = from.wp22mincost;
+       if (from.wp21mincost < c) {from.wp22 = to;from.wp22mincost = c;return;} from.wp22 = from.wp21;from.wp22mincost = from.wp21mincost;
+       if (from.wp20mincost < c) {from.wp21 = to;from.wp21mincost = c;return;} from.wp21 = from.wp20;from.wp21mincost = from.wp20mincost;
+       if (from.wp19mincost < c) {from.wp20 = to;from.wp20mincost = c;return;} from.wp20 = from.wp19;from.wp20mincost = from.wp19mincost;
+       if (from.wp18mincost < c) {from.wp19 = to;from.wp19mincost = c;return;} from.wp19 = from.wp18;from.wp19mincost = from.wp18mincost;
+       if (from.wp17mincost < c) {from.wp18 = to;from.wp18mincost = c;return;} from.wp18 = from.wp17;from.wp18mincost = from.wp17mincost;
+       if (from.wp16mincost < c) {from.wp17 = to;from.wp17mincost = c;return;} from.wp17 = from.wp16;from.wp17mincost = from.wp16mincost;
+       if (from.wp15mincost < c) {from.wp16 = to;from.wp16mincost = c;return;} from.wp16 = from.wp15;from.wp16mincost = from.wp15mincost;
+       if (from.wp14mincost < c) {from.wp15 = to;from.wp15mincost = c;return;} from.wp15 = from.wp14;from.wp15mincost = from.wp14mincost;
+       if (from.wp13mincost < c) {from.wp14 = to;from.wp14mincost = c;return;} from.wp14 = from.wp13;from.wp14mincost = from.wp13mincost;
+       if (from.wp12mincost < c) {from.wp13 = to;from.wp13mincost = c;return;} from.wp13 = from.wp12;from.wp13mincost = from.wp12mincost;
+       if (from.wp11mincost < c) {from.wp12 = to;from.wp12mincost = c;return;} from.wp12 = from.wp11;from.wp12mincost = from.wp11mincost;
+       if (from.wp10mincost < c) {from.wp11 = to;from.wp11mincost = c;return;} from.wp11 = from.wp10;from.wp11mincost = from.wp10mincost;
+       if (from.wp09mincost < c) {from.wp10 = to;from.wp10mincost = c;return;} from.wp10 = from.wp09;from.wp10mincost = from.wp09mincost;
+       if (from.wp08mincost < c) {from.wp09 = to;from.wp09mincost = c;return;} from.wp09 = from.wp08;from.wp09mincost = from.wp08mincost;
+       if (from.wp07mincost < c) {from.wp08 = to;from.wp08mincost = c;return;} from.wp08 = from.wp07;from.wp08mincost = from.wp07mincost;
+       if (from.wp06mincost < c) {from.wp07 = to;from.wp07mincost = c;return;} from.wp07 = from.wp06;from.wp07mincost = from.wp06mincost;
+       if (from.wp05mincost < c) {from.wp06 = to;from.wp06mincost = c;return;} from.wp06 = from.wp05;from.wp06mincost = from.wp05mincost;
+       if (from.wp04mincost < c) {from.wp05 = to;from.wp05mincost = c;return;} from.wp05 = from.wp04;from.wp05mincost = from.wp04mincost;
+       if (from.wp03mincost < c) {from.wp04 = to;from.wp04mincost = c;return;} from.wp04 = from.wp03;from.wp04mincost = from.wp03mincost;
+       if (from.wp02mincost < c) {from.wp03 = to;from.wp03mincost = c;return;} from.wp03 = from.wp02;from.wp03mincost = from.wp02mincost;
+       if (from.wp01mincost < c) {from.wp02 = to;from.wp02mincost = c;return;} from.wp02 = from.wp01;from.wp02mincost = from.wp01mincost;
+       if (from.wp00mincost < c) {from.wp01 = to;from.wp01mincost = c;return;} from.wp01 = from.wp00;from.wp01mincost = from.wp00mincost;
+       from.wp00 = to;from.wp00mincost = c;return;
+}
+
+// relink this spawnfunc_waypoint
+// (precompile a list of all reachable waypoints from this spawnfunc_waypoint)
+// (SLOW!)
+void waypoint_think(entity this)
+{
+       vector sv, sm1, sm2, ev, em1, em2, dv;
+
+       bot_calculate_stepheightvec();
+
+       bot_navigation_movemode = ((autocvar_bot_navigation_ignoreplayers) ? MOVE_NOMONSTERS : MOVE_NORMAL);
+
+       //dprint("waypoint_think wpisbox = ", ftos(this.wpisbox), "\n");
+       sm1 = this.origin + this.mins;
+       sm2 = this.origin + this.maxs;
+       IL_EACH(g_waypoints, true,
+       {
+               if (boxesoverlap(this.absmin, this.absmax, it.absmin, it.absmax))
+               {
+                       waypoint_addlink(this, it);
+                       waypoint_addlink(it, this);
+               }
+               else
+               {
+                       ++relink_total;
+                       if(!checkpvs(this.origin, it))
+                       {
+                               ++relink_pvsculled;
+                               continue;
+                       }
+                       sv = it.origin;
+                       sv.x = bound(sm1_x, sv.x, sm2_x);
+                       sv.y = bound(sm1_y, sv.y, sm2_y);
+                       sv.z = bound(sm1_z, sv.z, sm2_z);
+                       ev = this.origin;
+                       em1 = it.origin + it.mins;
+                       em2 = it.origin + it.maxs;
+                       ev.x = bound(em1_x, ev.x, em2_x);
+                       ev.y = bound(em1_y, ev.y, em2_y);
+                       ev.z = bound(em1_z, ev.z, em2_z);
+                       dv = ev - sv;
+                       dv.z = 0;
+                       if(vdist(dv, >=, 1050)) // max search distance in XY
+                       {
+                               ++relink_lengthculled;
+                               continue;
+                       }
+                       navigation_testtracewalk = 0;
+                       if (!this.wpisbox)
+                       {
+                               tracebox(sv - STAT(PL_MIN, NULL).z * '0 0 1', STAT(PL_MIN, NULL), STAT(PL_MAX, NULL), sv, false, this);
+                               if (!trace_startsolid)
+                               {
+                                       //dprint("sv deviation", vtos(trace_endpos - sv), "\n");
+                                       sv = trace_endpos + '0 0 1';
+                               }
+                       }
+                       if (!it.wpisbox)
+                       {
+                               tracebox(ev - STAT(PL_MIN, NULL).z * '0 0 1', STAT(PL_MIN, NULL), STAT(PL_MAX, NULL), ev, false, it);
+                               if (!trace_startsolid)
+                               {
+                                       //dprint("ev deviation", vtos(trace_endpos - ev), "\n");
+                                       ev = trace_endpos + '0 0 1';
+                               }
+                       }
+                       //traceline(this.origin, it.origin, false, NULL);
+                       //if (trace_fraction == 1)
+                       if (!this.wpisbox && tracewalk(this, sv, STAT(PL_MIN, NULL), STAT(PL_MAX, NULL), ev, MOVE_NOMONSTERS))
+                               waypoint_addlink(this, it);
+                       else
+                               relink_walkculled += 0.5;
+                       if (!it.wpisbox && tracewalk(it, ev, STAT(PL_MIN, NULL), STAT(PL_MAX, NULL), sv, MOVE_NOMONSTERS))
+                               waypoint_addlink(it, this);
+                       else
+                               relink_walkculled += 0.5;
+               }
+       });
+       navigation_testtracewalk = 0;
+       this.wplinked = true;
+}
+
+void waypoint_clearlinks(entity wp)
+{
+       // clear links to other waypoints
+       float f;
+       f = 10000000;
+       wp.wp00 = wp.wp01 = wp.wp02 = wp.wp03 = wp.wp04 = wp.wp05 = wp.wp06 = wp.wp07 = NULL;
+       wp.wp08 = wp.wp09 = wp.wp10 = wp.wp11 = wp.wp12 = wp.wp13 = wp.wp14 = wp.wp15 = NULL;
+       wp.wp16 = wp.wp17 = wp.wp18 = wp.wp19 = wp.wp20 = wp.wp21 = wp.wp22 = wp.wp23 = NULL;
+       wp.wp24 = wp.wp25 = wp.wp26 = wp.wp27 = wp.wp28 = wp.wp29 = wp.wp30 = wp.wp31 = NULL;
+
+       wp.wp00mincost = wp.wp01mincost = wp.wp02mincost = wp.wp03mincost = wp.wp04mincost = wp.wp05mincost = wp.wp06mincost = wp.wp07mincost = f;
+       wp.wp08mincost = wp.wp09mincost = wp.wp10mincost = wp.wp11mincost = wp.wp12mincost = wp.wp13mincost = wp.wp14mincost = wp.wp15mincost = f;
+       wp.wp16mincost = wp.wp17mincost = wp.wp18mincost = wp.wp19mincost = wp.wp20mincost = wp.wp21mincost = wp.wp22mincost = wp.wp23mincost = f;
+       wp.wp24mincost = wp.wp25mincost = wp.wp26mincost = wp.wp27mincost = wp.wp28mincost = wp.wp29mincost = wp.wp30mincost = wp.wp31mincost = f;
+
+       wp.wplinked = false;
+}
+
+// tell a spawnfunc_waypoint to relink
+void waypoint_schedulerelink(entity wp)
+{
+       if (wp == NULL)
+               return;
+       // TODO: add some sort of visible box in edit mode for box waypoints
+       if (autocvar_g_waypointeditor)
+       {
+               vector m1, m2;
+               m1 = wp.mins;
+               m2 = wp.maxs;
+               setmodel(wp, MDL_WAYPOINT); wp.effects = EF_LOWPRECISION;
+               setsize(wp, m1, m2);
+               if (wp.wpflags & WAYPOINTFLAG_ITEM)
+                       wp.colormod = '1 0 0';
+               else if (wp.wpflags & WAYPOINTFLAG_GENERATED)
+                       wp.colormod = '1 1 0';
+               else
+                       wp.colormod = '1 1 1';
+       }
+       else
+               wp.model = "";
+       wp.wpisbox = vlen(wp.size) > 0;
+       wp.enemy = NULL;
+       if (!(wp.wpflags & WAYPOINTFLAG_PERSONAL))
+               wp.owner = NULL;
+       if (!(wp.wpflags & WAYPOINTFLAG_NORELINK))
+               waypoint_clearlinks(wp);
+       // schedule an actual relink on next frame
+       setthink(wp, waypoint_think);
+       wp.nextthink = time;
+       wp.effects = EF_LOWPRECISION;
+}
+
+// spawnfunc_waypoint map entity
+spawnfunc(waypoint)
+{
+       IL_PUSH(g_waypoints, this);
+
+       setorigin(this, this.origin);
+       // schedule a relink after other waypoints have had a chance to spawn
+       waypoint_clearlinks(this);
+       //waypoint_schedulerelink(this);
+}
+
+// remove a spawnfunc_waypoint, and schedule all neighbors to relink
+void waypoint_remove(entity e)
+{
+       // tell all linked waypoints that they need to relink
+       waypoint_schedulerelink(e.wp00);
+       waypoint_schedulerelink(e.wp01);
+       waypoint_schedulerelink(e.wp02);
+       waypoint_schedulerelink(e.wp03);
+       waypoint_schedulerelink(e.wp04);
+       waypoint_schedulerelink(e.wp05);
+       waypoint_schedulerelink(e.wp06);
+       waypoint_schedulerelink(e.wp07);
+       waypoint_schedulerelink(e.wp08);
+       waypoint_schedulerelink(e.wp09);
+       waypoint_schedulerelink(e.wp10);
+       waypoint_schedulerelink(e.wp11);
+       waypoint_schedulerelink(e.wp12);
+       waypoint_schedulerelink(e.wp13);
+       waypoint_schedulerelink(e.wp14);
+       waypoint_schedulerelink(e.wp15);
+       waypoint_schedulerelink(e.wp16);
+       waypoint_schedulerelink(e.wp17);
+       waypoint_schedulerelink(e.wp18);
+       waypoint_schedulerelink(e.wp19);
+       waypoint_schedulerelink(e.wp20);
+       waypoint_schedulerelink(e.wp21);
+       waypoint_schedulerelink(e.wp22);
+       waypoint_schedulerelink(e.wp23);
+       waypoint_schedulerelink(e.wp24);
+       waypoint_schedulerelink(e.wp25);
+       waypoint_schedulerelink(e.wp26);
+       waypoint_schedulerelink(e.wp27);
+       waypoint_schedulerelink(e.wp28);
+       waypoint_schedulerelink(e.wp29);
+       waypoint_schedulerelink(e.wp30);
+       waypoint_schedulerelink(e.wp31);
+       // and now remove the spawnfunc_waypoint
+       delete(e);
+}
+
+// empties the map of waypoints
+void waypoint_removeall()
+{
+       IL_EACH(g_waypoints, true,
+       {
+               delete(it);
+       });
+}
+
+// tell all waypoints to relink
+// (is this useful at all?)
+void waypoint_schedulerelinkall()
+{
+       relink_total = relink_walkculled = relink_pvsculled = relink_lengthculled = 0;
+       IL_EACH(g_waypoints, true,
+       {
+               waypoint_schedulerelink(it);
+       });
+}
+
+// Load waypoint links from file
+float waypoint_load_links()
+{
+       string filename, s;
+       float file, tokens, c = 0, found;
+       entity wp_from = NULL, wp_to;
+       vector wp_to_pos, wp_from_pos;
+       filename = strcat("maps/", mapname);
+       filename = strcat(filename, ".waypoints.cache");
+       file = fopen(filename, FILE_READ);
+
+       if (file < 0)
+       {
+               LOG_TRACE("waypoint links load from ");
+               LOG_TRACE(filename);
+               LOG_TRACE(" failed");
+               return false;
+       }
+
+       while ((s = fgets(file)))
+       {
+               tokens = tokenizebyseparator(s, "*");
+
+               if (tokens!=2)
+               {
+                       // bad file format
+                       fclose(file);
+                       return false;
+               }
+
+               wp_from_pos     = stov(argv(0));
+               wp_to_pos       = stov(argv(1));
+
+               // Search "from" waypoint
+               if(!wp_from || wp_from.origin!=wp_from_pos)
+               {
+                       wp_from = findradius(wp_from_pos, 1);
+                       found = false;
+                       while(wp_from)
+                       {
+                               if(vdist(wp_from.origin - wp_from_pos, <, 1))
+                               if(wp_from.classname == "waypoint")
+                               {
+                                       found = true;
+                                       break;
+                               }
+                               wp_from = wp_from.chain;
+                       }
+
+                       if(!found)
+                       {
+                               LOG_TRACE("waypoint_load_links: couldn't find 'from' waypoint at ", vtos(wp_from.origin));
+                               continue;
+                       }
+
+               }
+
+               // Search "to" waypoint
+               wp_to = findradius(wp_to_pos, 1);
+               found = false;
+               while(wp_to)
+               {
+                       if(vdist(wp_to.origin - wp_to_pos, <, 1))
+                       if(wp_to.classname == "waypoint")
+                       {
+                               found = true;
+                               break;
+                       }
+                       wp_to = wp_to.chain;
+               }
+
+               if(!found)
+               {
+                       LOG_TRACE("waypoint_load_links: couldn't find 'to' waypoint at ", vtos(wp_to.origin));
+                       continue;
+               }
+
+               ++c;
+               waypoint_addlink(wp_from, wp_to);
+       }
+
+       fclose(file);
+
+       LOG_TRACE("loaded ", ftos(c), " waypoint links from maps/", mapname, ".waypoints.cache");
+
+       botframe_cachedwaypointlinks = true;
+       return true;
+}
+
+void waypoint_load_links_hardwired()
+{
+       string filename, s;
+       float file, tokens, c = 0, found;
+       entity wp_from = NULL, wp_to;
+       vector wp_to_pos, wp_from_pos;
+       filename = strcat("maps/", mapname);
+       filename = strcat(filename, ".waypoints.hardwired");
+       file = fopen(filename, FILE_READ);
+
+       botframe_loadedforcedlinks = true;
+
+       if (file < 0)
+       {
+               LOG_TRACE("waypoint links load from ", filename, " failed");
+               return;
+       }
+
+       while ((s = fgets(file)))
+       {
+               if(substring(s, 0, 2)=="//")
+                       continue;
+
+               if(substring(s, 0, 1)=="#")
+                       continue;
+
+               tokens = tokenizebyseparator(s, "*");
+
+               if (tokens!=2)
+                       continue;
+
+               wp_from_pos     = stov(argv(0));
+               wp_to_pos       = stov(argv(1));
+
+               // Search "from" waypoint
+               if(!wp_from || wp_from.origin!=wp_from_pos)
+               {
+                       wp_from = findradius(wp_from_pos, 5);
+                       found = false;
+                       while(wp_from)
+                       {
+                               if(vdist(wp_from.origin - wp_from_pos, <, 5))
+                               if(wp_from.classname == "waypoint")
+                               {
+                                       found = true;
+                                       break;
+                               }
+                               wp_from = wp_from.chain;
+                       }
+
+                       if(!found)
+                       {
+                               LOG_INFO(strcat("NOTICE: Can not find waypoint at ", vtos(wp_from_pos), ". Path skipped\n"));
+                               continue;
+                       }
+               }
+
+               // Search "to" waypoint
+               wp_to = findradius(wp_to_pos, 5);
+               found = false;
+               while(wp_to)
+               {
+                       if(vdist(wp_to.origin - wp_to_pos, <, 5))
+                       if(wp_to.classname == "waypoint")
+                       {
+                               found = true;
+                               break;
+                       }
+                       wp_to = wp_to.chain;
+               }
+
+               if(!found)
+               {
+                       LOG_INFO(strcat("NOTICE: Can not find waypoint at ", vtos(wp_to_pos), ". Path skipped\n"));
+                       continue;
+               }
+
+               ++c;
+               waypoint_addlink(wp_from, wp_to);
+               wp_from.wphardwired = true;
+               wp_to.wphardwired = true;
+       }
+
+       fclose(file);
+
+       LOG_TRACE("loaded ", ftos(c), " waypoint links from maps/", mapname, ".waypoints.hardwired");
+}
+
+entity waypoint_get_link(entity w, float i)
+{
+       switch(i)
+       {
+               case  0:return w.wp00;
+               case  1:return w.wp01;
+               case  2:return w.wp02;
+               case  3:return w.wp03;
+               case  4:return w.wp04;
+               case  5:return w.wp05;
+               case  6:return w.wp06;
+               case  7:return w.wp07;
+               case  8:return w.wp08;
+               case  9:return w.wp09;
+               case 10:return w.wp10;
+               case 11:return w.wp11;
+               case 12:return w.wp12;
+               case 13:return w.wp13;
+               case 14:return w.wp14;
+               case 15:return w.wp15;
+               case 16:return w.wp16;
+               case 17:return w.wp17;
+               case 18:return w.wp18;
+               case 19:return w.wp19;
+               case 20:return w.wp20;
+               case 21:return w.wp21;
+               case 22:return w.wp22;
+               case 23:return w.wp23;
+               case 24:return w.wp24;
+               case 25:return w.wp25;
+               case 26:return w.wp26;
+               case 27:return w.wp27;
+               case 28:return w.wp28;
+               case 29:return w.wp29;
+               case 30:return w.wp30;
+               case 31:return w.wp31;
+               default:return NULL;
+       }
+}
+
+// Save all waypoint links to a file
+void waypoint_save_links()
+{
+       string filename = sprintf("maps/%s.waypoints.cache", mapname);
+       int file = fopen(filename, FILE_WRITE);
+       if (file < 0)
+       {
+               LOG_INFOF("waypoint link save to %s failed\n", filename);
+               return;
+       }
+
+       int c = 0;
+       IL_EACH(g_waypoints, true,
+       {
+               for(int j = 0; j < 32; ++j)
+               {
+                       entity link = waypoint_get_link(it, j);
+                       if(link)
+                       {
+                               string s = strcat(vtos(it.origin), "*", vtos(link.origin), "\n");
+                               fputs(file, s);
+                               ++c;
+                       }
+               }
+       });
+       fclose(file);
+       botframe_cachedwaypointlinks = true;
+
+       LOG_INFOF("saved %d waypoint links to maps/%s.waypoints.cache\n", c, mapname);
+}
+
+// save waypoints to gamedir/data/maps/mapname.waypoints
+void waypoint_saveall()
+{
+       string filename = sprintf("maps/%s.waypoints", mapname);
+       int file = fopen(filename, FILE_WRITE);
+       if (file < 0)
+       {
+               waypoint_save_links(); // save anyway?
+               botframe_loadedforcedlinks = false;
+
+               LOG_INFOF("waypoint links: save to %s failed\n", filename);
+               return;
+       }
+
+       int c = 0;
+       IL_EACH(g_waypoints, true,
+       {
+               if(it.wpflags & WAYPOINTFLAG_GENERATED)
+                       continue;
+
+               for(int j = 0; j < 32; ++j)
+               {
+                       string s;
+                       s = strcat(vtos(it.origin + it.mins), "\n");
+                       s = strcat(s, vtos(it.origin + it.maxs));
+                       s = strcat(s, "\n");
+                       s = strcat(s, ftos(it.wpflags));
+                       s = strcat(s, "\n");
+                       fputs(file, s);
+                       ++c;
+               }
+       });
+       fclose(file);
+       waypoint_save_links();
+       botframe_loadedforcedlinks = false;
+
+       LOG_INFOF("saved %d waypoints to maps/%s.waypoints\n", c, mapname);
+}
+
+// load waypoints from file
+float waypoint_loadall()
+{
+       string filename, s;
+       float file, cwp, cwb, fl;
+       vector m1, m2;
+       cwp = 0;
+       cwb = 0;
+       filename = strcat("maps/", mapname);
+       filename = strcat(filename, ".waypoints");
+       file = fopen(filename, FILE_READ);
+       if (file >= 0)
+       {
+               while ((s = fgets(file)))
+               {
+                       m1 = stov(s);
+                       s = fgets(file);
+                       if (!s)
+                               break;
+                       m2 = stov(s);
+                       s = fgets(file);
+                       if (!s)
+                               break;
+                       fl = stof(s);
+                       waypoint_spawn(m1, m2, fl);
+                       if (m1 == m2)
+                               cwp = cwp + 1;
+                       else
+                               cwb = cwb + 1;
+               }
+               fclose(file);
+               LOG_TRACE("loaded ", ftos(cwp), " waypoints and ", ftos(cwb), " wayboxes from maps/", mapname, ".waypoints");
+       }
+       else
+       {
+               LOG_TRACE("waypoint load from ", filename, " failed");
+       }
+       return cwp + cwb;
+}
+
+vector waypoint_fixorigin(vector position)
+{
+       tracebox(position + '0 0 1' * (1 - STAT(PL_MIN, NULL).z), STAT(PL_MIN, NULL), STAT(PL_MAX, NULL), position + '0 0 -512', MOVE_NOMONSTERS, NULL);
+       if(trace_fraction < 1)
+               position = trace_endpos;
+       //traceline(position, position + '0 0 -512', MOVE_NOMONSTERS, NULL);
+       //print("position is ", ftos(trace_endpos_z - position_z), " above solid\n");
+       return position;
+}
+
+void waypoint_spawnforitem_force(entity e, vector org)
+{
+       // Fix the waypoint altitude if necessary
+       org = waypoint_fixorigin(org);
+
+       // don't spawn an item spawnfunc_waypoint if it already exists
+       IL_EACH(g_waypoints, true,
+       {
+               if(it.wpisbox)
+               {
+                       if(boxesoverlap(org, org, it.absmin, it.absmax))
+                       {
+                               e.nearestwaypoint = it;
+                               return;
+                       }
+               }
+               else
+               {
+                       if(vdist(it.origin - org, <, 16))
+                       {
+                               e.nearestwaypoint = it;
+                               return;
+                       }
+               }
+       });
+
+       e.nearestwaypoint = waypoint_spawn(org, org, WAYPOINTFLAG_GENERATED | WAYPOINTFLAG_ITEM);
+}
+
+void waypoint_spawnforitem(entity e)
+{
+       if(!bot_waypoints_for_items)
+               return;
+
+       waypoint_spawnforitem_force(e, e.origin);
+}
+
+void waypoint_spawnforteleporter_boxes(entity e, vector org1, vector org2, vector destination1, vector destination2, float timetaken)
+{
+       entity w;
+       entity dw;
+       w = waypoint_spawn(org1, org2, WAYPOINTFLAG_GENERATED | WAYPOINTFLAG_TELEPORT | WAYPOINTFLAG_NORELINK);
+       dw = waypoint_spawn(destination1, destination2, WAYPOINTFLAG_GENERATED);
+       // one way link to the destination
+       w.wp00 = dw;
+       w.wp00mincost = timetaken; // this is just for jump pads
+       // the teleporter's nearest spawnfunc_waypoint is this one
+       // (teleporters are not goals, so this is probably useless)
+       e.nearestwaypoint = w;
+       e.nearestwaypointtimeout = time + 1000000000;
+}
+
+void waypoint_spawnforteleporter_v(entity e, vector org, vector destination, float timetaken)
+{
+       org = waypoint_fixorigin(org);
+       destination = waypoint_fixorigin(destination);
+       waypoint_spawnforteleporter_boxes(e, org, org, destination, destination, timetaken);
+}
+
+void waypoint_spawnforteleporter(entity e, vector destination, float timetaken)
+{
+       destination = waypoint_fixorigin(destination);
+       waypoint_spawnforteleporter_boxes(e, e.absmin, e.absmax, destination, destination, timetaken);
+}
+
+entity waypoint_spawnpersonal(entity this, vector position)
+{
+       entity w;
+
+       // drop the waypoint to a proper location:
+       //   first move it up by a player height
+       //   then move it down to hit the floor with player bbox size
+       position = waypoint_fixorigin(position);
+
+       w = waypoint_spawn(position, position, WAYPOINTFLAG_GENERATED | WAYPOINTFLAG_PERSONAL);
+       w.nearestwaypoint = NULL;
+       w.nearestwaypointtimeout = 0;
+       w.owner = this;
+
+       waypoint_schedulerelink(w);
+
+       return w;
+}
+
+void botframe_showwaypointlinks()
+{
+       if (time < botframe_waypointeditorlightningtime)
+               return;
+       botframe_waypointeditorlightningtime = time + 0.5;
+       FOREACH_CLIENT(IS_PLAYER(it) && !it.isbot,
+       {
+               if(IS_ONGROUND(it) || it.waterlevel > WATERLEVEL_NONE)
+               {
+                       //navigation_testtracewalk = true;
+                       entity head = navigation_findnearestwaypoint(it, false);
+               //      print("currently selected WP is ", etos(head), "\n");
+                       //navigation_testtracewalk = false;
+                       if (head)
+                       {
+                               entity w;
+                               w = head     ;if (w) te_lightning2(NULL, w.origin, it.origin);
+                               w = head.wp00;if (w) te_lightning2(NULL, w.origin, head.origin);
+                               w = head.wp01;if (w) te_lightning2(NULL, w.origin, head.origin);
+                               w = head.wp02;if (w) te_lightning2(NULL, w.origin, head.origin);
+                               w = head.wp03;if (w) te_lightning2(NULL, w.origin, head.origin);
+                               w = head.wp04;if (w) te_lightning2(NULL, w.origin, head.origin);
+                               w = head.wp05;if (w) te_lightning2(NULL, w.origin, head.origin);
+                               w = head.wp06;if (w) te_lightning2(NULL, w.origin, head.origin);
+                               w = head.wp07;if (w) te_lightning2(NULL, w.origin, head.origin);
+                               w = head.wp08;if (w) te_lightning2(NULL, w.origin, head.origin);
+                               w = head.wp09;if (w) te_lightning2(NULL, w.origin, head.origin);
+                               w = head.wp10;if (w) te_lightning2(NULL, w.origin, head.origin);
+                               w = head.wp11;if (w) te_lightning2(NULL, w.origin, head.origin);
+                               w = head.wp12;if (w) te_lightning2(NULL, w.origin, head.origin);
+                               w = head.wp13;if (w) te_lightning2(NULL, w.origin, head.origin);
+                               w = head.wp14;if (w) te_lightning2(NULL, w.origin, head.origin);
+                               w = head.wp15;if (w) te_lightning2(NULL, w.origin, head.origin);
+                               w = head.wp16;if (w) te_lightning2(NULL, w.origin, head.origin);
+                               w = head.wp17;if (w) te_lightning2(NULL, w.origin, head.origin);
+                               w = head.wp18;if (w) te_lightning2(NULL, w.origin, head.origin);
+                               w = head.wp19;if (w) te_lightning2(NULL, w.origin, head.origin);
+                               w = head.wp20;if (w) te_lightning2(NULL, w.origin, head.origin);
+                               w = head.wp21;if (w) te_lightning2(NULL, w.origin, head.origin);
+                               w = head.wp22;if (w) te_lightning2(NULL, w.origin, head.origin);
+                               w = head.wp23;if (w) te_lightning2(NULL, w.origin, head.origin);
+                               w = head.wp24;if (w) te_lightning2(NULL, w.origin, head.origin);
+                               w = head.wp25;if (w) te_lightning2(NULL, w.origin, head.origin);
+                               w = head.wp26;if (w) te_lightning2(NULL, w.origin, head.origin);
+                               w = head.wp27;if (w) te_lightning2(NULL, w.origin, head.origin);
+                               w = head.wp28;if (w) te_lightning2(NULL, w.origin, head.origin);
+                               w = head.wp29;if (w) te_lightning2(NULL, w.origin, head.origin);
+                               w = head.wp30;if (w) te_lightning2(NULL, w.origin, head.origin);
+                               w = head.wp31;if (w) te_lightning2(NULL, w.origin, head.origin);
+                       }
+               }
+       });
+}
+
+float botframe_autowaypoints_fixdown(vector v)
+{
+       tracebox(v, STAT(PL_MIN, NULL), STAT(PL_MAX, NULL), v + '0 0 -64', MOVE_NOMONSTERS, NULL);
+       if(trace_fraction >= 1)
+               return 0;
+       return 1;
+}
+
+float botframe_autowaypoints_createwp(vector v, entity p, .entity fld, float f)
+{
+       IL_EACH(g_waypoints, boxesoverlap(v - '32 32 32', v + '32 32 32', it.absmin, it.absmax),
+       {
+               // if a matching spawnfunc_waypoint already exists, don't add a duplicate
+               return 0;
+       });
+
+       waypoint_schedulerelink(p.(fld) = waypoint_spawn(v, v, f));
+       return 1;
+}
+
+// return value:
+//    1 = WP created
+//    0 = no action needed
+//   -1 = temp fail, try from world too
+//   -2 = permanent fail, do not retry
+float botframe_autowaypoints_fix_from(entity p, float walkfromwp, entity wp, .entity fld)
+{
+       // make it possible to go from p to wp, if we can
+       // if wp is NULL, nearest is chosen
+
+       entity w;
+       vector porg;
+       float t, tmin, tmax;
+       vector o;
+       vector save;
+
+       if(!botframe_autowaypoints_fixdown(p.origin))
+               return -2;
+       porg = trace_endpos;
+
+       if(wp)
+       {
+               // if any WP w fulfills wp -> w -> porg and w is closer than wp, then switch from wp to w
+
+               // if wp -> porg, then OK
+               float maxdist;
+               if(navigation_waypoint_will_link(wp.origin, porg, p, walkfromwp, 1050))
+               {
+                       // we may find a better one
+                       maxdist = vlen(wp.origin - porg);
+               }
+               else
+               {
+                       // accept any "good"
+                       maxdist = 2100;
+               }
+
+               float bestdist = maxdist;
+               IL_EACH(g_waypoints, it != wp && !(it.wpflags & WAYPOINTFLAG_NORELINK),
+               {
+                       float d = vlen(wp.origin - it.origin) + vlen(it.origin - porg);
+                       if(d < bestdist)
+                       if(navigation_waypoint_will_link(wp.origin, it.origin, p, walkfromwp, 1050))
+                       if(navigation_waypoint_will_link(it.origin, porg, p, walkfromwp, 1050))
+                       {
+                               bestdist = d;
+                               p.(fld) = it;
+                       }
+               });
+               if(bestdist < maxdist)
+               {
+                       LOG_INFO("update chain to new nearest WP ", etos(p.(fld)), "\n");
+                       return 0;
+               }
+
+               if(bestdist < 2100)
+               {
+                       // we know maxdist < 2100
+                       // so wp -> porg is still valid
+                       // all is good
+                       p.(fld) = wp;
+                       return 0;
+               }
+
+               // otherwise, no existing WP can fix our issues
+       }
+       else
+       {
+               save = p.origin;
+               setorigin(p, porg);
+               w = navigation_findnearestwaypoint(p, walkfromwp);
+               setorigin(p, save);
+               if(w)
+               {
+                       p.(fld) = w;
+                       return 0;
+               }
+       }
+
+       tmin = 0;
+       tmax = 1;
+       for (;;)
+       {
+               if(tmax - tmin < 0.001)
+               {
+                       // did not get a good candidate
+                       return -1;
+               }
+
+               t = (tmin + tmax) * 0.5;
+               o = antilag_takebackorigin(p, CS(p), time - t);
+               if(!botframe_autowaypoints_fixdown(o))
+                       return -2;
+               o = trace_endpos;
+
+               if(wp)
+               {
+                       if(!navigation_waypoint_will_link(wp.origin, o, p, walkfromwp, 1050))
+                       {
+                               // we cannot walk from wp.origin to o
+                               // get closer to tmax
+                               tmin = t;
+                               continue;
+                       }
+               }
+               else
+               {
+                       save = p.origin;
+                       setorigin(p, o);
+                       w = navigation_findnearestwaypoint(p, walkfromwp);
+                       setorigin(p, save);
+                       if(!w)
+                       {
+                               // we cannot walk from any WP to o
+                               // get closer to tmax
+                               tmin = t;
+                               continue;
+                       }
+               }
+
+               // if we get here, o is valid regarding waypoints
+               // check if o is connected right to the player
+               // we break if it succeeds, as that means o is a good waypoint location
+               if(navigation_waypoint_will_link(o, porg, p, walkfromwp, 1050))
+                       break;
+
+               // o is no good, we need to get closer to the player
+               tmax = t;
+       }
+
+       LOG_INFO("spawning a waypoint for connecting to ", etos(wp), "\n");
+       botframe_autowaypoints_createwp(o, p, fld, 0);
+       return 1;
+}
+
+// automatically create missing waypoints
+.entity botframe_autowaypoints_lastwp0, botframe_autowaypoints_lastwp1;
+void botframe_autowaypoints_fix(entity p, float walkfromwp, .entity fld)
+{
+       float r = botframe_autowaypoints_fix_from(p, walkfromwp, p.(fld), fld);
+       if(r != -1)
+               return;
+       r = botframe_autowaypoints_fix_from(p, walkfromwp, NULL, fld);
+       if(r != -1)
+               return;
+
+       LOG_INFO("emergency: got no good nearby WP to build a link from, starting a new chain\n");
+       if(!botframe_autowaypoints_fixdown(p.origin))
+               return; // shouldn't happen, caught above
+       botframe_autowaypoints_createwp(trace_endpos, p, fld, WAYPOINTFLAG_PROTECTED);
+}
+
+void botframe_deleteuselesswaypoints()
+{
+       FOREACH_ENTITY_FLOAT(bot_pickup, true,
+       {
+               // NOTE: this protects waypoints if they're the ONLY nearest
+               // waypoint. That's the intention.
+               navigation_findnearestwaypoint(it, false);  // Walk TO item.
+               navigation_findnearestwaypoint(it, true);  // Walk FROM item.
+       });
+       IL_EACH(g_waypoints, true,
+       {
+               it.wpflags |= WAYPOINTFLAG_DEAD_END;
+               it.wpflags &= ~WAYPOINTFLAG_USEFUL;
+               // WP is useful if:
+               if (it.wpflags & WAYPOINTFLAG_ITEM)
+                       it.wpflags |= WAYPOINTFLAG_USEFUL;
+               if (it.wpflags & WAYPOINTFLAG_TELEPORT)
+                       it.wpflags |= WAYPOINTFLAG_USEFUL;
+               if (it.wpflags & WAYPOINTFLAG_PROTECTED)
+                       it.wpflags |= WAYPOINTFLAG_USEFUL;
+               // b) WP is closest WP for an item/spawnpoint/other entity
+               //    This has been done above by protecting these WPs.
+       });
+       // c) There are w1, w, w2 so that w1 -> w, w -> w2 and not w1 -> w2.
+       IL_EACH(g_waypoints, !(it.wpflags & WAYPOINTFLAG_PERSONAL),
+       {
+               for (int m = 0; m < 32; ++m)
+               {
+                       entity w = waypoint_get_link(it, m);
+                       if (!w)
+                               break;
+                       if (w.wpflags & WAYPOINTFLAG_PERSONAL)
+                               continue;
+                       if (w.wpflags & WAYPOINTFLAG_USEFUL)
+                               continue;
+                       for (int j = 0; j < 32; ++j)
+                       {
+                               entity w2 = waypoint_get_link(w, j);
+                               if (!w2)
+                                       break;
+                               if (it == w2)
+                                       continue;
+                               if (w2.wpflags & WAYPOINTFLAG_PERSONAL)
+                                       continue;
+                               // If we got here, it != w2 exist with it -> w
+                               // and w -> w2. That means the waypoint is not
+                               // a dead end.
+                               w.wpflags &= ~WAYPOINTFLAG_DEAD_END;
+                               for (int k = 0; k < 32; ++k)
+                               {
+                                       if (waypoint_get_link(it, k) == w2)
+                                               continue;
+                                       // IF WE GET HERE, w is proven useful
+                                       // to get from it to w2!
+                                       w.wpflags |= WAYPOINTFLAG_USEFUL;
+                                       goto next;
+                               }
+                       }
+LABEL(next)
+               }
+       });
+       // d) The waypoint is a dead end. Dead end waypoints must be kept as
+       //     they are needed to complete routes while autowaypointing.
+
+       IL_EACH(g_waypoints, !(it.wpflags & (WAYPOINTFLAG_USEFUL | WAYPOINTFLAG_DEAD_END)),
+       {
+               LOG_INFOF("Removed a waypoint at %v. Try again for more!\n", it.origin);
+               te_explosion(it.origin);
+               waypoint_remove(it);
+               break;
+       });
+
+       IL_EACH(g_waypoints, true,
+       {
+               it.wpflags &= ~(WAYPOINTFLAG_USEFUL | WAYPOINTFLAG_DEAD_END); // temp flag
+       });
+}
+
+void botframe_autowaypoints()
+{
+       FOREACH_CLIENT(IS_PLAYER(it) && IS_REAL_CLIENT(it) && !IS_DEAD(it), LAMBDA(
+               // going back is broken, so only fix waypoints to walk TO the player
+               //botframe_autowaypoints_fix(p, false, botframe_autowaypoints_lastwp0);
+               botframe_autowaypoints_fix(it, true, botframe_autowaypoints_lastwp1);
+               //te_explosion(p.botframe_autowaypoints_lastwp0.origin);
+       ));
+
+       if (autocvar_g_waypointeditor_auto >= 2) {
+               botframe_deleteuselesswaypoints();
+       }
+}
+
diff --git a/qcsrc/server/bot/default/waypoints.qh b/qcsrc/server/bot/default/waypoints.qh
new file mode 100644 (file)
index 0000000..38d57a0
--- /dev/null
@@ -0,0 +1,58 @@
+#pragma once
+/*
+ * Globals and Fields
+ */
+
+// fields you can query using prvm_global server to get some statistics about waypoint linking culling
+float relink_total, relink_walkculled, relink_pvsculled, relink_lengthculled;
+
+float botframe_waypointeditorlightningtime;
+float botframe_loadedforcedlinks;
+float botframe_cachedwaypointlinks;
+
+.entity wp00, wp01, wp02, wp03, wp04, wp05, wp06, wp07, wp08, wp09, wp10, wp11, wp12, wp13, wp14, wp15;
+.entity wp16, wp17, wp18, wp19, wp20, wp21, wp22, wp23, wp24, wp25, wp26, wp27, wp28, wp29, wp30, wp31;
+
+// itemscore = (howmuchmoreIwant / howmuchIcanwant) / itemdistance
+.float wp00mincost, wp01mincost, wp02mincost, wp03mincost, wp04mincost, wp05mincost, wp06mincost, wp07mincost;
+.float wp08mincost, wp09mincost, wp10mincost, wp11mincost, wp12mincost, wp13mincost, wp14mincost, wp15mincost;
+.float wp16mincost, wp17mincost, wp18mincost, wp19mincost, wp20mincost, wp21mincost, wp22mincost, wp23mincost;
+.float wp24mincost, wp25mincost, wp26mincost, wp27mincost, wp28mincost, wp29mincost, wp30mincost, wp31mincost;
+
+.float wpfire, wpcost, wpconsidered, wpisbox, wplinked, wphardwired;
+.int wpflags;
+
+.vector wpnearestpoint;
+
+/*
+ * Functions
+ */
+
+spawnfunc(waypoint);
+void waypoint_addlink(entity from, entity to);
+void waypoint_think(entity this);
+void waypoint_clearlinks(entity wp);
+void waypoint_schedulerelink(entity wp);
+
+void waypoint_remove(entity e);
+void waypoint_removeall();
+void waypoint_schedulerelinkall();
+void waypoint_load_links_hardwired();
+void waypoint_save_links();
+void waypoint_saveall();
+
+void waypoint_spawnforitem_force(entity e, vector org);
+void waypoint_spawnforitem(entity e);
+void waypoint_spawnforteleporter(entity e, vector destination, float timetaken);
+void waypoint_spawnforteleporter_v(entity e, vector org, vector destination, float timetaken);
+void botframe_showwaypointlinks();
+
+float waypoint_loadall();
+float waypoint_load_links();
+
+entity waypoint_spawn(vector m1, vector m2, float f);
+entity waypoint_spawnpersonal(entity this, vector position);
+
+vector waypoint_fixorigin(vector position);
+
+void botframe_autowaypoints();
diff --git a/qcsrc/server/bot/havocbot/_mod.inc b/qcsrc/server/bot/havocbot/_mod.inc
deleted file mode 100644 (file)
index a6270bc..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-// generated file; do not modify
-#include <server/bot/havocbot/havocbot.qc>
-#include <server/bot/havocbot/roles.qc>
diff --git a/qcsrc/server/bot/havocbot/_mod.qh b/qcsrc/server/bot/havocbot/_mod.qh
deleted file mode 100644 (file)
index 4b62d1b..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-// generated file; do not modify
-#include <server/bot/havocbot/havocbot.qh>
-#include <server/bot/havocbot/roles.qh>
diff --git a/qcsrc/server/bot/havocbot/havocbot.qc b/qcsrc/server/bot/havocbot/havocbot.qc
deleted file mode 100644 (file)
index b22ded2..0000000
+++ /dev/null
@@ -1,1296 +0,0 @@
-#include "havocbot.qh"
-
-#include "../aim.qh"
-#include "../bot.qh"
-#include "../navigation.qh"
-#include "../scripting.qh"
-#include "../waypoints.qh"
-
-#include <common/constants.qh>
-#include <common/physics/player.qh>
-#include <common/state.qh>
-#include <common/items/all.qh>
-
-#include <common/triggers/trigger/jumppads.qh>
-
-#include <lib/warpzone/common.qh>
-
-.float speed;
-
-void havocbot_ai(entity this)
-{
-       if(this.draggedby)
-               return;
-
-       if(bot_execute_commands(this))
-               return;
-
-       if (bot_strategytoken == this)
-       if (!bot_strategytoken_taken)
-       {
-               if(this.havocbot_blockhead)
-               {
-                       this.havocbot_blockhead = false;
-               }
-               else
-               {
-                       if (!this.jumppadcount)
-                               this.havocbot_role(this); // little too far down the rabbit hole
-               }
-
-               // TODO: tracewalk() should take care of this job (better path finding under water)
-               // if we don't have a goal and we're under water look for a waypoint near the "shore" and push it
-               if(IS_DEAD(this))
-               if(!this.goalcurrent)
-               if(this.waterlevel == WATERLEVEL_SWIMMING || (this.aistatus & AI_STATUS_OUT_WATER))
-               {
-                       // Look for the closest waypoint out of water
-                       entity newgoal = NULL;
-                       IL_EACH(g_waypoints, vdist(it.origin - this.origin, <=, 10000),
-                       {
-                               if(it.origin.z < this.origin.z)
-                                       continue;
-
-                               if(it.origin.z - this.origin.z - this.view_ofs.z > 100)
-                                       continue;
-
-                               if (pointcontents(it.origin + it.maxs + '0 0 1') != CONTENT_EMPTY)
-                                       continue;
-
-                               traceline(this.origin + this.view_ofs, ((it.absmin + it.absmax) * 0.5), true, this);
-
-                               if(trace_fraction < 1)
-                                       continue;
-
-                               if(!newgoal || vlen2(it.origin - this.origin) < vlen2(newgoal.origin - this.origin))
-                                       newgoal = it;
-                       });
-
-                       if(newgoal)
-                       {
-                       //      te_wizspike(newgoal.origin);
-                               navigation_pushroute(this, newgoal);
-                       }
-               }
-
-               // token has been used this frame
-               bot_strategytoken_taken = true;
-       }
-
-       if(IS_DEAD(this))
-               return;
-
-       havocbot_chooseenemy(this);
-       if (this.bot_chooseweapontime < time )
-       {
-               this.bot_chooseweapontime = time + autocvar_bot_ai_chooseweaponinterval;
-               havocbot_chooseweapon(this);
-       }
-       havocbot_aim(this);
-       lag_update(this);
-       if (this.bot_aimtarg)
-       {
-               this.aistatus |= AI_STATUS_ATTACKING;
-               this.aistatus &= ~AI_STATUS_ROAMING;
-
-               if(this.weapons)
-               {
-                       Weapon w = PS(this).m_weapon;
-                       w.wr_aim(w, this);
-                       if (autocvar_bot_nofire || IS_INDEPENDENT_PLAYER(this))
-                       {
-                               PHYS_INPUT_BUTTON_ATCK(this) = false;
-                               PHYS_INPUT_BUTTON_ATCK2(this) = false;
-                       }
-                       else
-                       {
-                               if(PHYS_INPUT_BUTTON_ATCK(this) || PHYS_INPUT_BUTTON_ATCK2(this))
-                                       this.lastfiredweapon = PS(this).m_weapon.m_id;
-                       }
-               }
-               else
-               {
-                       if(IS_PLAYER(this.bot_aimtarg))
-                               bot_aimdir(this, this.bot_aimtarg.origin + this.bot_aimtarg.view_ofs - this.origin - this.view_ofs , -1);
-               }
-       }
-       else if (this.goalcurrent)
-       {
-               this.aistatus |= AI_STATUS_ROAMING;
-               this.aistatus &= ~AI_STATUS_ATTACKING;
-
-               vector now,v,next;//,heading;
-               float aimdistance,skillblend,distanceblend,blend;
-               next = now = ( (this.goalcurrent.absmin + this.goalcurrent.absmax) * 0.5) - (this.origin + this.view_ofs);
-               aimdistance = vlen(now);
-               //heading = this.velocity;
-               //dprint(this.goalstack01.classname,etos(this.goalstack01),"\n");
-               if(
-                       this.goalstack01 != this && this.goalstack01 != NULL && ((this.aistatus & AI_STATUS_RUNNING) == 0) &&
-                       !(this.goalcurrent.wpflags & WAYPOINTFLAG_TELEPORT)
-               )
-                       next = ((this.goalstack01.absmin + this.goalstack01.absmax) * 0.5) - (this.origin + this.view_ofs);
-
-               skillblend=bound(0,(skill+this.bot_moveskill-2.5)*0.5,1); //lower skill player can't preturn
-               distanceblend=bound(0,aimdistance/autocvar_bot_ai_keyboard_distance,1);
-               blend = skillblend * (1-distanceblend);
-               //v = (now * (distanceblend) + next * (1-distanceblend)) * (skillblend) + now * (1-skillblend);
-               //v = now * (distanceblend) * (skillblend) + next * (1-distanceblend) * (skillblend) + now * (1-skillblend);
-               //v = now * ((1-skillblend) + (distanceblend) * (skillblend)) + next * (1-distanceblend) * (skillblend);
-               v = now + blend * (next - now);
-               //dprint(etos(this), " ");
-               //dprint(vtos(now), ":", vtos(next), "=", vtos(v), " (blend ", ftos(blend), ")\n");
-               //v = now * (distanceblend) + next * (1-distanceblend);
-               if (this.waterlevel < WATERLEVEL_SWIMMING)
-                       v.z = 0;
-               //dprint("walk at:", vtos(v), "\n");
-               //te_lightning2(NULL, this.origin, this.goalcurrent.origin);
-               bot_aimdir(this, v, -1);
-       }
-       havocbot_movetogoal(this);
-
-       // if the bot is not attacking, consider reloading weapons
-       if (!(this.aistatus & AI_STATUS_ATTACKING))
-       {
-               // 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(this.clip_load < this.clip_size)
-                       this.impulse = 20; // "press" the reload button, not sure if this is done right
-
-               // if we're not reloading a weapon, switch to any weapon in our invnetory that's not fully loaded to reload it next
-               // the code above executes next frame, starting the reloading then
-               if(skill >= 5) // bots can only look for unloaded weapons past this skill
-               if(this.clip_load >= 0) // only if we're not reloading a weapon already
-               {
-                       FOREACH(Weapons, it != WEP_Null, LAMBDA(
-                               if((this.weapons & (it.m_wepset)) && (it.spawnflags & WEP_FLAG_RELOADABLE) && (this.weapon_load[it.m_id] < it.reloading_ammo))
-                                       PS(this).m_switchweapon = it;
-                       ));
-               }
-       }
-}
-
-void havocbot_keyboard_movement(entity this, vector destorg)
-{
-       vector keyboard;
-       float blend, maxspeed;
-       float sk;
-
-       sk = skill + this.bot_moveskill;
-
-       maxspeed = autocvar_sv_maxspeed;
-
-       if (time < this.havocbot_keyboardtime)
-               return;
-
-       this.havocbot_keyboardtime =
-               max(
-                       this.havocbot_keyboardtime
-                               + 0.05/max(1, sk+this.havocbot_keyboardskill)
-                               + random()*0.025/max(0.00025, skill+this.havocbot_keyboardskill)
-               , time);
-       keyboard = this.movement * (1.0 / maxspeed);
-
-       float trigger, trigger1;
-       blend = bound(0,sk*0.1,1);
-       trigger = autocvar_bot_ai_keyboard_threshold;
-       trigger1 = 0 - trigger;
-
-       // categorize forward movement
-       // at skill < 1.5 only forward
-       // at skill < 2.5 only individual directions
-       // at skill < 4.5 only individual directions, and forward diagonals
-       // at skill >= 4.5, all cases allowed
-       if (keyboard.x > trigger)
-       {
-               keyboard.x = 1;
-               if (sk < 2.5)
-                       keyboard.y = 0;
-       }
-       else if (keyboard.x < trigger1 && sk > 1.5)
-       {
-               keyboard.x = -1;
-               if (sk < 4.5)
-                       keyboard.y = 0;
-       }
-       else
-       {
-               keyboard.x = 0;
-               if (sk < 1.5)
-                       keyboard.y = 0;
-       }
-       if (sk < 4.5)
-               keyboard.z = 0;
-
-       if (keyboard.y > trigger)
-               keyboard.y = 1;
-       else if (keyboard.y < trigger1)
-               keyboard.y = -1;
-       else
-               keyboard.y = 0;
-
-       if (keyboard.z > trigger)
-               keyboard.z = 1;
-       else if (keyboard.z < trigger1)
-               keyboard.z = -1;
-       else
-               keyboard.z = 0;
-
-       this.havocbot_keyboard = keyboard * maxspeed;
-       if (this.havocbot_ducktime>time) PHYS_INPUT_BUTTON_CROUCH(this) = true;
-
-       keyboard = this.havocbot_keyboard;
-       blend = bound(0,vlen(destorg-this.origin)/autocvar_bot_ai_keyboard_distance,1); // When getting close move with 360 degree
-       //dprint("movement ", vtos(this.movement), " keyboard ", vtos(keyboard), " blend ", ftos(blend), "\n");
-       this.movement = this.movement + (keyboard - this.movement) * blend;
-}
-
-void havocbot_bunnyhop(entity this, vector dir)
-{
-       float bunnyhopdistance;
-       vector deviation;
-       float maxspeed;
-       vector gco, gno;
-
-       // Don't jump when attacking
-       if(this.aistatus & AI_STATUS_ATTACKING)
-               return;
-
-       if(IS_PLAYER(this.goalcurrent))
-               return;
-
-       maxspeed = autocvar_sv_maxspeed;
-
-       if(this.aistatus & AI_STATUS_DANGER_AHEAD)
-       {
-               this.aistatus &= ~AI_STATUS_RUNNING;
-               PHYS_INPUT_BUTTON_JUMP(this) = false;
-               this.bot_canruntogoal = 0;
-               this.bot_timelastseengoal = 0;
-               return;
-       }
-
-       if(this.waterlevel > WATERLEVEL_WETFEET)
-       {
-               this.aistatus &= ~AI_STATUS_RUNNING;
-               return;
-       }
-
-       if(this.bot_lastseengoal != this.goalcurrent && !(this.aistatus & AI_STATUS_RUNNING))
-       {
-               this.bot_canruntogoal = 0;
-               this.bot_timelastseengoal = 0;
-       }
-
-       gco = (this.goalcurrent.absmin + this.goalcurrent.absmax) * 0.5;
-       bunnyhopdistance = vlen(this.origin - gco);
-
-       // Run only to visible goals
-       if(IS_ONGROUND(this))
-       if(this.speed==maxspeed)
-       if(checkpvs(this.origin + this.view_ofs, this.goalcurrent))
-       {
-                       this.bot_lastseengoal = this.goalcurrent;
-
-                       // seen it before
-                       if(this.bot_timelastseengoal)
-                       {
-                               // for a period of time
-                               if(time - this.bot_timelastseengoal > autocvar_bot_ai_bunnyhop_firstjumpdelay)
-                               {
-                                       float checkdistance;
-                                       checkdistance = true;
-
-                                       // don't run if it is too close
-                                       if(this.bot_canruntogoal==0)
-                                       {
-                                               if(bunnyhopdistance > autocvar_bot_ai_bunnyhop_startdistance)
-                                                       this.bot_canruntogoal = 1;
-                                               else
-                                                       this.bot_canruntogoal = -1;
-                                       }
-
-                                       if(this.bot_canruntogoal != 1)
-                                               return;
-
-                                       if(this.aistatus & AI_STATUS_ROAMING)
-                                       if(this.goalcurrent.classname=="waypoint")
-                                       if (!(this.goalcurrent.wpflags & WAYPOINTFLAG_PERSONAL))
-                                       if(fabs(gco.z - this.origin.z) < this.maxs.z - this.mins.z)
-                                       if(this.goalstack01!=NULL)
-                                       {
-                                               gno = (this.goalstack01.absmin + this.goalstack01.absmax) * 0.5;
-                                               deviation = vectoangles(gno - this.origin) - vectoangles(gco - this.origin);
-                                               while (deviation.y < -180) deviation.y = deviation.y + 360;
-                                               while (deviation.y > 180) deviation.y = deviation.y - 360;
-
-                                               if(fabs(deviation.y) < 20)
-                                               if(bunnyhopdistance < vlen(this.origin - gno))
-                                               if(fabs(gno.z - gco.z) < this.maxs.z - this.mins.z)
-                                               {
-                                                       if(vdist(gco - gno, >, autocvar_bot_ai_bunnyhop_startdistance))
-                                                       if(checkpvs(this.origin + this.view_ofs, this.goalstack01))
-                                                       {
-                                                               checkdistance = false;
-                                                       }
-                                               }
-                                       }
-
-                                       if(checkdistance)
-                                       {
-                                               this.aistatus &= ~AI_STATUS_RUNNING;
-                                               if(bunnyhopdistance > autocvar_bot_ai_bunnyhop_stopdistance)
-                                                       PHYS_INPUT_BUTTON_JUMP(this) = true;
-                                       }
-                                       else
-                                       {
-                                               this.aistatus |= AI_STATUS_RUNNING;
-                                               PHYS_INPUT_BUTTON_JUMP(this) = true;
-                                       }
-                               }
-                       }
-                       else
-                       {
-                               this.bot_timelastseengoal = time;
-                       }
-       }
-       else
-       {
-               this.bot_timelastseengoal = 0;
-       }
-
-#if 0
-       // Release jump button
-       if(!cvar("sv_pogostick"))
-       if((IS_ONGROUND(this)) == 0)
-       {
-               if(this.velocity.z < 0 || vlen(this.velocity)<maxspeed)
-                       PHYS_INPUT_BUTTON_JUMP(this) = false;
-
-               // Strafe
-               if(this.aistatus & AI_STATUS_RUNNING)
-               if(vlen(this.velocity)>maxspeed)
-               {
-                       deviation = vectoangles(dir) - vectoangles(this.velocity);
-                       while (deviation.y < -180) deviation.y = deviation.y + 360;
-                       while (deviation.y > 180) deviation.y = deviation.y - 360;
-
-                       if(fabs(deviation.y)>10)
-                               this.movement_x = 0;
-
-                       if(deviation.y>10)
-                               this.movement_y = maxspeed * -1;
-                       else if(deviation.y<10)
-                               this.movement_y = maxspeed;
-
-               }
-       }
-#endif
-}
-
-void havocbot_movetogoal(entity this)
-{
-       vector destorg;
-       vector diff;
-       vector dir;
-       vector flatdir;
-       vector m1;
-       vector m2;
-       vector evadeobstacle;
-       vector evadelava;
-       float s;
-       float maxspeed;
-       vector gco;
-       //float dist;
-       vector dodge;
-       //if (this.goalentity)
-       //      te_lightning2(this, this.origin, (this.goalentity.absmin + this.goalentity.absmax) * 0.5);
-       this.movement = '0 0 0';
-       maxspeed = autocvar_sv_maxspeed;
-
-       // Jetpack navigation
-       if(this.goalcurrent)
-       if(this.navigation_jetpack_goal)
-       if(this.goalcurrent==this.navigation_jetpack_goal)
-       if(this.ammo_fuel)
-       {
-               if(autocvar_bot_debug_goalstack)
-               {
-                       debuggoalstack(this);
-                       te_wizspike(this.navigation_jetpack_point);
-               }
-
-               // Take off
-               if (!(this.aistatus & AI_STATUS_JETPACK_FLYING))
-               {
-                       // Brake almost completely so it can get a good direction
-                       if(vdist(this.velocity, >, 10))
-                               return;
-                       this.aistatus |= AI_STATUS_JETPACK_FLYING;
-               }
-
-               makevectors(this.v_angle.y * '0 1 0');
-               dir = normalize(this.navigation_jetpack_point - this.origin);
-
-               // Landing
-               if(this.aistatus & AI_STATUS_JETPACK_LANDING)
-               {
-                       // Calculate brake distance in xy
-                       float db, v, d;
-                       vector dxy;
-
-                       dxy = this.origin - ( ( this.goalcurrent.absmin + this.goalcurrent.absmax ) * 0.5 ); dxy.z = 0;
-                       d = vlen(dxy);
-                       v = vlen(this.velocity -  this.velocity.z * '0 0 1');
-                       db = (pow(v,2) / (autocvar_g_jetpack_acceleration_side * 2)) + 100;
-               //      dprint("distance ", ftos(ceil(d)), " velocity ", ftos(ceil(v)), " brake at ", ftos(ceil(db)), "\n");
-                       if(d < db || d < 500)
-                       {
-                               // Brake
-                               if(fabs(this.velocity.x)>maxspeed*0.3)
-                               {
-                                       this.movement_x = dir * v_forward * -maxspeed;
-                                       return;
-                               }
-                               // Switch to normal mode
-                               this.navigation_jetpack_goal = NULL;
-                               this.aistatus &= ~AI_STATUS_JETPACK_LANDING;
-                               this.aistatus &= ~AI_STATUS_JETPACK_FLYING;
-                               return;
-                       }
-               }
-               else if(checkpvs(this.origin,this.goalcurrent))
-               {
-                       // If I can see the goal switch to landing code
-                       this.aistatus &= ~AI_STATUS_JETPACK_FLYING;
-                       this.aistatus |= AI_STATUS_JETPACK_LANDING;
-                       return;
-               }
-
-               // Flying
-               PHYS_INPUT_BUTTON_HOOK(this) = true;
-               if(this.navigation_jetpack_point.z - STAT(PL_MAX, NULL).z + STAT(PL_MIN, NULL).z < this.origin.z)
-               {
-                       this.movement_x = dir * v_forward * maxspeed;
-                       this.movement_y = dir * v_right * maxspeed;
-               }
-               return;
-       }
-
-       // Handling of jump pads
-       if(this.jumppadcount)
-       {
-               // If got stuck on the jump pad try to reach the farthest visible waypoint
-               if(this.aistatus & AI_STATUS_OUT_JUMPPAD)
-               {
-                       if(fabs(this.velocity.z)<50)
-                       {
-                               entity newgoal = NULL;
-                               IL_EACH(g_waypoints, vdist(it.origin - this.origin, <=, 1000),
-                               {
-                                       traceline(this.origin + this.view_ofs, ((it.absmin + it.absmax) * 0.5), true, this);
-
-                                       if(trace_fraction < 1)
-                                               continue;
-
-                                       if(!newgoal || vlen2(it.origin - this.origin) > vlen2(newgoal.origin - this.origin))
-                                               newgoal = it;
-                               });
-
-                               if(newgoal)
-                               {
-                                       this.ignoregoal = this.goalcurrent;
-                                       this.ignoregoaltime = time + autocvar_bot_ai_ignoregoal_timeout;
-                                       navigation_clearroute(this);
-                                       navigation_routetogoal(this, newgoal, this.origin);
-                                       this.aistatus &= ~AI_STATUS_OUT_JUMPPAD;
-                               }
-                       }
-                       else
-                               return;
-               }
-               else
-               {
-                       if(this.velocity.z>0)
-                       {
-                               float threshold;
-                               vector velxy = this.velocity; velxy_z = 0;
-                               threshold = maxspeed * 0.2;
-                               if(vdist(velxy, <, threshold))
-                               {
-                                       LOG_TRACE("Warning: ", this.netname, " got stuck on a jumppad (velocity in xy is ", vtos(velxy), "), trying to get out of it now\n");
-                                       this.aistatus |= AI_STATUS_OUT_JUMPPAD;
-                               }
-                               return;
-                       }
-
-                       // Don't chase players while using a jump pad
-                       if(IS_PLAYER(this.goalcurrent) || IS_PLAYER(this.goalstack01))
-                               return;
-               }
-       }
-       else if(this.aistatus & AI_STATUS_OUT_JUMPPAD)
-               this.aistatus &= ~AI_STATUS_OUT_JUMPPAD;
-
-       // If there is a trigger_hurt right below try to use the jetpack or make a rocketjump
-       if(skill>6)
-       if (!(IS_ONGROUND(this)))
-       {
-               tracebox(this.origin, this.mins, this.maxs, this.origin + '0 0 -65536', MOVE_NOMONSTERS, this);
-               if(tracebox_hits_trigger_hurt(this.origin, this.mins, this.maxs, trace_endpos ))
-               if(this.items & IT_JETPACK)
-               {
-                       tracebox(this.origin, this.mins, this.maxs, this.origin + '0 0 65536', MOVE_NOMONSTERS, this);
-                       if(tracebox_hits_trigger_hurt(this.origin, this.mins, this.maxs, trace_endpos + '0 0 1' ))
-                       {
-                               if(this.velocity.z<0)
-                               {
-                                       PHYS_INPUT_BUTTON_HOOK(this) = true;
-                               }
-                       }
-                       else
-                               PHYS_INPUT_BUTTON_HOOK(this) = true;
-
-                       // If there is no goal try to move forward
-
-                       if(this.goalcurrent==NULL)
-                               dir = v_forward;
-                       else
-                               dir = normalize(( ( this.goalcurrent.absmin + this.goalcurrent.absmax ) * 0.5 ) - this.origin);
-
-                       vector xyvelocity = this.velocity; xyvelocity_z = 0;
-                       float xyspeed = xyvelocity * dir;
-
-                       if(xyspeed < (maxspeed / 2))
-                       {
-                               makevectors(this.v_angle.y * '0 1 0');
-                               tracebox(this.origin, this.mins, this.maxs, this.origin + (dir * maxspeed * 3), MOVE_NOMONSTERS, this);
-                               if(trace_fraction==1)
-                               {
-                                       this.movement_x = dir * v_forward * maxspeed;
-                                       this.movement_y = dir * v_right * maxspeed;
-                                       if (skill < 10)
-                                               havocbot_keyboard_movement(this, this.origin + dir * 100);
-                               }
-                       }
-
-                       this.havocbot_blockhead = true;
-
-                       return;
-               }
-               else if(this.health>WEP_CVAR(devastator, damage)*0.5)
-               {
-                       if(this.velocity.z < 0)
-                       if(client_hasweapon(this, WEP_DEVASTATOR, true, false))
-                       {
-                               this.movement_x = maxspeed;
-
-                               if(this.rocketjumptime)
-                               {
-                                       if(time > this.rocketjumptime)
-                                       {
-                                               PHYS_INPUT_BUTTON_ATCK2(this) = true;
-                                               this.rocketjumptime = 0;
-                                       }
-                                       return;
-                               }
-
-                               PS(this).m_switchweapon = WEP_DEVASTATOR;
-                               this.v_angle_x = 90;
-                               PHYS_INPUT_BUTTON_ATCK(this) = true;
-                               this.rocketjumptime = time + WEP_CVAR(devastator, detonatedelay);
-                               return;
-                       }
-               }
-               else
-               {
-                       // If there is no goal try to move forward
-                       if(this.goalcurrent==NULL)
-                               this.movement_x = maxspeed;
-               }
-       }
-
-       // If we are under water with no goals, swim up
-       if(this.waterlevel)
-       if(this.goalcurrent==NULL)
-       {
-               dir = '0 0 0';
-               if(this.waterlevel>WATERLEVEL_SWIMMING)
-                       dir.z = 1;
-               else if(this.velocity.z >= 0 && !(this.waterlevel == WATERLEVEL_WETFEET && this.watertype == CONTENT_WATER))
-                       PHYS_INPUT_BUTTON_JUMP(this) = true;
-               else
-                       PHYS_INPUT_BUTTON_JUMP(this) = false;
-               makevectors(this.v_angle.y * '0 1 0');
-               this.movement_x = dir * v_forward * maxspeed;
-               this.movement_y = dir * v_right * maxspeed;
-               this.movement_z = dir * v_up * maxspeed;
-       }
-
-       // if there is nowhere to go, exit
-       if (this.goalcurrent == NULL)
-               return;
-
-       if (this.goalcurrent)
-               navigation_poptouchedgoals(this);
-
-       // if ran out of goals try to use an alternative goal or get a new strategy asap
-       if(this.goalcurrent == NULL)
-       {
-               this.bot_strategytime = 0;
-               return;
-       }
-
-
-       if(autocvar_bot_debug_goalstack)
-               debuggoalstack(this);
-
-       m1 = this.goalcurrent.origin + this.goalcurrent.mins;
-       m2 = this.goalcurrent.origin + this.goalcurrent.maxs;
-       destorg = this.origin;
-       destorg.x = bound(m1_x, destorg.x, m2_x);
-       destorg.y = bound(m1_y, destorg.y, m2_y);
-       destorg.z = bound(m1_z, destorg.z, m2_z);
-       diff = destorg - this.origin;
-       //dist = vlen(diff);
-       dir = normalize(diff);
-       flatdir = diff;flatdir.z = 0;
-       flatdir = normalize(flatdir);
-       gco = (this.goalcurrent.absmin + this.goalcurrent.absmax) * 0.5;
-
-       //if (this.bot_dodgevector_time < time)
-       {
-       //      this.bot_dodgevector_time = time + cvar("bot_ai_dodgeupdateinterval");
-       //      this.bot_dodgevector_jumpbutton = 1;
-               evadeobstacle = '0 0 0';
-               evadelava = '0 0 0';
-
-               if (this.waterlevel)
-               {
-                       if(this.waterlevel>WATERLEVEL_SWIMMING)
-                       {
-                       //      flatdir_z = 1;
-                               this.aistatus |= AI_STATUS_OUT_WATER;
-                       }
-                       else
-                       {
-                               if(this.velocity.z >= 0 && !(this.watertype == CONTENT_WATER && gco.z < this.origin.z) &&
-                                       ( !(this.waterlevel == WATERLEVEL_WETFEET && this.watertype == CONTENT_WATER) || this.aistatus & AI_STATUS_OUT_WATER))
-                                       PHYS_INPUT_BUTTON_JUMP(this) = true;
-                               else
-                                       PHYS_INPUT_BUTTON_JUMP(this) = false;
-                       }
-                       dir = normalize(flatdir);
-                       makevectors(this.v_angle.y * '0 1 0');
-               }
-               else
-               {
-                       if(this.aistatus & AI_STATUS_OUT_WATER)
-                               this.aistatus &= ~AI_STATUS_OUT_WATER;
-
-                       // jump if going toward an obstacle that doesn't look like stairs we
-                       // can walk up directly
-                       tracebox(this.origin, this.mins, this.maxs, this.origin + this.velocity * 0.2, false, this);
-                       if (trace_fraction < 1)
-                       if (trace_plane_normal.z < 0.7)
-                       {
-                               s = trace_fraction;
-                               tracebox(this.origin + stepheightvec, this.mins, this.maxs, this.origin + this.velocity * 0.2 + stepheightvec, false, this);
-                               if (trace_fraction < s + 0.01)
-                               if (trace_plane_normal.z < 0.7)
-                               {
-                                       s = trace_fraction;
-                                       tracebox(this.origin + jumpstepheightvec, this.mins, this.maxs, this.origin + this.velocity * 0.2 + jumpstepheightvec, false, this);
-                                       if (trace_fraction > s)
-                                               PHYS_INPUT_BUTTON_JUMP(this) = true;
-                               }
-                       }
-
-                       // avoiding dangers and obstacles
-                       vector dst_ahead, dst_down;
-                       makevectors(this.v_angle.y * '0 1 0');
-                       dst_ahead = this.origin + this.view_ofs + (this.velocity * 0.4) + (v_forward * 32 * 3);
-                       dst_down = dst_ahead - '0 0 1500';
-
-                       // Look ahead
-                       traceline(this.origin + this.view_ofs, dst_ahead, true, NULL);
-
-                       // Check head-banging against walls
-                       if(vdist(this.origin + this.view_ofs - trace_endpos, <, 25) && !(this.aistatus & AI_STATUS_OUT_WATER))
-                       {
-                               PHYS_INPUT_BUTTON_JUMP(this) = true;
-                               if(this.facingwalltime && time > this.facingwalltime)
-                               {
-                                       this.ignoregoal = this.goalcurrent;
-                                       this.ignoregoaltime = time + autocvar_bot_ai_ignoregoal_timeout;
-                                       this.bot_strategytime = 0;
-                                       return;
-                               }
-                               else
-                               {
-                                       this.facingwalltime = time + 0.05;
-                               }
-                       }
-                       else
-                       {
-                               this.facingwalltime = 0;
-
-                               if(this.ignoregoal != NULL && time > this.ignoregoaltime)
-                               {
-                                       this.ignoregoal = NULL;
-                                       this.ignoregoaltime = 0;
-                               }
-                       }
-
-                       // Check for water/slime/lava and dangerous edges
-                       // (only when the bot is on the ground or jumping intentionally)
-                       this.aistatus &= ~AI_STATUS_DANGER_AHEAD;
-
-                       if(trace_fraction == 1 && this.jumppadcount == 0 && !this.goalcurrent.wphardwired )
-                       if((IS_ONGROUND(this)) || (this.aistatus & AI_STATUS_RUNNING) || PHYS_INPUT_BUTTON_JUMP(this))
-                       {
-                               // Look downwards
-                               traceline(dst_ahead , dst_down, true, NULL);
-                       //      te_lightning2(NULL, this.origin, dst_ahead);    // Draw "ahead" look
-                       //      te_lightning2(NULL, dst_ahead, dst_down);               // Draw "downwards" look
-                               if(trace_endpos.z < this.origin.z + this.mins.z)
-                               {
-                                       s = pointcontents(trace_endpos + '0 0 1');
-                                       if (s != CONTENT_SOLID)
-                                       if (s == CONTENT_LAVA || s == CONTENT_SLIME)
-                                               evadelava = normalize(this.velocity) * -1;
-                                       else if (s == CONTENT_SKY)
-                                               evadeobstacle = normalize(this.velocity) * -1;
-                                       else if (!boxesoverlap(dst_ahead - this.view_ofs + this.mins, dst_ahead - this.view_ofs + this.maxs,
-                                                               this.goalcurrent.absmin, this.goalcurrent.absmax))
-                                       {
-                                               // if ain't a safe goal with "holes" (like the jumpad on soylent)
-                                               // and there is a trigger_hurt below
-                                               if(tracebox_hits_trigger_hurt(dst_ahead, this.mins, this.maxs, trace_endpos))
-                                               {
-                                                       // Remove dangerous dynamic goals from stack
-                                                       LOG_TRACE("bot ", this.netname, " avoided the goal ", this.goalcurrent.classname, " ", etos(this.goalcurrent), " because it led to a dangerous path; goal stack cleared\n");
-                                                       navigation_clearroute(this);
-                                                       return;
-                                               }
-                                       }
-                               }
-                       }
-
-                       dir = flatdir;
-                       evadeobstacle.z = 0;
-                       evadelava.z = 0;
-                       makevectors(this.v_angle.y * '0 1 0');
-
-                       if(evadeobstacle!='0 0 0'||evadelava!='0 0 0')
-                               this.aistatus |= AI_STATUS_DANGER_AHEAD;
-               }
-
-               dodge = havocbot_dodge(this);
-               dodge = dodge * bound(0,0.5+(skill+this.bot_dodgeskill)*0.1,1);
-               evadelava = evadelava * bound(1,3-(skill+this.bot_dodgeskill),3); //Noobs fear lava a lot and take more distance from it
-               traceline(this.origin, ( ( this.enemy.absmin + this.enemy.absmax ) * 0.5 ), true, NULL);
-               if(IS_PLAYER(trace_ent))
-                       dir = dir * bound(0,(skill+this.bot_dodgeskill)/7,1);
-
-               dir = normalize(dir + dodge + evadeobstacle + evadelava);
-       //      this.bot_dodgevector = dir;
-       //      this.bot_dodgevector_jumpbutton = PHYS_INPUT_BUTTON_JUMP(this);
-       }
-
-       if(time < this.ladder_time)
-       {
-               if(this.goalcurrent.origin.z + this.goalcurrent.mins.z > this.origin.z + this.mins.z)
-               {
-                       if(this.origin.z + this.mins.z  < this.ladder_entity.origin.z + this.ladder_entity.maxs.z)
-                               dir.z = 1;
-               }
-               else
-               {
-                       if(this.origin.z + this.mins.z  > this.ladder_entity.origin.z + this.ladder_entity.mins.z)
-                               dir.z = -1;
-               }
-       }
-
-       //dir = this.bot_dodgevector;
-       //if (this.bot_dodgevector_jumpbutton)
-       //      PHYS_INPUT_BUTTON_JUMP(this) = true;
-       this.movement_x = dir * v_forward * maxspeed;
-       this.movement_y = dir * v_right * maxspeed;
-       this.movement_z = dir * v_up * maxspeed;
-
-       // Emulate keyboard interface
-       if (skill < 10)
-               havocbot_keyboard_movement(this, destorg);
-
-       // Bunnyhop!
-//     if(this.aistatus & AI_STATUS_ROAMING)
-       if(this.goalcurrent)
-       if(skill+this.bot_moveskill >= autocvar_bot_ai_bunnyhop_skilloffset)
-               havocbot_bunnyhop(this, dir);
-
-       if ((dir * v_up) >= autocvar_sv_jumpvelocity*0.5 && (IS_ONGROUND(this))) PHYS_INPUT_BUTTON_JUMP(this) = true;
-       if (((dodge * v_up) > 0) && random()*frametime >= 0.2*bound(0,(10-skill-this.bot_dodgeskill)*0.1,1)) PHYS_INPUT_BUTTON_JUMP(this) = true;
-       if (((dodge * v_up) < 0) && random()*frametime >= 0.5*bound(0,(10-skill-this.bot_dodgeskill)*0.1,1)) this.havocbot_ducktime=time+0.3/bound(0.1,skill+this.bot_dodgeskill,10);
-}
-
-void havocbot_chooseenemy(entity this)
-{
-       entity head, best, head2;
-       float rating, bestrating, hf;
-       vector eye, v;
-       if (autocvar_bot_nofire || IS_INDEPENDENT_PLAYER(this))
-       {
-               this.enemy = NULL;
-               return;
-       }
-       if (this.enemy)
-       {
-               if (!bot_shouldattack(this, this.enemy))
-               {
-                       // enemy died or something, find a new target
-                       this.enemy = NULL;
-                       this.havocbot_chooseenemy_finished = time;
-               }
-               else if (this.havocbot_stickenemy)
-               {
-                       // tracking last chosen enemy
-                       // if enemy is visible
-                       // and not really really far away
-                       // and we're not severely injured
-                       // then keep tracking for a half second into the future
-                       traceline(this.origin+this.view_ofs, ( this.enemy.absmin + this.enemy.absmax ) * 0.5,false,NULL);
-                       if (trace_ent == this.enemy || trace_fraction == 1)
-                       if (vdist(((this.enemy.absmin + this.enemy.absmax) * 0.5) - this.origin, <, 1000))
-                       if (this.health > 30)
-                       {
-                               // remain tracking him for a shot while (case he went after a small corner or pilar
-                               this.havocbot_chooseenemy_finished = time + 0.5;
-                               return;
-                       }
-                       // enemy isn't visible, or is far away, or we're injured severely
-                       // so stop preferring this enemy
-                       // (it will still take a half second until a new one is chosen)
-                       this.havocbot_stickenemy = 0;
-               }
-       }
-       if (time < this.havocbot_chooseenemy_finished)
-               return;
-       this.havocbot_chooseenemy_finished = time + autocvar_bot_ai_enemydetectioninterval;
-       eye = this.origin + this.view_ofs;
-       best = NULL;
-       bestrating = 100000000;
-       head = head2 = findchainfloat(bot_attack, true);
-
-       // Backup hit flags
-       hf = this.dphitcontentsmask;
-
-       // Search for enemies, if no enemy can be seen directly try to look through transparent objects
-
-       this.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_CORPSE;
-
-       bool scan_transparent = false;
-       bool scan_secondary_targets = false;
-       bool have_secondary_targets = false;
-       while(true)
-       {
-               scan_secondary_targets = false;
-LABEL(scan_targets)
-               for( ; head; head = head.chain)
-               {
-                       if(!scan_secondary_targets)
-                       {
-                               if(head.classname == "misc_breakablemodel")
-                               {
-                                       have_secondary_targets = true;
-                                       continue;
-                               }
-                       }
-                       else
-                       {
-                               if(head.classname != "misc_breakablemodel")
-                                       continue;
-                       }
-
-                       v = (head.absmin + head.absmax) * 0.5;
-                       rating = vlen(v - eye);
-                       if (rating<autocvar_bot_ai_enemydetectionradius)
-                       if (bestrating > rating)
-                       if (bot_shouldattack(this, head))
-                       {
-                               traceline(eye, v, true, this);
-                               if (trace_ent == head || trace_fraction >= 1)
-                               {
-                                       best = head;
-                                       bestrating = rating;
-                               }
-                       }
-               }
-
-               if(!best && have_secondary_targets && !scan_secondary_targets)
-               {
-                       scan_secondary_targets = true;
-                       // restart the loop
-                       head = head2;
-                       bestrating = 100000000;
-                       goto scan_targets;
-               }
-
-               // I want to do a second scan if no enemy was found or I don't have weapons
-               // TODO: Perform the scan when using the rifle (requires changes on the rifle code)
-               if(best || this.weapons) // || this.weapon == WEP_RIFLE.m_id
-                       break;
-               if(scan_transparent)
-                       break;
-
-               // Set flags to see through transparent objects
-               this.dphitcontentsmask |= DPCONTENTS_OPAQUE;
-
-               head = head2;
-               scan_transparent = true;
-       }
-
-       // Restore hit flags
-       this.dphitcontentsmask = hf;
-
-       this.enemy = best;
-       this.havocbot_stickenemy = true;
-       if(best && best.classname == "misc_breakablemodel")
-               this.havocbot_stickenemy = false;
-}
-
-float havocbot_chooseweapon_checkreload(entity this, int new_weapon)
-{
-       // bots under this skill cannot find unloaded weapons to reload idly when not in combat,
-       // so skip this for them, or they'll never get to reload their weapons at all.
-       // this also allows bots under this skill to be more stupid, and reload more often during combat :)
-       if(skill < 5)
-               return false;
-
-       // if this weapon is scheduled for reloading, don't switch to it during combat
-       if (this.weapon_load[new_weapon] < 0)
-       {
-               bool other_weapon_available = false;
-               FOREACH(Weapons, it != WEP_Null, LAMBDA(
-                       if(it.wr_checkammo1(it, this) + it.wr_checkammo2(it, this))
-                               other_weapon_available = true;
-               ));
-               if(other_weapon_available)
-                       return true;
-       }
-
-       return false;
-}
-
-void havocbot_chooseweapon(entity this)
-{
-       int i;
-
-       // ;)
-       if(g_weaponarena_weapons == WEPSET(TUBA))
-       {
-               PS(this).m_switchweapon = WEP_TUBA;
-               return;
-       }
-
-       // TODO: clean this up by moving it to weapon code
-       if(this.enemy==NULL)
-       {
-               // If no weapon was chosen get the first available weapon
-               if(PS(this).m_weapon==WEP_Null)
-               FOREACH(Weapons, it != WEP_Null, LAMBDA(
-                       if(client_hasweapon(this, it, true, false))
-                       {
-                               PS(this).m_switchweapon = it;
-                               return;
-                       }
-               ));
-               return;
-       }
-
-       // Do not change weapon during the next second after a combo
-       float f = time - this.lastcombotime;
-       if(f < 1)
-               return;
-
-       float w;
-       float distance; distance=bound(10,vlen(this.origin-this.enemy.origin)-200,10000);
-
-       // Should it do a weapon combo?
-       float af, ct, combo_time, combo;
-
-       af = ATTACK_FINISHED(this, 0);
-       ct = autocvar_bot_ai_weapon_combo_threshold;
-
-       // Bots with no skill will be 4 times more slower than "godlike" bots when doing weapon combos
-       // Ideally this 4 should be calculated as longest_weapon_refire / bot_ai_weapon_combo_threshold
-       combo_time = time + ct + (ct * ((-0.3*(skill+this.bot_weaponskill))+3));
-
-       combo = false;
-
-       if(autocvar_bot_ai_weapon_combo)
-       if(PS(this).m_weapon.m_id == this.lastfiredweapon)
-       if(af > combo_time)
-       {
-               combo = true;
-               this.lastcombotime = time;
-       }
-
-       distance *= pow(2, this.bot_rangepreference);
-
-       // Custom weapon list based on distance to the enemy
-       if(bot_custom_weapon){
-
-               // Choose weapons for far distance
-               if ( distance > bot_distance_far ) {
-                       for(i=0; i < Weapons_COUNT && bot_weapons_far[i] != -1 ; ++i){
-                               w = bot_weapons_far[i];
-                               if ( client_hasweapon(this, Weapons_from(w), true, false) )
-                               {
-                                       if ((PS(this).m_weapon.m_id == w && combo) || havocbot_chooseweapon_checkreload(this, w))
-                                               continue;
-                                       PS(this).m_switchweapon = Weapons_from(w);
-                                       return;
-                               }
-                       }
-               }
-
-               // Choose weapons for mid distance
-               if ( distance > bot_distance_close) {
-                       for(i=0; i < Weapons_COUNT && bot_weapons_mid[i] != -1 ; ++i){
-                               w = bot_weapons_mid[i];
-                               if ( client_hasweapon(this, Weapons_from(w), true, false) )
-                               {
-                                       if ((PS(this).m_weapon.m_id == w && combo) || havocbot_chooseweapon_checkreload(this, w))
-                                               continue;
-                                       PS(this).m_switchweapon = Weapons_from(w);
-                                       return;
-                               }
-                       }
-               }
-
-               // Choose weapons for close distance
-               for(i=0; i < Weapons_COUNT && bot_weapons_close[i] != -1 ; ++i){
-                       w = bot_weapons_close[i];
-                       if ( client_hasweapon(this, Weapons_from(w), true, false) )
-                       {
-                               if ((PS(this).m_weapon.m_id == w && combo) || havocbot_chooseweapon_checkreload(this, w))
-                                       continue;
-                               PS(this).m_switchweapon = Weapons_from(w);
-                               return;
-                       }
-               }
-       }
-}
-
-void havocbot_aim(entity this)
-{
-       vector myvel, enemyvel;
-//     if(this.flags & FL_INWATER)
-//             return;
-       if (time < this.nextaim)
-               return;
-       this.nextaim = time + 0.1;
-       myvel = this.velocity;
-       if (!this.waterlevel)
-               myvel.z = 0;
-       if (this.enemy)
-       {
-               enemyvel = this.enemy.velocity;
-               if (!this.enemy.waterlevel)
-                       enemyvel.z = 0;
-               lag_additem(this, time + this.ping, 0, 0, this.enemy, this.origin, myvel, (this.enemy.absmin + this.enemy.absmax) * 0.5, enemyvel);
-       }
-       else
-               lag_additem(this, time + this.ping, 0, 0, NULL, this.origin, myvel, ( this.goalcurrent.absmin + this.goalcurrent.absmax ) * 0.5, '0 0 0');
-}
-
-bool havocbot_moveto_refresh_route(entity this)
-{
-       // Refresh path to goal if necessary
-       entity wp;
-       wp = this.havocbot_personal_waypoint;
-       navigation_goalrating_start(this);
-       navigation_routerating(this, wp, 10000, 10000);
-       navigation_goalrating_end(this);
-       return this.navigation_hasgoals;
-}
-
-float havocbot_moveto(entity this, vector pos)
-{
-       entity wp;
-
-       if(this.aistatus & AI_STATUS_WAYPOINT_PERSONAL_GOING)
-       {
-               // Step 4: Move to waypoint
-               if(this.havocbot_personal_waypoint==NULL)
-               {
-                       LOG_TRACE("Error: ", this.netname, " trying to walk to a non existent personal waypoint\n");
-                       this.aistatus &= ~AI_STATUS_WAYPOINT_PERSONAL_GOING;
-                       return CMD_STATUS_ERROR;
-               }
-
-               if (!bot_strategytoken_taken)
-               if(this.havocbot_personal_waypoint_searchtime<time)
-               {
-                       bot_strategytoken_taken = true;
-                       if(havocbot_moveto_refresh_route(this))
-                       {
-                               LOG_TRACE(this.netname, " walking to its personal waypoint (after ", ftos(this.havocbot_personal_waypoint_failcounter), " failed attempts)\n");
-                               this.havocbot_personal_waypoint_searchtime = time + 10;
-                               this.havocbot_personal_waypoint_failcounter = 0;
-                       }
-                       else
-                       {
-                               this.havocbot_personal_waypoint_failcounter += 1;
-                               this.havocbot_personal_waypoint_searchtime = time + 2;
-                               if(this.havocbot_personal_waypoint_failcounter >= 30)
-                               {
-                                       LOG_TRACE("Warning: can't walk to the personal waypoint located at ", vtos(this.havocbot_personal_waypoint.origin),"\n");
-                                       this.aistatus &= ~AI_STATUS_WAYPOINT_PERSONAL_LINKING;
-                                       remove(this.havocbot_personal_waypoint);
-                                       return CMD_STATUS_ERROR;
-                               }
-                               else
-                                       LOG_TRACE(this.netname, " can't walk to its personal waypoint (after ", ftos(this.havocbot_personal_waypoint_failcounter), " failed attempts), trying later\n");
-                       }
-               }
-
-               if(autocvar_bot_debug_goalstack)
-                       debuggoalstack(this);
-
-               // Heading
-               vector dir = ( ( this.goalcurrent.absmin + this.goalcurrent.absmax ) * 0.5 ) - (this.origin + this.view_ofs);
-               dir.z = 0;
-               bot_aimdir(this, dir, -1);
-
-               // Go!
-               havocbot_movetogoal(this);
-
-               if(this.aistatus & AI_STATUS_WAYPOINT_PERSONAL_REACHED)
-               {
-                       // Step 5: Waypoint reached
-                       LOG_TRACE(this.netname, "'s personal waypoint reached\n");
-                       remove(this.havocbot_personal_waypoint);
-                       this.aistatus &= ~AI_STATUS_WAYPOINT_PERSONAL_REACHED;
-                       return CMD_STATUS_FINISHED;
-               }
-
-               return CMD_STATUS_EXECUTING;
-       }
-
-       // Step 2: Linking waypoint
-       if(this.aistatus & AI_STATUS_WAYPOINT_PERSONAL_LINKING)
-       {
-               // Wait until it is linked
-               if(!this.havocbot_personal_waypoint.wplinked)
-               {
-                       LOG_TRACE(this.netname, " waiting for personal waypoint to be linked\n");
-                       return CMD_STATUS_EXECUTING;
-               }
-
-               this.havocbot_personal_waypoint_searchtime = time; // so we set the route next frame
-               this.aistatus &= ~AI_STATUS_WAYPOINT_PERSONAL_LINKING;
-               this.aistatus |= AI_STATUS_WAYPOINT_PERSONAL_GOING;
-
-               // Step 3: Route to waypoint
-               LOG_TRACE(this.netname, " walking to its personal waypoint\n");
-
-               return CMD_STATUS_EXECUTING;
-       }
-
-       // Step 1: Spawning waypoint
-       wp = waypoint_spawnpersonal(this, pos);
-       if(wp==NULL)
-       {
-               LOG_TRACE("Error: Can't spawn personal waypoint at ",vtos(pos),"\n");
-               return CMD_STATUS_ERROR;
-       }
-
-       this.havocbot_personal_waypoint = wp;
-       this.havocbot_personal_waypoint_failcounter = 0;
-       this.aistatus |= AI_STATUS_WAYPOINT_PERSONAL_LINKING;
-
-       // if pos is inside a teleport, then let's mark it as teleport waypoint
-       FOREACH_ENTITY_CLASS("trigger_teleport", WarpZoneLib_BoxTouchesBrush(pos, pos, it, NULL),
-       {
-               wp.wpflags |= WAYPOINTFLAG_TELEPORT;
-               this.lastteleporttime = 0;
-       });
-
-/*
-       if(wp.wpflags & WAYPOINTFLAG_TELEPORT)
-               print("routing to a teleporter\n");
-       else
-               print("routing to a non-teleporter\n");
-*/
-
-       return CMD_STATUS_EXECUTING;
-}
-
-float havocbot_resetgoal(entity this)
-{
-       navigation_clearroute(this);
-       return CMD_STATUS_FINISHED;
-}
-
-void havocbot_setupbot(entity this)
-{
-       this.bot_ai = havocbot_ai;
-       this.cmd_moveto = havocbot_moveto;
-       this.cmd_resetgoal = havocbot_resetgoal;
-
-       havocbot_chooserole(this);
-}
-
-vector havocbot_dodge(entity this)
-{
-       // LordHavoc: disabled because this is too expensive
-       return '0 0 0';
-#if 0
-       entity head;
-       vector dodge, v, n;
-       float danger, bestdanger, vl, d;
-       dodge = '0 0 0';
-       bestdanger = -20;
-       // check for dangerous objects near bot or approaching bot
-       head = findchainfloat(bot_dodge, true);
-       while(head)
-       {
-               if (head.owner != this)
-               {
-                       vl = vlen(head.velocity);
-                       if (vl > autocvar_sv_maxspeed * 0.3)
-                       {
-                               n = normalize(head.velocity);
-                               v = this.origin - head.origin;
-                               d = v * n;
-                               if (d > (0 - head.bot_dodgerating))
-                               if (d < (vl * 0.2 + head.bot_dodgerating))
-                               {
-                                       // calculate direction and distance from the flight path, by removing the forward axis
-                                       v = v - (n * (v * n));
-                                       danger = head.bot_dodgerating - vlen(v);
-                                       if (bestdanger < danger)
-                                       {
-                                               bestdanger = danger;
-                                               // dodge to the side of the object
-                                               dodge = normalize(v);
-                                       }
-                               }
-                       }
-                       else
-                       {
-                               danger = head.bot_dodgerating - vlen(head.origin - this.origin);
-                               if (bestdanger < danger)
-                               {
-                                       bestdanger = danger;
-                                       dodge = normalize(this.origin - head.origin);
-                               }
-                       }
-               }
-               head = head.chain;
-       }
-       return dodge;
-#endif
-}
diff --git a/qcsrc/server/bot/havocbot/havocbot.qh b/qcsrc/server/bot/havocbot/havocbot.qh
deleted file mode 100644 (file)
index 4a391b6..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-#pragma once
-
-/*
- * Globals and Fields
- */
-
-.float havocbot_keyboardskill;
-.float facingwalltime, ignoregoaltime;
-.float lastfiredweapon;
-.float lastcombotime;
-.float havocbot_blockhead;
-
-.float havocbot_keyboardtime;
-.float havocbot_ducktime;
-.float bot_timelastseengoal;
-.float bot_canruntogoal;
-.float bot_chooseweapontime;
-.float rocketjumptime;
-.float nextaim;
-.float havocbot_personal_waypoint_searchtime;
-.float havocbot_personal_waypoint_failcounter;
-.float havocbot_chooseenemy_finished;
-.float havocbot_stickenemy;
-.float havocbot_role_timeout;
-
-.entity ignoregoal;
-.entity bot_lastseengoal;
-.entity havocbot_personal_waypoint;
-
-.vector havocbot_keyboard;
-
-/*
- * Functions
- */
-
-void havocbot_ai(entity this);
-void havocbot_aim(entity this);
-void havocbot_setupbot(entity this);
-void havocbot_movetogoal(entity this);
-void havocbot_chooserole(entity this);
-void havocbot_chooseenemy(entity this);
-void havocbot_chooseweapon(entity this);
-void havocbot_bunnyhop(entity this, vector dir);
-void havocbot_keyboard_movement(entity this, vector destorg);
-
-float havocbot_resetgoal(entity this);
-float havocbot_moveto(entity this, vector pos);
-float havocbot_moveto_refresh_route(entity this);
-
-vector havocbot_dodge(entity this);
-
-.void(entity this) havocbot_role;
-.void(entity this) havocbot_previous_role;
-
-void(entity this, float ratingscale, vector org, float sradius) havocbot_goalrating_items;
-void(entity this, float ratingscale, vector org, float sradius) havocbot_goalrating_enemyplayers;
-
-/*
- * Imports
- */
-
-.entity draggedby;
-.float ladder_time;
-.entity ladder_entity;
diff --git a/qcsrc/server/bot/havocbot/roles.qc b/qcsrc/server/bot/havocbot/roles.qc
deleted file mode 100644 (file)
index 9ea6a3d..0000000
+++ /dev/null
@@ -1,208 +0,0 @@
-#include "roles.qh"
-
-#include "havocbot.qh"
-
-#include "../bot.qh"
-#include "../navigation.qh"
-
-.float max_armorvalue;
-.float havocbot_role_timeout;
-
-.void(entity this) havocbot_previous_role;
-.void(entity this) havocbot_role;
-
-void havocbot_goalrating_items(entity this, float ratingscale, vector org, float sradius)
-{
-       float rating, d, discard, friend_distance, enemy_distance;
-       vector o;
-       ratingscale = ratingscale * 0.0001; // items are rated around 10000 already
-
-       FOREACH_ENTITY_FLOAT(bot_pickup, true,
-       {
-               o = (it.absmin + it.absmax) * 0.5;
-               friend_distance = 10000; enemy_distance = 10000;
-               rating = 0;
-
-               if(!it.solid || vdist(o - org, >, sradius) || (it == this.ignoregoal && time < this.ignoregoaltime) )
-                       continue;
-
-               // Check if the item can be picked up safely
-               if(it.classname == "droppedweapon")
-               {
-                       traceline(o, o + '0 0 -1500', true, NULL);
-
-                       d = pointcontents(trace_endpos + '0 0 1');
-                       if(d & CONTENT_WATER || d & CONTENT_SLIME || d & CONTENT_LAVA)
-                               continue;
-                       if(tracebox_hits_trigger_hurt(it.origin, it.mins, it.maxs, trace_endpos))
-                               continue;
-               }
-               else
-               {
-                       // Ignore items under water
-                       traceline(it.origin + it.maxs, it.origin + it.maxs, MOVE_NORMAL, it);
-                       if(trace_dpstartcontents & DPCONTENTS_LIQUIDSMASK)
-                               continue;
-               }
-
-               if(teamplay)
-               {
-                       discard = false;
-
-                       entity picker = it;
-                       FOREACH_CLIENT(IS_PLAYER(it) && it != this && !IS_DEAD(it),
-                       {
-                               d = vlen(it.origin - o); // distance between player and item
-
-                               if ( it.team == this.team )
-                               {
-                                       if ( !IS_REAL_CLIENT(it) || discard )
-                                               continue;
-
-                                       if( d > friend_distance)
-                                               continue;
-
-                                       friend_distance = d;
-
-                                       discard = true;
-
-                                       if( picker.health && it.health > this.health )
-                                               continue;
-
-                                       if( picker.armorvalue && it.armorvalue > this.armorvalue)
-                                               continue;
-
-                                       if( picker.weapons )
-                                       if( picker.weapons & ~it.weapons )
-                                               continue;
-
-                                       if (picker.ammo_shells && it.ammo_shells > this.ammo_shells)
-                                               continue;
-
-                                       if (picker.ammo_nails && it.ammo_nails > this.ammo_nails)
-                                               continue;
-
-                                       if (picker.ammo_rockets && it.ammo_rockets > this.ammo_rockets)
-                                               continue;
-
-                                       if (picker.ammo_cells && it.ammo_cells > this.ammo_cells)
-                                               continue;
-
-                                       if (picker.ammo_plasma && it.ammo_plasma > this.ammo_plasma)
-                                               continue;
-
-                                       discard = false;
-                               }
-                               else
-                               {
-                                       // If enemy only track distances
-                                       // TODO: track only if visible ?
-                                       if( d < enemy_distance )
-                                               enemy_distance = d;
-                               }
-                       });
-
-                       // Rate the item only if no one needs it, or if an enemy is closer to it
-                       if ( (enemy_distance < friend_distance && vdist(o - org, <, enemy_distance)) ||
-                               (friend_distance > autocvar_bot_ai_friends_aware_pickup_radius ) || !discard )
-                               rating = it.bot_pickupevalfunc(this, it);
-
-               }
-               else
-                       rating = it.bot_pickupevalfunc(this, it);
-
-               if(rating > 0)
-                       navigation_routerating(this, it, rating * ratingscale, 2000);
-       });
-}
-
-void havocbot_goalrating_controlpoints(entity this, float ratingscale, vector org, float sradius)
-{
-       FOREACH_ENTITY_CLASS("dom_controlpoint", vdist((((it.absmin + it.absmax) * 0.5) - org), <, sradius),
-       {
-               if(it.cnt > -1) // this is just being fought
-                       navigation_routerating(this, it, ratingscale, 5000);
-               else if(it.goalentity.cnt == 0) // unclaimed
-                       navigation_routerating(this, it, ratingscale * 0.5, 5000);
-               else if(it.goalentity.team != this.team) // other team's point
-                       navigation_routerating(this, it, ratingscale * 0.2, 5000);
-       });
-}
-
-void havocbot_goalrating_enemyplayers(entity this, float ratingscale, vector org, float sradius)
-{
-       if (autocvar_bot_nofire)
-               return;
-
-       // don't chase players if we're under water
-       if(this.waterlevel>WATERLEVEL_WETFEET)
-               return;
-
-       int t;
-
-       FOREACH_CLIENT(IS_PLAYER(it) && bot_shouldattack(this, it), LAMBDA(
-               // TODO: Merge this logic with the bot_shouldattack function
-               if(vdist(it.origin - org, <, 100) || vdist(it.origin - org, >, sradius))
-                       continue;
-
-               // rate only visible enemies
-               /*
-               traceline(this.origin + this.view_ofs, it.origin, MOVE_NOMONSTERS, this);
-               if (trace_fraction < 1 || trace_ent != it)
-                       continue;
-               */
-
-               if((it.flags & FL_INWATER) || (it.flags & FL_PARTIALGROUND))
-                       continue;
-
-               // not falling
-               if((IS_ONGROUND(it)) == 0)
-               {
-                       traceline(it.origin, it.origin + '0 0 -1500', true, NULL);
-                       t = pointcontents(trace_endpos + '0 0 1');
-                       if(t != CONTENT_SOLID )
-                       if(t & CONTENT_WATER || t & CONTENT_SLIME || t & CONTENT_LAVA)
-                               continue;
-                       if(tracebox_hits_trigger_hurt(it.origin, it.mins, it.maxs, trace_endpos))
-                               continue;
-               }
-
-               // TODO: rate waypoints near the targetted player at that moment, instead of the player itthis
-               //               adding a player as a goal seems to be quite dangerous, especially on space maps
-               //               remove hack in navigation_poptouchedgoals() after performing this change
-
-               t = (this.health + this.armorvalue ) / (it.health + it.armorvalue );
-               navigation_routerating(this, it, t * ratingscale, 2000);
-       ));
-}
-
-// legacy bot role for standard gamemodes
-// go to best items
-void havocbot_role_generic(entity this)
-{
-       if(IS_DEAD(this))
-               return;
-
-       if (this.bot_strategytime < time)
-       {
-               this.bot_strategytime = time + autocvar_bot_ai_strategyinterval;
-               navigation_goalrating_start(this);
-               havocbot_goalrating_items(this, 10000, this.origin, 10000);
-               havocbot_goalrating_enemyplayers(this, 20000, this.origin, 10000);
-               //havocbot_goalrating_waypoints(1, this.origin, 1000);
-               navigation_goalrating_end(this);
-       }
-}
-
-void havocbot_chooserole_generic(entity this)
-{
-       this.havocbot_role = havocbot_role_generic;
-}
-
-void havocbot_chooserole(entity this)
-{
-       LOG_TRACE("choosing a role...\n");
-       this.bot_strategytime = 0;
-       if(!MUTATOR_CALLHOOK(HavocBot_ChooseRole, this))
-               havocbot_chooserole_generic(this);
-}
diff --git a/qcsrc/server/bot/havocbot/roles.qh b/qcsrc/server/bot/havocbot/roles.qh
deleted file mode 100644 (file)
index 5b1f2b5..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-#pragma once
-void havocbot_goalrating_controlpoints(entity this, float ratingscale, vector org, float sradius);
diff --git a/qcsrc/server/bot/havocbot/scripting.qh b/qcsrc/server/bot/havocbot/scripting.qh
deleted file mode 100644 (file)
index 07cb4d6..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-#pragma once
-
-void bot_clearqueue(entity bot);
diff --git a/qcsrc/server/bot/navigation.qc b/qcsrc/server/bot/navigation.qc
deleted file mode 100644 (file)
index c9418e2..0000000
+++ /dev/null
@@ -1,1211 +0,0 @@
-#include "navigation.qh"
-
-#include "bot.qh"
-#include "waypoints.qh"
-
-#include <common/t_items.qh>
-
-#include <common/items/all.qh>
-
-#include <common/constants.qh>
-#include <common/triggers/trigger/jumppads.qh>
-
-.float speed;
-
-// rough simulation of walking from one point to another to test if a path
-// can be traveled, used for waypoint linking and havocbot
-
-bool tracewalk(entity e, vector start, vector m1, vector m2, vector end, float movemode)
-{
-       vector org;
-       vector move;
-       vector dir;
-       float dist;
-       float totaldist;
-       float stepdist;
-       float yaw;
-       float ignorehazards;
-       float swimming;
-
-       if(autocvar_bot_debug_tracewalk)
-       {
-               debugresetnodes();
-               debugnode(e, start);
-       }
-
-       move = end - start;
-       move.z = 0;
-       org = start;
-       dist = totaldist = vlen(move);
-       dir = normalize(move);
-       stepdist = 32;
-       ignorehazards = false;
-       swimming = false;
-
-       // Analyze starting point
-       traceline(start, start, MOVE_NORMAL, e);
-       if (trace_dpstartcontents & (DPCONTENTS_SLIME | DPCONTENTS_LAVA))
-               ignorehazards = true;
-       else
-       {
-               traceline( start, start + '0 0 -65536', MOVE_NORMAL, e);
-               if (trace_dpstartcontents & (DPCONTENTS_SLIME | DPCONTENTS_LAVA))
-               {
-                       ignorehazards = true;
-                       swimming = true;
-               }
-       }
-       tracebox(start, m1, m2, start, MOVE_NOMONSTERS, e);
-       if (trace_startsolid)
-       {
-               // Bad start
-               if(autocvar_bot_debug_tracewalk)
-                       debugnodestatus(start, DEBUG_NODE_FAIL);
-
-               //print("tracewalk: ", vtos(start), " is a bad start\n");
-               return false;
-       }
-
-       // Movement loop
-       yaw = vectoyaw(move);
-       move = end - org;
-       for (;;)
-       {
-               if (boxesoverlap(end, end, org + m1 + '-1 -1 -1', org + m2 + '1 1 1'))
-               {
-                       // Succeeded
-                       if(autocvar_bot_debug_tracewalk)
-                               debugnodestatus(org, DEBUG_NODE_SUCCESS);
-
-                       //print("tracewalk: ", vtos(start), " can reach ", vtos(end), "\n");
-                       return true;
-               }
-               if(autocvar_bot_debug_tracewalk)
-                       debugnode(e, org);
-
-               if (dist <= 0)
-                       break;
-               if (stepdist > dist)
-                       stepdist = dist;
-               dist = dist - stepdist;
-               traceline(org, org, MOVE_NORMAL, e);
-               if (!ignorehazards)
-               {
-                       if (trace_dpstartcontents & (DPCONTENTS_SLIME | DPCONTENTS_LAVA))
-                       {
-                               // hazards blocking path
-                               if(autocvar_bot_debug_tracewalk)
-                                       debugnodestatus(org, DEBUG_NODE_FAIL);
-
-                               //print("tracewalk: ", vtos(start), " hits a hazard when trying to reach ", vtos(end), "\n");
-                               return false;
-                       }
-               }
-               if (trace_dpstartcontents & DPCONTENTS_LIQUIDSMASK)
-               {
-                       move = normalize(end - org);
-                       tracebox(org, m1, m2, org + move * stepdist, movemode, e);
-
-                       if(autocvar_bot_debug_tracewalk)
-                               debugnode(e, trace_endpos);
-
-                       if (trace_fraction < 1)
-                       {
-                               swimming = true;
-                               org = trace_endpos - normalize(org - trace_endpos) * stepdist;
-                               for (; org.z < end.z + e.maxs.z; org.z += stepdist)
-                               {
-                                               if(autocvar_bot_debug_tracewalk)
-                                                       debugnode(e, org);
-
-                                       if(pointcontents(org) == CONTENT_EMPTY)
-                                                       break;
-                               }
-
-                               if(pointcontents(org + '0 0 1') != CONTENT_EMPTY)
-                               {
-                                       if(autocvar_bot_debug_tracewalk)
-                                               debugnodestatus(org, DEBUG_NODE_FAIL);
-
-                                       return false;
-                                       //print("tracewalk: ", vtos(start), " failed under water\n");
-                               }
-                               continue;
-
-                       }
-                       else
-                               org = trace_endpos;
-               }
-               else
-               {
-                       move = dir * stepdist + org;
-                       tracebox(org, m1, m2, move, movemode, e);
-
-                       if(autocvar_bot_debug_tracewalk)
-                               debugnode(e, trace_endpos);
-
-                       // hit something
-                       if (trace_fraction < 1)
-                       {
-                               // check if we can walk over this obstacle, possibly by jumpstepping
-                               tracebox(org + stepheightvec, m1, m2, move + stepheightvec, movemode, e);
-                               if (trace_fraction < 1 || trace_startsolid)
-                               {
-                                       tracebox(org + jumpstepheightvec, m1, m2, move + jumpstepheightvec, movemode, e);
-                                       if (trace_fraction < 1 || trace_startsolid)
-                                       {
-                                               if(autocvar_bot_debug_tracewalk)
-                                                       debugnodestatus(trace_endpos, DEBUG_NODE_WARNING);
-
-                                               // check for doors
-                                               traceline( org, move, movemode, e);
-                                               if ( trace_ent.classname == "door_rotating" || trace_ent.classname == "door")
-                                               {
-                                                       vector nextmove;
-                                                       move = trace_endpos;
-                                                       while(trace_ent.classname == "door_rotating" || trace_ent.classname == "door")
-                                                       {
-                                                               nextmove = move + (dir * stepdist);
-                                                               traceline( move, nextmove, movemode, e);
-                                                               move = nextmove;
-                                                       }
-                                               }
-                                               else
-                                               {
-                                                       if(autocvar_bot_debug_tracewalk)
-                                                               debugnodestatus(trace_endpos, DEBUG_NODE_FAIL);
-
-                                                       //print("tracewalk: ", vtos(start), " hit something when trying to reach ", vtos(end), "\n");
-                                                       //te_explosion(trace_endpos);
-                                                       //print(ftos(e.dphitcontentsmask), "\n");
-                                                       return false; // failed
-                                               }
-                                       }
-                                       else
-                                               move = trace_endpos;
-                               }
-                               else
-                                       move = trace_endpos;
-                       }
-                       else
-                               move = trace_endpos;
-
-                       // trace down from stepheight as far as possible and move there,
-                       // if this starts in solid we try again without the stepup, and
-                       // if that also fails we assume it is a wall
-                       // (this is the same logic as the Quake walkmove function used)
-                       tracebox(move, m1, m2, move + '0 0 -65536', movemode, e);
-
-                       // moved successfully
-                       if(swimming)
-                       {
-                               float c;
-                               c = pointcontents(org + '0 0 1');
-                               if (!(c == CONTENT_WATER || c == CONTENT_LAVA || c == CONTENT_SLIME))
-                                       swimming = false;
-                               else
-                                       continue;
-                       }
-
-                       org = trace_endpos;
-               }
-       }
-
-       //print("tracewalk: ", vtos(start), " did not arrive at ", vtos(end), " but at ", vtos(org), "\n");
-
-       // moved but didn't arrive at the intended destination
-       if(autocvar_bot_debug_tracewalk)
-               debugnodestatus(org, DEBUG_NODE_FAIL);
-
-       return false;
-}
-
-/////////////////////////////////////////////////////////////////////////////
-// goal stack
-/////////////////////////////////////////////////////////////////////////////
-
-// completely empty the goal stack, used when deciding where to go
-void navigation_clearroute(entity this)
-{
-       //print("bot ", etos(this), " clear\n");
-       this.navigation_hasgoals = false;
-       this.goalcurrent = NULL;
-       this.goalstack01 = NULL;
-       this.goalstack02 = NULL;
-       this.goalstack03 = NULL;
-       this.goalstack04 = NULL;
-       this.goalstack05 = NULL;
-       this.goalstack06 = NULL;
-       this.goalstack07 = NULL;
-       this.goalstack08 = NULL;
-       this.goalstack09 = NULL;
-       this.goalstack10 = NULL;
-       this.goalstack11 = NULL;
-       this.goalstack12 = NULL;
-       this.goalstack13 = NULL;
-       this.goalstack14 = NULL;
-       this.goalstack15 = NULL;
-       this.goalstack16 = NULL;
-       this.goalstack17 = NULL;
-       this.goalstack18 = NULL;
-       this.goalstack19 = NULL;
-       this.goalstack20 = NULL;
-       this.goalstack21 = NULL;
-       this.goalstack22 = NULL;
-       this.goalstack23 = NULL;
-       this.goalstack24 = NULL;
-       this.goalstack25 = NULL;
-       this.goalstack26 = NULL;
-       this.goalstack27 = NULL;
-       this.goalstack28 = NULL;
-       this.goalstack29 = NULL;
-       this.goalstack30 = NULL;
-       this.goalstack31 = NULL;
-}
-
-// add a new goal at the beginning of the stack
-// (in other words: add a new prerequisite before going to the later goals)
-// NOTE: when a waypoint is added, the WP gets pushed first, then the
-// next-closest WP on the shortest path to the WP
-// That means, if the stack overflows, the bot will know how to do the FIRST 32
-// steps to the goal, and then recalculate the path.
-void navigation_pushroute(entity this, entity e)
-{
-       //print("bot ", etos(this), " push ", etos(e), "\n");
-       this.goalstack31 = this.goalstack30;
-       this.goalstack30 = this.goalstack29;
-       this.goalstack29 = this.goalstack28;
-       this.goalstack28 = this.goalstack27;
-       this.goalstack27 = this.goalstack26;
-       this.goalstack26 = this.goalstack25;
-       this.goalstack25 = this.goalstack24;
-       this.goalstack24 = this.goalstack23;
-       this.goalstack23 = this.goalstack22;
-       this.goalstack22 = this.goalstack21;
-       this.goalstack21 = this.goalstack20;
-       this.goalstack20 = this.goalstack19;
-       this.goalstack19 = this.goalstack18;
-       this.goalstack18 = this.goalstack17;
-       this.goalstack17 = this.goalstack16;
-       this.goalstack16 = this.goalstack15;
-       this.goalstack15 = this.goalstack14;
-       this.goalstack14 = this.goalstack13;
-       this.goalstack13 = this.goalstack12;
-       this.goalstack12 = this.goalstack11;
-       this.goalstack11 = this.goalstack10;
-       this.goalstack10 = this.goalstack09;
-       this.goalstack09 = this.goalstack08;
-       this.goalstack08 = this.goalstack07;
-       this.goalstack07 = this.goalstack06;
-       this.goalstack06 = this.goalstack05;
-       this.goalstack05 = this.goalstack04;
-       this.goalstack04 = this.goalstack03;
-       this.goalstack03 = this.goalstack02;
-       this.goalstack02 = this.goalstack01;
-       this.goalstack01 = this.goalcurrent;
-       this.goalcurrent = e;
-}
-
-// remove first goal from stack
-// (in other words: remove a prerequisite for reaching the later goals)
-// (used when a spawnfunc_waypoint is reached)
-void navigation_poproute(entity this)
-{
-       //print("bot ", etos(this), " pop\n");
-       this.goalcurrent = this.goalstack01;
-       this.goalstack01 = this.goalstack02;
-       this.goalstack02 = this.goalstack03;
-       this.goalstack03 = this.goalstack04;
-       this.goalstack04 = this.goalstack05;
-       this.goalstack05 = this.goalstack06;
-       this.goalstack06 = this.goalstack07;
-       this.goalstack07 = this.goalstack08;
-       this.goalstack08 = this.goalstack09;
-       this.goalstack09 = this.goalstack10;
-       this.goalstack10 = this.goalstack11;
-       this.goalstack11 = this.goalstack12;
-       this.goalstack12 = this.goalstack13;
-       this.goalstack13 = this.goalstack14;
-       this.goalstack14 = this.goalstack15;
-       this.goalstack15 = this.goalstack16;
-       this.goalstack16 = this.goalstack17;
-       this.goalstack17 = this.goalstack18;
-       this.goalstack18 = this.goalstack19;
-       this.goalstack19 = this.goalstack20;
-       this.goalstack20 = this.goalstack21;
-       this.goalstack21 = this.goalstack22;
-       this.goalstack22 = this.goalstack23;
-       this.goalstack23 = this.goalstack24;
-       this.goalstack24 = this.goalstack25;
-       this.goalstack25 = this.goalstack26;
-       this.goalstack26 = this.goalstack27;
-       this.goalstack27 = this.goalstack28;
-       this.goalstack28 = this.goalstack29;
-       this.goalstack29 = this.goalstack30;
-       this.goalstack30 = this.goalstack31;
-       this.goalstack31 = NULL;
-}
-
-float navigation_waypoint_will_link(vector v, vector org, entity ent, float walkfromwp, float bestdist)
-{
-       float dist;
-       dist = vlen(v - org);
-       if (bestdist > dist)
-       {
-               traceline(v, org, true, ent);
-               if (trace_fraction == 1)
-               {
-                       if (walkfromwp)
-                       {
-                               if (tracewalk(ent, v, STAT(PL_MIN, NULL), STAT(PL_MAX, NULL), org, bot_navigation_movemode))
-                                       return true;
-                       }
-                       else
-                       {
-                               if (tracewalk(ent, org, STAT(PL_MIN, NULL), STAT(PL_MAX, NULL), v, bot_navigation_movemode))
-                                       return true;
-                       }
-               }
-       }
-       return false;
-}
-
-// find the spawnfunc_waypoint near a dynamic goal such as a dropped weapon
-entity navigation_findnearestwaypoint_withdist_except(entity ent, float walkfromwp, float bestdist, entity except)
-{
-       vector pm1 = ent.origin + ent.mins;
-       vector pm2 = ent.origin + ent.maxs;
-
-       // do two scans, because box test is cheaper
-       IL_EACH(g_waypoints, it != ent && it != except,
-       {
-               if(boxesoverlap(pm1, pm2, it.absmin, it.absmax))
-                       return it;
-       });
-
-       vector org = ent.origin + 0.5 * (ent.mins + ent.maxs);
-       org.z = ent.origin.z + ent.mins.z - STAT(PL_MIN, NULL).z; // player height
-       // TODO possibly make other code have the same support for bboxes
-       if(ent.tag_entity)
-               org = org + ent.tag_entity.origin;
-       if (navigation_testtracewalk)
-               te_plasmaburn(org);
-
-       entity best = NULL;
-       vector v;
-
-       // box check failed, try walk
-       IL_EACH(g_waypoints, it != ent,
-       {
-               if(it.wpisbox)
-               {
-                       vector wm1 = it.origin + it.mins;
-                       vector wm2 = it.origin + it.maxs;
-                       v.x = bound(wm1_x, org.x, wm2_x);
-                       v.y = bound(wm1_y, org.y, wm2_y);
-                       v.z = bound(wm1_z, org.z, wm2_z);
-               }
-               else
-                       v = it.origin;
-               if(navigation_waypoint_will_link(v, org, ent, walkfromwp, bestdist))
-               {
-                       bestdist = vlen(v - org);
-                       best = it;
-               }
-       });
-       return best;
-}
-entity navigation_findnearestwaypoint(entity ent, float walkfromwp)
-{
-       entity wp = navigation_findnearestwaypoint_withdist_except(ent, walkfromwp, 1050, NULL);
-       if (autocvar_g_waypointeditor_auto)
-       {
-               entity wp2 = navigation_findnearestwaypoint_withdist_except(ent, walkfromwp, 1050, wp);
-               if (wp && !wp2)
-                       wp.wpflags |= WAYPOINTFLAG_PROTECTED;
-       }
-       return wp;
-}
-
-// finds the waypoints near the bot initiating a navigation query
-float navigation_markroutes_nearestwaypoints(entity this, float maxdist)
-{
-       vector v, m1, m2;
-//     navigation_testtracewalk = true;
-       int c = 0;
-       IL_EACH(g_waypoints, !it.wpconsidered,
-       {
-               if (it.wpisbox)
-               {
-                       m1 = it.origin + it.mins;
-                       m2 = it.origin + it.maxs;
-                       v = this.origin;
-                       v.x = bound(m1_x, v.x, m2_x);
-                       v.y = bound(m1_y, v.y, m2_y);
-                       v.z = bound(m1_z, v.z, m2_z);
-               }
-               else
-                       v = it.origin;
-               vector diff = v - this.origin;
-               diff.z = max(0, diff.z);
-               if(vdist(diff, <, maxdist))
-               {
-                       it.wpconsidered = true;
-                       if (tracewalk(this, this.origin, this.mins, this.maxs, v, bot_navigation_movemode))
-                       {
-                               it.wpnearestpoint = v;
-                               it.wpcost = vlen(v - this.origin) + it.dmg;
-                               it.wpfire = 1;
-                               it.enemy = NULL;
-                               c = c + 1;
-                       }
-               }
-       });
-       //navigation_testtracewalk = false;
-       return c;
-}
-
-// updates a path link if a spawnfunc_waypoint link is better than the current one
-void navigation_markroutes_checkwaypoint(entity w, entity wp, float cost2, vector p)
-{
-       vector m1;
-       vector m2;
-       vector v;
-       if (wp.wpisbox)
-       {
-               m1 = wp.absmin;
-               m2 = wp.absmax;
-               v.x = bound(m1_x, p.x, m2_x);
-               v.y = bound(m1_y, p.y, m2_y);
-               v.z = bound(m1_z, p.z, m2_z);
-       }
-       else
-               v = wp.origin;
-       cost2 = cost2 + vlen(v - p);
-       if (wp.wpcost > cost2)
-       {
-               wp.wpcost = cost2;
-               wp.enemy = w;
-               wp.wpfire = 1;
-               wp.wpnearestpoint = v;
-       }
-}
-
-// queries the entire spawnfunc_waypoint network for pathes leading away from the bot
-void navigation_markroutes(entity this, entity fixed_source_waypoint)
-{
-       float cost, cost2;
-       vector p;
-
-       IL_EACH(g_waypoints, true,
-       {
-               it.wpconsidered = false;
-               it.wpnearestpoint = '0 0 0';
-               it.wpcost = 10000000;
-               it.wpfire = 0;
-               it.enemy = NULL;
-       });
-
-       if(fixed_source_waypoint)
-       {
-               fixed_source_waypoint.wpconsidered = true;
-               fixed_source_waypoint.wpnearestpoint = fixed_source_waypoint.origin + 0.5 * (fixed_source_waypoint.mins + fixed_source_waypoint.maxs);
-               fixed_source_waypoint.wpcost = fixed_source_waypoint.dmg;
-               fixed_source_waypoint.wpfire = 1;
-               fixed_source_waypoint.enemy = NULL;
-       }
-       else
-       {
-               // try a short range search for the nearest waypoints, and expand the search repeatedly if none are found
-               // as this search is expensive we will use lower values if the bot is on the air
-               float increment, maxdistance;
-               if(IS_ONGROUND(this))
-               {
-                       increment = 750;
-                       maxdistance = 50000;
-               }
-               else
-               {
-                       increment = 500;
-                       maxdistance = 1500;
-               }
-
-               for(int j = increment; !navigation_markroutes_nearestwaypoints(this, j) && j < maxdistance; j += increment);
-       }
-
-       bool searching = true;
-       while (searching)
-       {
-               searching = false;
-               IL_EACH(g_waypoints, it.wpfire,
-               {
-                       searching = true;
-                       it.wpfire = 0;
-                       cost = it.wpcost;
-                       p = it.wpnearestpoint;
-                       entity wp;
-                       wp = it.wp00;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp00mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
-                       wp = it.wp01;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp01mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
-                       wp = it.wp02;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp02mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
-                       wp = it.wp03;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp03mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
-                       wp = it.wp04;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp04mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
-                       wp = it.wp05;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp05mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
-                       wp = it.wp06;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp06mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
-                       wp = it.wp07;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp07mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
-                       wp = it.wp08;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp08mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
-                       wp = it.wp09;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp09mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
-                       wp = it.wp10;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp10mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
-                       wp = it.wp11;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp11mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
-                       wp = it.wp12;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp12mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
-                       wp = it.wp13;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp13mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
-                       wp = it.wp14;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp14mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
-                       wp = it.wp15;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp15mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
-                       wp = it.wp16;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp16mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
-                       wp = it.wp17;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp17mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
-                       wp = it.wp18;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp18mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
-                       wp = it.wp19;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp19mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
-                       wp = it.wp20;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp20mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
-                       wp = it.wp21;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp21mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
-                       wp = it.wp22;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp22mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
-                       wp = it.wp23;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp23mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
-                       wp = it.wp24;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp24mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
-                       wp = it.wp25;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp25mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
-                       wp = it.wp26;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp26mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
-                       wp = it.wp27;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp27mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
-                       wp = it.wp28;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp28mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
-                       wp = it.wp29;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp29mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
-                       wp = it.wp30;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp30mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
-                       wp = it.wp31;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp31mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
-                       }}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}
-               });
-       }
-}
-
-// queries the entire spawnfunc_waypoint network for pathes leading to the bot
-void navigation_markroutes_inverted(entity fixed_source_waypoint)
-{
-       float cost, cost2;
-       vector p;
-       IL_EACH(g_waypoints, true,
-       {
-               it.wpconsidered = false;
-               it.wpnearestpoint = '0 0 0';
-               it.wpcost = 10000000;
-               it.wpfire = 0;
-               it.enemy = NULL;
-       });
-
-       if(fixed_source_waypoint)
-       {
-               fixed_source_waypoint.wpconsidered = true;
-               fixed_source_waypoint.wpnearestpoint = fixed_source_waypoint.origin + 0.5 * (fixed_source_waypoint.mins + fixed_source_waypoint.maxs);
-               fixed_source_waypoint.wpcost = fixed_source_waypoint.dmg; // the cost to get from X to fixed_source_waypoint
-               fixed_source_waypoint.wpfire = 1;
-               fixed_source_waypoint.enemy = NULL;
-       }
-       else
-       {
-               error("need to start with a waypoint\n");
-       }
-
-       bool searching = true;
-       while (searching)
-       {
-               searching = false;
-               IL_EACH(g_waypoints, it.wpfire,
-               {
-                       searching = true;
-                       it.wpfire = 0;
-                       cost = it.wpcost; // cost to walk from it to home
-                       p = it.wpnearestpoint;
-                       entity wp = it;
-                       IL_EACH(g_waypoints, true,
-                       {
-                               if(wp != it.wp00) if(wp != it.wp01) if(wp != it.wp02) if(wp != it.wp03)
-                               if(wp != it.wp04) if(wp != it.wp05) if(wp != it.wp06) if(wp != it.wp07)
-                               if(wp != it.wp08) if(wp != it.wp09) if(wp != it.wp10) if(wp != it.wp11)
-                               if(wp != it.wp12) if(wp != it.wp13) if(wp != it.wp14) if(wp != it.wp15)
-                               if(wp != it.wp16) if(wp != it.wp17) if(wp != it.wp18) if(wp != it.wp19)
-                               if(wp != it.wp20) if(wp != it.wp21) if(wp != it.wp22) if(wp != it.wp23)
-                               if(wp != it.wp24) if(wp != it.wp25) if(wp != it.wp26) if(wp != it.wp27)
-                               if(wp != it.wp28) if(wp != it.wp29) if(wp != it.wp30) if(wp != it.wp31)
-                                       continue;
-                               cost2 = cost + it.dmg;
-                               navigation_markroutes_checkwaypoint(wp, it, cost2, p);
-                       });
-               });
-       }
-}
-
-// updates the best goal according to a weighted calculation of travel cost and item value of a new proposed item
-void navigation_routerating(entity this, entity e, float f, float rangebias)
-{
-       entity nwp;
-       vector o;
-       if (!e)
-               return;
-
-       if(e.blacklisted)
-               return;
-
-       o = (e.absmin + e.absmax) * 0.5;
-
-       //print("routerating ", etos(e), " = ", ftos(f), " - ", ftos(rangebias), "\n");
-
-       // Evaluate path using jetpack
-       if(g_jetpack)
-       if(this.items & IT_JETPACK)
-       if(autocvar_bot_ai_navigation_jetpack)
-       if(vdist(this.origin - o, >, autocvar_bot_ai_navigation_jetpack_mindistance))
-       {
-               vector pointa, pointb;
-
-               LOG_DEBUG("jetpack ai: evaluating path for ", e.classname, "\n");
-
-               // Point A
-               traceline(this.origin, this.origin + '0 0 65535', MOVE_NORMAL, this);
-               pointa = trace_endpos - '0 0 1';
-
-               // Point B
-               traceline(o, o + '0 0 65535', MOVE_NORMAL, e);
-               pointb = trace_endpos - '0 0 1';
-
-               // Can I see these two points from the sky?
-               traceline(pointa, pointb, MOVE_NORMAL, this);
-
-               if(trace_fraction==1)
-               {
-                       LOG_DEBUG("jetpack ai: can bridge these two points\n");
-
-                       // Lower the altitude of these points as much as possible
-                       float zdistance, xydistance, cost, t, fuel;
-                       vector down, npa, npb;
-
-                       down = '0 0 -1' * (STAT(PL_MAX, NULL).z - STAT(PL_MIN, NULL).z) * 10;
-
-                       do{
-                               npa = pointa + down;
-                               npb = pointb + down;
-
-                               if(npa.z<=this.absmax.z)
-                                       break;
-
-                               if(npb.z<=e.absmax.z)
-                                       break;
-
-                               traceline(npa, npb, MOVE_NORMAL, this);
-                               if(trace_fraction==1)
-                               {
-                                       pointa = npa;
-                                       pointb = npb;
-                               }
-                       }
-                       while(trace_fraction == 1);
-
-
-                       // Rough estimation of fuel consumption
-                       // (ignores acceleration and current xyz velocity)
-                       xydistance = vlen(pointa - pointb);
-                       zdistance = fabs(pointa.z - this.origin.z);
-
-                       t = zdistance / autocvar_g_jetpack_maxspeed_up;
-                       t += xydistance / autocvar_g_jetpack_maxspeed_side;
-                       fuel = t * autocvar_g_jetpack_fuel * 0.8;
-
-                       LOG_DEBUG(strcat("jetpack ai: required fuel ", ftos(fuel), " this.ammo_fuel ", ftos(this.ammo_fuel), "\n"));
-
-                       // enough fuel ?
-                       if(this.ammo_fuel>fuel)
-                       {
-                               // Estimate cost
-                               // (as onground costs calculation is mostly based on distances, here we do the same establishing some relationship
-                               //  - between air and ground speeds)
-
-                               cost = xydistance / (autocvar_g_jetpack_maxspeed_side/autocvar_sv_maxspeed);
-                               cost += zdistance / (autocvar_g_jetpack_maxspeed_up/autocvar_sv_maxspeed);
-                               cost *= 1.5;
-
-                               // Compare against other goals
-                               f = f * rangebias / (rangebias + cost);
-
-                               if (navigation_bestrating < f)
-                               {
-                                       LOG_DEBUG(strcat("jetpack path: added goal ", e.classname, " (with rating ", ftos(f), ")\n"));
-                                       navigation_bestrating = f;
-                                       navigation_bestgoal = e;
-                                       this.navigation_jetpack_goal = e;
-                                       this.navigation_jetpack_point = pointb;
-                               }
-                               return;
-                       }
-               }
-       }
-
-       //te_wizspike(e.origin);
-       //bprint(etos(e));
-       //bprint("\n");
-       // update the cached spawnfunc_waypoint link on a dynamic item entity
-       if(e.classname == "waypoint" && !(e.wpflags & WAYPOINTFLAG_PERSONAL))
-       {
-               nwp = e;
-       }
-       else
-       {
-               float search;
-
-               search = true;
-
-               if(e.flags & FL_ITEM)
-               {
-                       if (!(e.flags & FL_WEAPON))
-                       if(e.nearestwaypoint)
-                               search = false;
-               }
-               else if (e.flags & FL_WEAPON)
-               {
-                       if(e.classname != "droppedweapon")
-                       if(e.nearestwaypoint)
-                               search = false;
-               }
-
-               if(search)
-               if (time > e.nearestwaypointtimeout)
-               {
-                       nwp = navigation_findnearestwaypoint(e, true);
-                       if(nwp)
-                               e.nearestwaypoint = nwp;
-                       else
-                       {
-                               LOG_DEBUG(strcat("FAILED to find a nearest waypoint to '", e.classname, "' #", etos(e), "\n"));
-
-                               if(e.flags & FL_ITEM)
-                                       e.blacklisted = true;
-                               else if (e.flags & FL_WEAPON)
-                               {
-                                       if(e.classname != "droppedweapon")
-                                               e.blacklisted = true;
-                               }
-
-                               if(e.blacklisted)
-                               {
-                                       LOG_DEBUG(strcat("The entity '", e.classname, "' is going to be excluded from path finding during this match\n"));
-                                       return;
-                               }
-                       }
-
-                       // TODO: Cleaner solution, probably handling this timeout from ctf.qc
-                       if(e.classname=="item_flag_team")
-                               e.nearestwaypointtimeout = time + 2;
-                       else
-                               e.nearestwaypointtimeout = time + random() * 3 + 5;
-               }
-               nwp = e.nearestwaypoint;
-       }
-
-       LOG_DEBUG(strcat("-- checking ", e.classname, " (with cost ", ftos(nwp.wpcost), ")\n"));
-       if (nwp)
-       if (nwp.wpcost < 10000000)
-       {
-               //te_wizspike(nwp.wpnearestpoint);
-               LOG_DEBUG(strcat(e.classname, " ", ftos(f), "/(1+", ftos((nwp.wpcost + vlen(e.origin - nwp.wpnearestpoint))), "/", ftos(rangebias), ") = "));
-               f = f * rangebias / (rangebias + (nwp.wpcost + vlen(o - nwp.wpnearestpoint)));
-               LOG_DEBUG(strcat("considering ", e.classname, " (with rating ", ftos(f), ")\n"));
-               if (navigation_bestrating < f)
-               {
-                       LOG_DEBUG(strcat("ground path: added goal ", e.classname, " (with rating ", ftos(f), ")\n"));
-                       navigation_bestrating = f;
-                       navigation_bestgoal = e;
-               }
-       }
-}
-
-// adds an item to the the goal stack with the path to a given item
-bool navigation_routetogoal(entity this, entity e, vector startposition)
-{
-       this.goalentity = e;
-
-       // if there is no goal, just exit
-       if (!e)
-               return false;
-
-       this.navigation_hasgoals = true;
-
-       // put the entity on the goal stack
-       //print("routetogoal ", etos(e), "\n");
-       navigation_pushroute(this, e);
-
-       if(g_jetpack)
-       if(e==this.navigation_jetpack_goal)
-               return true;
-
-       // if it can reach the goal there is nothing more to do
-       if (tracewalk(this, startposition, STAT(PL_MIN, NULL), STAT(PL_MAX, NULL), (e.absmin + e.absmax) * 0.5, bot_navigation_movemode))
-               return true;
-
-       // see if there are waypoints describing a path to the item
-       if(e.classname != "waypoint" || (e.wpflags & WAYPOINTFLAG_PERSONAL))
-               e = e.nearestwaypoint;
-       else
-               e = e.enemy; // we already have added it, so...
-
-       if(e == NULL)
-               return false;
-
-       for (;;)
-       {
-               // add the spawnfunc_waypoint to the path
-               navigation_pushroute(this, e);
-               e = e.enemy;
-
-               if(e==NULL)
-                       break;
-       }
-
-       return false;
-}
-
-// removes any currently touching waypoints from the goal stack
-// (this is how bots detect if they reached a goal)
-void navigation_poptouchedgoals(entity this)
-{
-       vector org, m1, m2;
-       org = this.origin;
-       m1 = org + this.mins;
-       m2 = org + this.maxs;
-
-       if(this.goalcurrent.wpflags & WAYPOINTFLAG_TELEPORT)
-       {
-               if(this.lastteleporttime>0)
-               if(time-this.lastteleporttime<(this.goalcurrent.wpflags & WAYPOINTFLAG_PERSONAL)?2:0.15)
-               {
-                       if(this.aistatus & AI_STATUS_WAYPOINT_PERSONAL_GOING)
-                       if(this.goalcurrent.wpflags & WAYPOINTFLAG_PERSONAL && this.goalcurrent.owner==this)
-                       {
-                               this.aistatus &= ~AI_STATUS_WAYPOINT_PERSONAL_GOING;
-                               this.aistatus |= AI_STATUS_WAYPOINT_PERSONAL_REACHED;
-                       }
-                       navigation_poproute(this);
-                       return;
-               }
-       }
-
-       // If for some reason the bot is closer to the next goal, pop the current one
-       if(this.goalstack01)
-       if(vlen2(this.goalcurrent.origin - this.origin) > vlen2(this.goalstack01.origin - this.origin))
-       if(checkpvs(this.origin + this.view_ofs, this.goalstack01))
-       if(tracewalk(this, this.origin, this.mins, this.maxs, (this.goalstack01.absmin + this.goalstack01.absmax) * 0.5, bot_navigation_movemode))
-       {
-               LOG_DEBUG(strcat("path optimized for ", this.netname, ", removed a goal from the queue\n"));
-               navigation_poproute(this);
-               // TODO this may also be a nice idea to do "early" (e.g. by
-               // manipulating the vlen() comparisons) to shorten paths in
-               // general - this would make bots walk more "on rails" than
-               // "zigzagging" which they currently do with sufficiently
-               // random-like waypoints, and thus can make a nice bot
-               // personality property
-       }
-
-       // HACK: remove players/bots as goals, they can lead a bot to unexpected places (cliffs, lava, etc)
-       // TODO: rate waypoints near the targetted player at that moment, instead of the player itthis
-       if(IS_PLAYER(this.goalcurrent))
-               navigation_poproute(this);
-
-       // aid for detecting jump pads better (distance based check fails sometimes)
-       if(this.goalcurrent.wpflags & WAYPOINTFLAG_TELEPORT && this.jumppadcount > 0 )
-               navigation_poproute(this);
-
-       // Loose goal touching check when running
-       if(this.aistatus & AI_STATUS_RUNNING)
-       if(this.speed >= autocvar_sv_maxspeed) // if -really- running
-       if(this.goalcurrent.classname=="waypoint")
-       {
-               if(vdist(this.origin - this.goalcurrent.origin, <, 150))
-               {
-                       traceline(this.origin + this.view_ofs , this.goalcurrent.origin, true, NULL);
-                       if(trace_fraction==1)
-                       {
-                               // Detect personal waypoints
-                               if(this.aistatus & AI_STATUS_WAYPOINT_PERSONAL_GOING)
-                               if(this.goalcurrent.wpflags & WAYPOINTFLAG_PERSONAL && this.goalcurrent.owner==this)
-                               {
-                                       this.aistatus &= ~AI_STATUS_WAYPOINT_PERSONAL_GOING;
-                                       this.aistatus |= AI_STATUS_WAYPOINT_PERSONAL_REACHED;
-                               }
-
-                               navigation_poproute(this);
-                       }
-               }
-       }
-
-       while (this.goalcurrent && boxesoverlap(m1, m2, this.goalcurrent.absmin, this.goalcurrent.absmax))
-       {
-               // Detect personal waypoints
-               if(this.aistatus & AI_STATUS_WAYPOINT_PERSONAL_GOING)
-               if(this.goalcurrent.wpflags & WAYPOINTFLAG_PERSONAL && this.goalcurrent.owner==this)
-               {
-                       this.aistatus &= ~AI_STATUS_WAYPOINT_PERSONAL_GOING;
-                       this.aistatus |= AI_STATUS_WAYPOINT_PERSONAL_REACHED;
-               }
-
-               navigation_poproute(this);
-       }
-}
-
-// begin a goal selection session (queries spawnfunc_waypoint network)
-void navigation_goalrating_start(entity this)
-{
-       if(this.aistatus & AI_STATUS_STUCK)
-               return;
-
-       this.navigation_jetpack_goal = NULL;
-       navigation_bestrating = -1;
-       this.navigation_hasgoals = false;
-       navigation_clearroute(this);
-       navigation_bestgoal = NULL;
-       navigation_markroutes(this, NULL);
-}
-
-// ends a goal selection session (updates goal stack to the best goal)
-void navigation_goalrating_end(entity this)
-{
-       if(this.aistatus & AI_STATUS_STUCK)
-               return;
-
-       navigation_routetogoal(this, navigation_bestgoal, this.origin);
-       LOG_DEBUG(strcat("best goal ", this.goalcurrent.classname , "\n"));
-
-       // If the bot got stuck then try to reach the farthest waypoint
-       if (!this.navigation_hasgoals)
-       if (autocvar_bot_wander_enable)
-       {
-               if (!(this.aistatus & AI_STATUS_STUCK))
-               {
-                       LOG_DEBUG(strcat(this.netname, " cannot walk to any goal\n"));
-                       this.aistatus |= AI_STATUS_STUCK;
-               }
-
-               this.navigation_hasgoals = false; // Reset this value
-       }
-}
-
-void botframe_updatedangerousobjects(float maxupdate)
-{
-       vector m1, m2, v, o;
-       float c, d, danger;
-       c = 0;
-       IL_EACH(g_waypoints, true,
-       {
-               danger = 0;
-               m1 = it.mins;
-               m2 = it.maxs;
-               FOREACH_ENTITY_FLOAT(bot_dodge, true,
-               {
-                       v = it.origin;
-                       v.x = bound(m1_x, v.x, m2_x);
-                       v.y = bound(m1_y, v.y, m2_y);
-                       v.z = bound(m1_z, v.z, m2_z);
-                       o = (it.absmin + it.absmax) * 0.5;
-                       d = it.bot_dodgerating - vlen(o - v);
-                       if (d > 0)
-                       {
-                               traceline(o, v, true, NULL);
-                               if (trace_fraction == 1)
-                                       danger = danger + d;
-                       }
-               });
-               it.dmg = danger;
-               c = c + 1;
-               if (c >= maxupdate)
-                       break;
-       });
-}
-
-void navigation_unstuck(entity this)
-{
-       float search_radius = 1000;
-
-       if (!autocvar_bot_wander_enable)
-               return;
-
-       if (!bot_waypoint_queue_owner)
-       {
-               LOG_DEBUG(strcat(this.netname, " sutck, taking over the waypoints queue\n"));
-               bot_waypoint_queue_owner = this;
-               bot_waypoint_queue_bestgoal = NULL;
-               bot_waypoint_queue_bestgoalrating = 0;
-       }
-
-       if(bot_waypoint_queue_owner!=this)
-               return;
-
-       if (bot_waypoint_queue_goal)
-       {
-               // evaluate the next goal on the queue
-               float d = vlen(this.origin - bot_waypoint_queue_goal.origin);
-               LOG_DEBUG(strcat(this.netname, " evaluating ", bot_waypoint_queue_goal.classname, " with distance ", ftos(d), "\n"));
-               if(tracewalk(bot_waypoint_queue_goal, this.origin, STAT(PL_MIN, NULL), STAT(PL_MAX, NULL), bot_waypoint_queue_goal.origin, bot_navigation_movemode))
-               {
-                       if( d > bot_waypoint_queue_bestgoalrating)
-                       {
-                               bot_waypoint_queue_bestgoalrating = d;
-                               bot_waypoint_queue_bestgoal = bot_waypoint_queue_goal;
-                       }
-               }
-               bot_waypoint_queue_goal = bot_waypoint_queue_goal.bot_waypoint_queue_nextgoal;
-
-               if (!bot_waypoint_queue_goal)
-               {
-                       if (bot_waypoint_queue_bestgoal)
-                       {
-                               LOG_DEBUG(strcat(this.netname, " stuck, reachable waypoint found, heading to it\n"));
-                               navigation_routetogoal(this, bot_waypoint_queue_bestgoal, this.origin);
-                               this.bot_strategytime = time + autocvar_bot_ai_strategyinterval;
-                               this.aistatus &= ~AI_STATUS_STUCK;
-                       }
-                       else
-                       {
-                               LOG_DEBUG(strcat(this.netname, " stuck, cannot walk to any waypoint at all\n"));
-                       }
-
-                       bot_waypoint_queue_owner = NULL;
-               }
-       }
-       else
-       {
-               if(bot_strategytoken!=this)
-                       return;
-
-               // build a new queue
-               LOG_DEBUG(strcat(this.netname, " stuck, scanning reachable waypoints within ", ftos(search_radius)," qu\n"));
-
-               entity first = NULL;
-
-               FOREACH_ENTITY_RADIUS(this.origin, search_radius, it.classname == "waypoint" && !(it.wpflags & WAYPOINTFLAG_GENERATED),
-               {
-                       if(bot_waypoint_queue_goal)
-                               bot_waypoint_queue_goal.bot_waypoint_queue_nextgoal = it;
-                       else
-                               first = it;
-
-                       bot_waypoint_queue_goal = it;
-                       bot_waypoint_queue_goal.bot_waypoint_queue_nextgoal = NULL;
-               });
-
-               if (first)
-                       bot_waypoint_queue_goal = first;
-               else
-               {
-                       LOG_DEBUG(strcat(this.netname, " stuck, cannot walk to any waypoint at all\n"));
-                       bot_waypoint_queue_owner = NULL;
-               }
-       }
-}
-
-// Support for debugging tracewalk visually
-
-void debugresetnodes()
-{
-       debuglastnode = '0 0 0';
-}
-
-void debugnode(entity this, vector node)
-{
-       if (!IS_PLAYER(this))
-               return;
-
-       if(debuglastnode=='0 0 0')
-       {
-               debuglastnode = node;
-               return;
-       }
-
-       te_lightning2(NULL, node, debuglastnode);
-       debuglastnode = node;
-}
-
-void debugnodestatus(vector position, float status)
-{
-       vector c;
-
-       switch (status)
-       {
-               case DEBUG_NODE_SUCCESS:
-                       c = '0 15 0';
-                       break;
-               case DEBUG_NODE_WARNING:
-                       c = '15 15 0';
-                       break;
-               case DEBUG_NODE_FAIL:
-                       c = '15 0 0';
-                       break;
-               default:
-                       c = '15 15 15';
-       }
-
-       te_customflash(position, 40,  2, c);
-}
-
-// Support for debugging the goal stack visually
-
-.float goalcounter;
-.vector lastposition;
-
-// Debug the goal stack visually
-void debuggoalstack(entity this)
-{
-       entity goal;
-       vector org, go;
-
-       if(this.goalcounter==0)goal=this.goalcurrent;
-       else if(this.goalcounter==1)goal=this.goalstack01;
-       else if(this.goalcounter==2)goal=this.goalstack02;
-       else if(this.goalcounter==3)goal=this.goalstack03;
-       else if(this.goalcounter==4)goal=this.goalstack04;
-       else if(this.goalcounter==5)goal=this.goalstack05;
-       else if(this.goalcounter==6)goal=this.goalstack06;
-       else if(this.goalcounter==7)goal=this.goalstack07;
-       else if(this.goalcounter==8)goal=this.goalstack08;
-       else if(this.goalcounter==9)goal=this.goalstack09;
-       else if(this.goalcounter==10)goal=this.goalstack10;
-       else if(this.goalcounter==11)goal=this.goalstack11;
-       else if(this.goalcounter==12)goal=this.goalstack12;
-       else if(this.goalcounter==13)goal=this.goalstack13;
-       else if(this.goalcounter==14)goal=this.goalstack14;
-       else if(this.goalcounter==15)goal=this.goalstack15;
-       else if(this.goalcounter==16)goal=this.goalstack16;
-       else if(this.goalcounter==17)goal=this.goalstack17;
-       else if(this.goalcounter==18)goal=this.goalstack18;
-       else if(this.goalcounter==19)goal=this.goalstack19;
-       else if(this.goalcounter==20)goal=this.goalstack20;
-       else if(this.goalcounter==21)goal=this.goalstack21;
-       else if(this.goalcounter==22)goal=this.goalstack22;
-       else if(this.goalcounter==23)goal=this.goalstack23;
-       else if(this.goalcounter==24)goal=this.goalstack24;
-       else if(this.goalcounter==25)goal=this.goalstack25;
-       else if(this.goalcounter==26)goal=this.goalstack26;
-       else if(this.goalcounter==27)goal=this.goalstack27;
-       else if(this.goalcounter==28)goal=this.goalstack28;
-       else if(this.goalcounter==29)goal=this.goalstack29;
-       else if(this.goalcounter==30)goal=this.goalstack30;
-       else if(this.goalcounter==31)goal=this.goalstack31;
-       else goal=NULL;
-
-       if(goal==NULL)
-       {
-               this.goalcounter = 0;
-               this.lastposition='0 0 0';
-               return;
-       }
-
-       if(this.lastposition=='0 0 0')
-               org = this.origin;
-       else
-               org = this.lastposition;
-
-
-       go = ( goal.absmin + goal.absmax ) * 0.5;
-       te_lightning2(NULL, org, go);
-       this.lastposition = go;
-
-       this.goalcounter++;
-}
diff --git a/qcsrc/server/bot/navigation.qh b/qcsrc/server/bot/navigation.qh
deleted file mode 100644 (file)
index ad01776..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-#pragma once
-/*
- * Globals and Fields
- */
-
-float navigation_bestrating;
-float bot_navigation_movemode;
-float navigation_testtracewalk;
-
-vector jumpstepheightvec;
-vector stepheightvec;
-
-entity navigation_bestgoal;
-
-// stack of current goals (the last one of which may be an item or other
-// desirable object, the rest are typically waypoints to reach it)
-.entity goalcurrent, goalstack01, goalstack02, goalstack03;
-.entity goalstack04, goalstack05, goalstack06, goalstack07;
-.entity goalstack08, goalstack09, goalstack10, goalstack11;
-.entity goalstack12, goalstack13, goalstack14, goalstack15;
-.entity goalstack16, goalstack17, goalstack18, goalstack19;
-.entity goalstack20, goalstack21, goalstack22, goalstack23;
-.entity goalstack24, goalstack25, goalstack26, goalstack27;
-.entity goalstack28, goalstack29, goalstack30, goalstack31;
-.entity nearestwaypoint;
-
-.float nearestwaypointtimeout;
-.float navigation_hasgoals;
-.float lastteleporttime;
-
-.float blacklisted;
-
-.entity navigation_jetpack_goal;
-.vector navigation_jetpack_point;
-
-const float DEBUG_NODE_SUCCESS        = 1;
-const float DEBUG_NODE_WARNING        = 2;
-const float DEBUG_NODE_FAIL           = 3;
-vector debuglastnode;
-
-entity bot_waypoint_queue_owner;       // Owner of the temporary list of goals
-entity bot_waypoint_queue_goal;                // Head of the temporary list of goals
-.entity bot_waypoint_queue_nextgoal;
-entity bot_waypoint_queue_bestgoal;
-float bot_waypoint_queue_bestgoalrating;
-
-/*
- * Functions
- */
-
-void debugresetnodes();
-void debugnode(entity this, vector node);
-void debugnodestatus(vector position, float status);
-
-void debuggoalstack(entity this);
-
-float tracewalk(entity e, vector start, vector m1, vector m2, vector end, float movemode);
-
-float navigation_markroutes_nearestwaypoints(entity this, float maxdist);
-float navigation_routetogoal(entity this, entity e, vector startposition);
-
-void navigation_clearroute(entity this);
-void navigation_pushroute(entity this, entity e);
-void navigation_poproute(entity this);
-void navigation_markroutes_checkwaypoint(entity w, entity wp, float cost2, vector p);
-void navigation_markroutes(entity this, entity fixed_source_waypoint);
-void navigation_markroutes_inverted(entity fixed_source_waypoint);
-void navigation_routerating(entity this, entity e, float f, float rangebias);
-void navigation_poptouchedgoals(entity this);
-void navigation_goalrating_start(entity this);
-void navigation_goalrating_end(entity this);
-void navigation_unstuck(entity this);
-
-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);
diff --git a/qcsrc/server/bot/scripting.qc b/qcsrc/server/bot/scripting.qc
deleted file mode 100644 (file)
index 291b22f..0000000
+++ /dev/null
@@ -1,1340 +0,0 @@
-#include "scripting.qh"
-
-#include <common/state.qh>
-#include <common/physics/player.qh>
-
-#include "bot.qh"
-
-.int state;
-
-.float bot_cmdqueuebuf_allocated;
-.float bot_cmdqueuebuf;
-.float bot_cmdqueuebuf_start;
-.float bot_cmdqueuebuf_end;
-
-void bot_clearqueue(entity bot)
-{
-       if(!bot.bot_cmdqueuebuf_allocated)
-               return;
-       buf_del(bot.bot_cmdqueuebuf);
-       bot.bot_cmdqueuebuf_allocated = false;
-       LOG_TRACE("bot ", bot.netname, " queue cleared\n");
-}
-
-void bot_queuecommand(entity bot, string cmdstring)
-{
-       if(!bot.bot_cmdqueuebuf_allocated)
-       {
-               bot.bot_cmdqueuebuf = buf_create();
-               bot.bot_cmdqueuebuf_allocated = true;
-               bot.bot_cmdqueuebuf_start = 0;
-               bot.bot_cmdqueuebuf_end = 0;
-       }
-
-       bufstr_set(bot.bot_cmdqueuebuf, bot.bot_cmdqueuebuf_end, cmdstring);
-
-       // if the command was a "sound" command, precache the sound NOW
-       // this prevents lagging!
-       {
-               float sp;
-               string parm;
-               string cmdstr;
-
-               sp = strstrofs(cmdstring, " ", 0);
-               if(sp >= 0)
-               {
-                       parm = substring(cmdstring, sp + 1, -1);
-                       cmdstr = substring(cmdstring, 0, sp);
-                       if(cmdstr == "sound")
-                       {
-                               // find the LAST word
-                               for (;;)
-                               {
-                                       sp = strstrofs(parm, " ", 0);
-                                       if(sp < 0)
-                                               break;
-                                       parm = substring(parm, sp + 1, -1);
-                               }
-                               precache_sound(parm);
-                       }
-               }
-       }
-
-       bot.bot_cmdqueuebuf_end += 1;
-}
-
-void bot_dequeuecommand(entity bot, float idx)
-{
-       if(!bot.bot_cmdqueuebuf_allocated)
-               error("dequeuecommand but no queue allocated");
-       if(idx < bot.bot_cmdqueuebuf_start)
-               error("dequeueing a command in the past");
-       if(idx >= bot.bot_cmdqueuebuf_end)
-               error("dequeueing a command in the future");
-       bufstr_set(bot.bot_cmdqueuebuf, idx, "");
-       if(idx == bot.bot_cmdqueuebuf_start)
-               bot.bot_cmdqueuebuf_start += 1;
-       if(bot.bot_cmdqueuebuf_start >= bot.bot_cmdqueuebuf_end)
-               bot_clearqueue(bot);
-}
-
-string bot_readcommand(entity bot, float idx)
-{
-       if(!bot.bot_cmdqueuebuf_allocated)
-               error("readcommand but no queue allocated");
-       if(idx < bot.bot_cmdqueuebuf_start)
-               error("reading a command in the past");
-       if(idx >= bot.bot_cmdqueuebuf_end)
-               error("reading a command in the future");
-       return bufstr_get(bot.bot_cmdqueuebuf, idx);
-}
-
-bool bot_havecommand(entity this, int idx)
-{
-       if(!this.bot_cmdqueuebuf_allocated)
-               return false;
-       if(idx < this.bot_cmdqueuebuf_start)
-               return false;
-       if(idx >= this.bot_cmdqueuebuf_end)
-               return false;
-       return true;
-}
-
-const int MAX_BOT_PLACES = 4;
-.float bot_places_count;
-.entity bot_places[MAX_BOT_PLACES];
-.string bot_placenames[MAX_BOT_PLACES];
-entity bot_getplace(entity this, string placename)
-{
-       entity e;
-       if(substring(placename, 0, 1) == "@")
-       {
-               int i, p;
-               placename = substring(placename, 1, -1);
-               string s, s2;
-               for(i = 0; i < this.bot_places_count; ++i)
-                       if(this.(bot_placenames[i]) == placename)
-                               return this.(bot_places[i]);
-               // now: i == this.bot_places_count
-               s = s2 = cvar_string(placename);
-               p = strstrofs(s2, " ", 0);
-               if(p >= 0)
-               {
-                       s = substring(s2, 0, p);
-                       //print("places: ", placename, " -> ", cvar_string(placename), "\n");
-                       cvar_set(placename, strcat(substring(s2, p+1, -1), " ", s));
-                       //print("places: ", placename, " := ", cvar_string(placename), "\n");
-               }
-               e = find(NULL, targetname, s);
-               if(!e)
-                       LOG_INFO("invalid place ", s, "\n");
-               if(i < MAX_BOT_PLACES)
-               {
-                       this.(bot_placenames[i]) = strzone(placename);
-                       this.(bot_places[i]) = e;
-                       this.bot_places_count += 1;
-               }
-               return e;
-       }
-       else
-       {
-               e = find(NULL, targetname, placename);
-               if(!e)
-                       LOG_INFO("invalid place ", placename, "\n");
-               return e;
-       }
-}
-
-
-// Initialize global commands list
-// NOTE: New commands should be initialized here
-void bot_commands_init()
-{
-       bot_cmd_string[BOT_CMD_NULL] = "";
-       bot_cmd_parm_type[BOT_CMD_NULL] = BOT_CMD_PARAMETER_NONE;
-
-       bot_cmd_string[BOT_CMD_PAUSE] = "pause";
-       bot_cmd_parm_type[BOT_CMD_PAUSE] = BOT_CMD_PARAMETER_NONE;
-
-       bot_cmd_string[BOT_CMD_CONTINUE] = "continue";
-       bot_cmd_parm_type[BOT_CMD_CONTINUE] = BOT_CMD_PARAMETER_NONE;
-
-       bot_cmd_string[BOT_CMD_WAIT] = "wait";
-       bot_cmd_parm_type[BOT_CMD_WAIT] = BOT_CMD_PARAMETER_FLOAT;
-
-       bot_cmd_string[BOT_CMD_TURN] = "turn";
-       bot_cmd_parm_type[BOT_CMD_TURN] = BOT_CMD_PARAMETER_FLOAT;
-
-       bot_cmd_string[BOT_CMD_MOVETO] = "moveto";
-       bot_cmd_parm_type[BOT_CMD_MOVETO] = BOT_CMD_PARAMETER_VECTOR;
-
-       bot_cmd_string[BOT_CMD_MOVETOTARGET] = "movetotarget";
-       bot_cmd_parm_type[BOT_CMD_MOVETOTARGET] = BOT_CMD_PARAMETER_STRING;
-
-       bot_cmd_string[BOT_CMD_RESETGOAL] = "resetgoal";
-       bot_cmd_parm_type[BOT_CMD_RESETGOAL] = BOT_CMD_PARAMETER_NONE;
-
-       bot_cmd_string[BOT_CMD_CC] = "cc";
-       bot_cmd_parm_type[BOT_CMD_CC] = BOT_CMD_PARAMETER_STRING;
-
-       bot_cmd_string[BOT_CMD_IF] = "if";
-       bot_cmd_parm_type[BOT_CMD_IF] = BOT_CMD_PARAMETER_STRING;
-
-       bot_cmd_string[BOT_CMD_ELSE] = "else";
-       bot_cmd_parm_type[BOT_CMD_ELSE] = BOT_CMD_PARAMETER_NONE;
-
-       bot_cmd_string[BOT_CMD_FI] = "fi";
-       bot_cmd_parm_type[BOT_CMD_FI] = BOT_CMD_PARAMETER_NONE;
-
-       bot_cmd_string[BOT_CMD_RESETAIM] = "resetaim";
-       bot_cmd_parm_type[BOT_CMD_RESETAIM] = BOT_CMD_PARAMETER_NONE;
-
-       bot_cmd_string[BOT_CMD_AIM] = "aim";
-       bot_cmd_parm_type[BOT_CMD_AIM] = BOT_CMD_PARAMETER_STRING;
-
-       bot_cmd_string[BOT_CMD_AIMTARGET] = "aimtarget";
-       bot_cmd_parm_type[BOT_CMD_AIMTARGET] = BOT_CMD_PARAMETER_STRING;
-
-       bot_cmd_string[BOT_CMD_PRESSKEY] = "presskey";
-       bot_cmd_parm_type[BOT_CMD_PRESSKEY] = BOT_CMD_PARAMETER_STRING;
-
-       bot_cmd_string[BOT_CMD_RELEASEKEY] = "releasekey";
-       bot_cmd_parm_type[BOT_CMD_RELEASEKEY] = BOT_CMD_PARAMETER_STRING;
-
-       bot_cmd_string[BOT_CMD_SELECTWEAPON] = "selectweapon";
-       bot_cmd_parm_type[BOT_CMD_SELECTWEAPON] = BOT_CMD_PARAMETER_FLOAT;
-
-       bot_cmd_string[BOT_CMD_IMPULSE] = "impulse";
-       bot_cmd_parm_type[BOT_CMD_IMPULSE] = BOT_CMD_PARAMETER_FLOAT;
-
-       bot_cmd_string[BOT_CMD_WAIT_UNTIL] = "wait_until";
-       bot_cmd_parm_type[BOT_CMD_WAIT_UNTIL] = BOT_CMD_PARAMETER_FLOAT;
-
-       bot_cmd_string[BOT_CMD_BARRIER] = "barrier";
-       bot_cmd_parm_type[BOT_CMD_BARRIER] = BOT_CMD_PARAMETER_NONE;
-
-       bot_cmd_string[BOT_CMD_CONSOLE] = "console";
-       bot_cmd_parm_type[BOT_CMD_CONSOLE] = BOT_CMD_PARAMETER_STRING;
-
-       bot_cmd_string[BOT_CMD_SOUND] = "sound";
-       bot_cmd_parm_type[BOT_CMD_SOUND] = BOT_CMD_PARAMETER_STRING;
-
-       bot_cmd_string[BOT_CMD_DEBUG_ASSERT_CANFIRE] = "debug_assert_canfire";
-       bot_cmd_parm_type[BOT_CMD_DEBUG_ASSERT_CANFIRE] = BOT_CMD_PARAMETER_FLOAT;
-
-       bot_cmds_initialized = true;
-}
-
-// Returns first bot with matching name
-entity find_bot_by_name(string name)
-{
-       entity bot;
-
-       bot = findchainflags(flags, FL_CLIENT);
-       while (bot)
-       {
-               if(IS_BOT_CLIENT(bot))
-               if(bot.netname==name)
-                       return bot;
-
-               bot = bot.chain;
-       }
-
-       return NULL;
-}
-
-// Returns a bot by number on list
-entity find_bot_by_number(float number)
-{
-       entity bot;
-       float c = 0;
-
-       if(!number)
-               return NULL;
-
-       bot = findchainflags(flags, FL_CLIENT); // TODO: doesn't findchainflags loop backwards through entities?
-       while (bot)
-       {
-               if(IS_BOT_CLIENT(bot))
-               {
-                       if(++c==number)
-                               return bot;
-               }
-               bot = bot.chain;
-       }
-
-       return NULL;
-}
-
-float bot_decodecommand(string cmdstring)
-{
-       float cmd_parm_type;
-       float sp;
-       string parm;
-
-       sp = strstrofs(cmdstring, " ", 0);
-       if(sp < 0)
-       {
-               parm = "";
-       }
-       else
-       {
-               parm = substring(cmdstring, sp + 1, -1);
-               cmdstring = substring(cmdstring, 0, sp);
-       }
-
-       if(!bot_cmds_initialized)
-               bot_commands_init();
-
-       int i;
-       for(i=1;i<BOT_CMD_COUNTER;++i)
-       {
-               if(bot_cmd_string[i]!=cmdstring)
-                       continue;
-
-               cmd_parm_type = bot_cmd_parm_type[i];
-
-               if(cmd_parm_type!=BOT_CMD_PARAMETER_NONE&&parm=="")
-               {
-                       LOG_INFO("ERROR: A parameter is required for this command\n");
-                       return 0;
-               }
-
-               // Load command into queue
-               bot_cmd.bot_cmd_type = i;
-
-               // Attach parameter
-               switch(cmd_parm_type)
-               {
-                       case BOT_CMD_PARAMETER_FLOAT:
-                               bot_cmd.bot_cmd_parm_float = stof(parm);
-                               break;
-                       case BOT_CMD_PARAMETER_STRING:
-                               if(bot_cmd.bot_cmd_parm_string)
-                                       strunzone(bot_cmd.bot_cmd_parm_string);
-                               bot_cmd.bot_cmd_parm_string = strzone(parm);
-                               break;
-                       case BOT_CMD_PARAMETER_VECTOR:
-                               bot_cmd.bot_cmd_parm_vector = stov(parm);
-                               break;
-                       default:
-                               break;
-               }
-               return 1;
-       }
-       LOG_INFO("ERROR: No such command '", cmdstring, "'\n");
-       return 0;
-}
-
-void bot_cmdhelp(string scmd)
-{
-       int i, ntype;
-       string stype;
-
-       if(!bot_cmds_initialized)
-               bot_commands_init();
-
-       for(i=1;i<BOT_CMD_COUNTER;++i)
-       {
-               if(bot_cmd_string[i]!=scmd)
-                       continue;
-
-               ntype = bot_cmd_parm_type[i];
-
-               switch(ntype)
-               {
-                       case BOT_CMD_PARAMETER_FLOAT:
-                               stype = "float number";
-                               break;
-                       case BOT_CMD_PARAMETER_STRING:
-                               stype = "string";
-                               break;
-                       case BOT_CMD_PARAMETER_VECTOR:
-                               stype = "vector";
-                               break;
-                       default:
-                               stype = "none";
-                               break;
-               }
-
-               LOG_INFO(strcat("Command: ",bot_cmd_string[i],"\nParameter: <",stype,"> \n"));
-
-               LOG_INFO("Description: ");
-               switch(i)
-               {
-                       case BOT_CMD_PAUSE:
-                               LOG_INFO("Stops the bot completely. Any command other than 'continue' will be ignored.");
-                               break;
-                       case BOT_CMD_CONTINUE:
-                               LOG_INFO("Disable paused status");
-                               break;
-                       case BOT_CMD_WAIT:
-                               LOG_INFO("Pause command parsing and bot ai for N seconds. Pressed key will remain pressed");
-                               break;
-                       case BOT_CMD_WAIT_UNTIL:
-                               LOG_INFO("Pause command parsing and bot ai until time is N from the last barrier. Pressed key will remain pressed");
-                               break;
-                       case BOT_CMD_BARRIER:
-                               LOG_INFO("Waits till all bots that have a command queue reach this command. Pressed key will remain pressed");
-                               break;
-                       case BOT_CMD_TURN:
-                               LOG_INFO("Look to the right or left N degrees. For turning to the left use positive numbers.");
-                               break;
-                       case BOT_CMD_MOVETO:
-                               LOG_INFO("Walk to an specific coordinate on the map. Usage: moveto \"x y z\"");
-                               break;
-                       case BOT_CMD_MOVETOTARGET:
-                               LOG_INFO("Walk to the specific target on the map");
-                               break;
-                       case BOT_CMD_RESETGOAL:
-                               LOG_INFO("Resets the goal stack");
-                               break;
-                       case BOT_CMD_CC:
-                               LOG_INFO("Execute client command. Examples: cc \"say something\"; cc god; cc \"name newnickname\"; cc kill;");
-                               break;
-                       case BOT_CMD_IF:
-                               LOG_INFO("Perform simple conditional execution.\n");
-                               LOG_INFO("Syntax: \n");
-                               LOG_INFO("        sv_cmd .. if \"condition\"\n");
-                               LOG_INFO("        sv_cmd ..     <instruction if true>\n");
-                               LOG_INFO("        sv_cmd ..     <instruction if true>\n");
-                               LOG_INFO("        sv_cmd .. else\n");
-                               LOG_INFO("        sv_cmd ..     <instruction if false>\n");
-                               LOG_INFO("        sv_cmd ..     <instruction if false>\n");
-                               LOG_INFO("        sv_cmd .. fi\n");
-                               LOG_INFO("Conditions: a=b, a>b, a<b, a\t\t(spaces not allowed)\n");
-                               LOG_INFO("            Values in conditions can be numbers, cvars in the form cvar.cvar_string or special fields\n");
-                               LOG_INFO("Fields: health, speed, flagcarrier\n");
-                               LOG_INFO("Examples: if health>50; if health>cvar.g_balance_laser_primary_damage; if flagcarrier;");
-                               break;
-                       case BOT_CMD_RESETAIM:
-                               LOG_INFO("Points the aim to the coordinates x,y 0,0");
-                               break;
-                       case BOT_CMD_AIM:
-                               LOG_INFO("Move the aim x/y (horizontal/vertical) degrees relatives to the bot\n");
-                               LOG_INFO("There is a 3rd optional parameter telling in how many seconds the aim has to reach the new position\n");
-                               LOG_INFO("Examples: aim \"90 0\"        // Turn 90 degrees inmediately (positive numbers move to the left/up)\n");
-                               LOG_INFO("          aim \"0 90 2\"      // Will gradually look to the sky in the next two seconds");
-                               break;
-                       case BOT_CMD_AIMTARGET:
-                               LOG_INFO("Points the aim to given target");
-                               break;
-                       case BOT_CMD_PRESSKEY:
-                               LOG_INFO("Press one of the following keys: forward, backward, left, right, jump, crouch, attack1, attack2, use\n");
-                               LOG_INFO("Multiple keys can be pressed at time (with many presskey calls) and it will remain pressed until the command \"releasekey\" is called");
-                               LOG_INFO("Note: The script will not return the control to the bot ai until all keys are released");
-                               break;
-                       case BOT_CMD_RELEASEKEY:
-                               LOG_INFO("Release previoulsy used keys. Use the parameter \"all\" to release all keys");
-                               break;
-                       case BOT_CMD_SOUND:
-                               LOG_INFO("play sound file at bot location");
-                               break;
-                       case BOT_CMD_DEBUG_ASSERT_CANFIRE:
-                               LOG_INFO("verify the state of the weapon entity");
-                               break;
-                       default:
-                               LOG_INFO("This command has no description yet.");
-                               break;
-               }
-               LOG_INFO("\n");
-       }
-}
-
-void bot_list_commands()
-{
-       int i;
-       string ptype;
-
-       if(!bot_cmds_initialized)
-               bot_commands_init();
-
-       LOG_INFO("List of all available commands:\n");
-       LOG_INFO("  Command - Parameter Type\n");
-
-       for(i=1;i<BOT_CMD_COUNTER;++i)
-       {
-               switch(bot_cmd_parm_type[i])
-               {
-                       case BOT_CMD_PARAMETER_FLOAT:
-                               ptype = "float number";
-                               break;
-                       case BOT_CMD_PARAMETER_STRING:
-                               ptype = "string";
-                               break;
-                       case BOT_CMD_PARAMETER_VECTOR:
-                               ptype = "vector";
-                               break;
-                       default:
-                               ptype = "none";
-                               break;
-               }
-               LOG_INFO(strcat("  ",bot_cmd_string[i]," - <",ptype,"> \n"));
-       }
-}
-
-// Commands code
-.int bot_exec_status;
-
-float bot_cmd_cc(entity this)
-{
-       SV_ParseClientCommand(this, bot_cmd.bot_cmd_parm_string);
-       return CMD_STATUS_FINISHED;
-}
-
-float bot_cmd_impulse(entity this)
-{
-       this.impulse = bot_cmd.bot_cmd_parm_float;
-       return CMD_STATUS_FINISHED;
-}
-
-float bot_cmd_continue(entity this)
-{
-       this.bot_exec_status &= ~BOT_EXEC_STATUS_PAUSED;
-       return CMD_STATUS_FINISHED;
-}
-
-.float bot_cmd_wait_time;
-float bot_cmd_wait(entity this)
-{
-       if(this.bot_exec_status & BOT_EXEC_STATUS_WAITING)
-       {
-               if(time>=this.bot_cmd_wait_time)
-               {
-                       this.bot_exec_status &= ~BOT_EXEC_STATUS_WAITING;
-                       return CMD_STATUS_FINISHED;
-               }
-               else
-                       return CMD_STATUS_EXECUTING;
-       }
-
-       this.bot_cmd_wait_time = time + bot_cmd.bot_cmd_parm_float;
-       this.bot_exec_status |= BOT_EXEC_STATUS_WAITING;
-       return CMD_STATUS_EXECUTING;
-}
-
-float bot_cmd_wait_until(entity this)
-{
-       if(time < bot_cmd.bot_cmd_parm_float + bot_barriertime)
-       {
-               this.bot_exec_status |= BOT_EXEC_STATUS_WAITING;
-               return CMD_STATUS_EXECUTING;
-       }
-       this.bot_exec_status &= ~BOT_EXEC_STATUS_WAITING;
-       return CMD_STATUS_FINISHED;
-}
-
-float bot_cmd_barrier(entity this)
-{
-       // 0 = no barrier, 1 = waiting, 2 = waiting finished
-
-       if(this.bot_barrier == 0) // initialization
-       {
-               this.bot_barrier = 1;
-
-               //this.colormod = '4 4 0';
-       }
-
-       if(this.bot_barrier == 1) // find other bots
-       {
-               FOREACH_CLIENT(it.isbot, LAMBDA(
-                       if(it.bot_cmdqueuebuf_allocated)
-                       if(it.bot_barrier != 1)
-                               return CMD_STATUS_EXECUTING; // not all are at the barrier yet
-               ));
-
-               // all bots hit the barrier!
-
-               // acknowledge barrier
-               FOREACH_CLIENT(it.isbot, LAMBDA(it.bot_barrier = 2));
-
-               bot_barriertime = time;
-       }
-
-       // if we get here, the barrier is finished
-       // so end it...
-       this.bot_barrier = 0;
-       //this.colormod = '0 0 0';
-
-       return CMD_STATUS_FINISHED;
-}
-
-float bot_cmd_turn(entity this)
-{
-       this.v_angle_y = this.v_angle.y + bot_cmd.bot_cmd_parm_float;
-       this.v_angle_y = this.v_angle.y - floor(this.v_angle.y / 360) * 360;
-       return CMD_STATUS_FINISHED;
-}
-
-float bot_cmd_select_weapon(entity this)
-{
-       float id = bot_cmd.bot_cmd_parm_float;
-
-       if(id < WEP_FIRST || id > WEP_LAST)
-               return CMD_STATUS_ERROR;
-
-       if(client_hasweapon(this, Weapons_from(id), true, false))
-               PS(this).m_switchweapon = Weapons_from(id);
-       else
-               return CMD_STATUS_ERROR;
-
-       return CMD_STATUS_FINISHED;
-}
-
-.int bot_cmd_condition_status;
-
-const int CMD_CONDITION_NONE = 0;
-const int CMD_CONDITION_true = 1;
-const int CMD_CONDITION_false = 2;
-const int CMD_CONDITION_true_BLOCK = 4;
-const int CMD_CONDITION_false_BLOCK = 8;
-
-float bot_cmd_eval(entity this, string expr)
-{
-       // Search for numbers
-       if(strstrofs("0123456789", substring(expr, 0, 1), 0) >= 0)
-       {
-               return stof(expr);
-       }
-
-       // Search for cvars
-       if(substring(expr, 0, 5)=="cvar.")
-       {
-               return cvar(substring(expr, 5, strlen(expr)));
-       }
-
-       // Search for fields
-       switch(expr)
-       {
-               case "health":
-                       return this.health;
-               case "speed":
-                       return vlen(this.velocity);
-               case "flagcarrier":
-                       return ((this.flagcarried!=NULL));
-       }
-
-       LOG_INFO(strcat("ERROR: Unable to convert the expression '",expr,"' into a numeric value\n"));
-       return 0;
-}
-
-float bot_cmd_if(entity this)
-{
-       string expr, val_a, val_b;
-       float cmpofs;
-
-       if(this.bot_cmd_condition_status != CMD_CONDITION_NONE)
-       {
-               // Only one "if" block is allowed at time
-               LOG_INFO("ERROR: Only one conditional block can be processed at time");
-               bot_clearqueue(this);
-               return CMD_STATUS_ERROR;
-       }
-
-       this.bot_cmd_condition_status |= CMD_CONDITION_true_BLOCK;
-
-       // search for operators
-       expr = bot_cmd.bot_cmd_parm_string;
-
-       cmpofs = strstrofs(expr,"=",0);
-
-       if(cmpofs>0)
-       {
-               val_a = substring(expr,0,cmpofs);
-               val_b = substring(expr,cmpofs+1,strlen(expr));
-
-               if(bot_cmd_eval(this, val_a)==bot_cmd_eval(this, val_b))
-                       this.bot_cmd_condition_status |= CMD_CONDITION_true;
-               else
-                       this.bot_cmd_condition_status |= CMD_CONDITION_false;
-
-               return CMD_STATUS_FINISHED;
-       }
-
-       cmpofs = strstrofs(expr,">",0);
-
-       if(cmpofs>0)
-       {
-               val_a = substring(expr,0,cmpofs);
-               val_b = substring(expr,cmpofs+1,strlen(expr));
-
-               if(bot_cmd_eval(this, val_a)>bot_cmd_eval(this, val_b))
-                       this.bot_cmd_condition_status |= CMD_CONDITION_true;
-               else
-                       this.bot_cmd_condition_status |= CMD_CONDITION_false;
-
-               return CMD_STATUS_FINISHED;
-       }
-
-       cmpofs = strstrofs(expr,"<",0);
-
-       if(cmpofs>0)
-       {
-               val_a = substring(expr,0,cmpofs);
-               val_b = substring(expr,cmpofs+1,strlen(expr));
-
-               if(bot_cmd_eval(this, val_a)<bot_cmd_eval(this, val_b))
-                       this.bot_cmd_condition_status |= CMD_CONDITION_true;
-               else
-                       this.bot_cmd_condition_status |= CMD_CONDITION_false;
-
-               return CMD_STATUS_FINISHED;
-       }
-
-       if(bot_cmd_eval(this, expr))
-               this.bot_cmd_condition_status |= CMD_CONDITION_true;
-       else
-               this.bot_cmd_condition_status |= CMD_CONDITION_false;
-
-       return CMD_STATUS_FINISHED;
-}
-
-float bot_cmd_else(entity this)
-{
-       this.bot_cmd_condition_status &= ~CMD_CONDITION_true_BLOCK;
-       this.bot_cmd_condition_status |= CMD_CONDITION_false_BLOCK;
-       return CMD_STATUS_FINISHED;
-}
-
-float bot_cmd_fi(entity this)
-{
-       this.bot_cmd_condition_status = CMD_CONDITION_NONE;
-       return CMD_STATUS_FINISHED;
-}
-
-float bot_cmd_resetaim(entity this)
-{
-       this.v_angle = '0 0 0';
-       return CMD_STATUS_FINISHED;
-}
-
-.float bot_cmd_aim_begintime;
-.float bot_cmd_aim_endtime;
-.vector bot_cmd_aim_begin;
-.vector bot_cmd_aim_end;
-
-float bot_cmd_aim(entity this)
-{
-       // Current direction
-       if(this.bot_cmd_aim_endtime)
-       {
-               float progress;
-
-               progress = min(1 - (this.bot_cmd_aim_endtime - time) / (this.bot_cmd_aim_endtime - this.bot_cmd_aim_begintime),1);
-               this.v_angle = this.bot_cmd_aim_begin + ((this.bot_cmd_aim_end - this.bot_cmd_aim_begin) * progress);
-
-               if(time>=this.bot_cmd_aim_endtime)
-               {
-                       this.bot_cmd_aim_endtime = 0;
-                       return CMD_STATUS_FINISHED;
-               }
-               else
-                       return CMD_STATUS_EXECUTING;
-       }
-
-       // New aiming direction
-       string parms;
-       float tokens, step;
-
-       parms = bot_cmd.bot_cmd_parm_string;
-
-       tokens = tokenizebyseparator(parms, " ");
-
-       if(tokens<2||tokens>3)
-               return CMD_STATUS_ERROR;
-
-       step = (tokens == 3) ? stof(argv(2)) : 0;
-
-       if(step == 0)
-       {
-               this.v_angle_x -= stof(argv(1));
-               this.v_angle_y += stof(argv(0));
-               return CMD_STATUS_FINISHED;
-       }
-
-       this.bot_cmd_aim_begin = this.v_angle;
-
-       this.bot_cmd_aim_end_x = this.v_angle.x - stof(argv(1));
-       this.bot_cmd_aim_end_y = this.v_angle.y + stof(argv(0));
-       this.bot_cmd_aim_end_z = 0;
-
-       this.bot_cmd_aim_begintime = time;
-       this.bot_cmd_aim_endtime = time + step;
-
-       return CMD_STATUS_EXECUTING;
-}
-
-float bot_cmd_aimtarget(entity this)
-{
-       if(this.bot_cmd_aim_endtime)
-       {
-               return bot_cmd_aim(this);
-       }
-
-       entity e;
-       string parms;
-       vector v;
-       float tokens, step;
-
-       parms = bot_cmd.bot_cmd_parm_string;
-
-       tokens = tokenizebyseparator(parms, " ");
-
-       e = bot_getplace(this, argv(0));
-       if(!e)
-               return CMD_STATUS_ERROR;
-
-       v = e.origin + (e.mins + e.maxs) * 0.5;
-
-       if(tokens==1)
-       {
-               this.v_angle = vectoangles(v - (this.origin + this.view_ofs));
-               this.v_angle_x = -this.v_angle.x;
-               return CMD_STATUS_FINISHED;
-       }
-
-       if(tokens<1||tokens>2)
-               return CMD_STATUS_ERROR;
-
-       step = stof(argv(1));
-
-       this.bot_cmd_aim_begin = this.v_angle;
-       this.bot_cmd_aim_end = vectoangles(v - (this.origin + this.view_ofs));
-       this.bot_cmd_aim_end_x = -this.bot_cmd_aim_end.x;
-
-       this.bot_cmd_aim_begintime = time;
-       this.bot_cmd_aim_endtime = time + step;
-
-       return CMD_STATUS_EXECUTING;
-}
-
-.int bot_cmd_keys;
-
-const int BOT_CMD_KEY_NONE             = 0;
-const int BOT_CMD_KEY_FORWARD  = BIT(0);
-const int BOT_CMD_KEY_BACKWARD         = BIT(1);
-const int BOT_CMD_KEY_RIGHT    = BIT(2);
-const int BOT_CMD_KEY_LEFT             = BIT(3);
-const int BOT_CMD_KEY_JUMP             = BIT(4);
-const int BOT_CMD_KEY_ATTACK1  = BIT(5);
-const int BOT_CMD_KEY_ATTACK2  = BIT(6);
-const int BOT_CMD_KEY_USE              = BIT(7);
-const int BOT_CMD_KEY_HOOK             = BIT(8);
-const int BOT_CMD_KEY_CROUCH   = BIT(9);
-const int BOT_CMD_KEY_CHAT             = BIT(10);
-
-bool bot_presskeys(entity this)
-{
-       this.movement = '0 0 0';
-       PHYS_INPUT_BUTTON_JUMP(this) = false;
-       PHYS_INPUT_BUTTON_CROUCH(this) = false;
-       PHYS_INPUT_BUTTON_ATCK(this) = false;
-       PHYS_INPUT_BUTTON_ATCK2(this) = false;
-       PHYS_INPUT_BUTTON_USE(this) = false;
-       PHYS_INPUT_BUTTON_HOOK(this) = false;
-       PHYS_INPUT_BUTTON_CHAT(this) = false;
-
-       if(this.bot_cmd_keys == BOT_CMD_KEY_NONE)
-               return false;
-
-       if(this.bot_cmd_keys & BOT_CMD_KEY_FORWARD)
-               this.movement_x = autocvar_sv_maxspeed;
-       else if(this.bot_cmd_keys & BOT_CMD_KEY_BACKWARD)
-               this.movement_x = -autocvar_sv_maxspeed;
-
-       if(this.bot_cmd_keys & BOT_CMD_KEY_RIGHT)
-               this.movement_y = autocvar_sv_maxspeed;
-       else if(this.bot_cmd_keys & BOT_CMD_KEY_LEFT)
-               this.movement_y = -autocvar_sv_maxspeed;
-
-       if(this.bot_cmd_keys & BOT_CMD_KEY_JUMP)
-               PHYS_INPUT_BUTTON_JUMP(this) = true;
-
-       if(this.bot_cmd_keys & BOT_CMD_KEY_CROUCH)
-               PHYS_INPUT_BUTTON_CROUCH(this) = true;
-
-       if(this.bot_cmd_keys & BOT_CMD_KEY_ATTACK1)
-               PHYS_INPUT_BUTTON_ATCK(this) = true;
-
-       if(this.bot_cmd_keys & BOT_CMD_KEY_ATTACK2)
-               PHYS_INPUT_BUTTON_ATCK2(this) = true;
-
-       if(this.bot_cmd_keys & BOT_CMD_KEY_USE)
-               PHYS_INPUT_BUTTON_USE(this) = true;
-
-       if(this.bot_cmd_keys & BOT_CMD_KEY_HOOK)
-               PHYS_INPUT_BUTTON_HOOK(this) = true;
-
-       if(this.bot_cmd_keys & BOT_CMD_KEY_CHAT)
-               PHYS_INPUT_BUTTON_CHAT(this) = true;
-
-       return true;
-}
-
-
-float bot_cmd_keypress_handler(entity this, string key, float enabled)
-{
-       switch(key)
-       {
-               case "all":
-                       if(enabled)
-                               this.bot_cmd_keys = power2of(20) - 1; // >:)
-                       else
-                               this.bot_cmd_keys = BOT_CMD_KEY_NONE;
-               case "forward":
-                       if(enabled)
-                       {
-                               this.bot_cmd_keys |= BOT_CMD_KEY_FORWARD;
-                               this.bot_cmd_keys &= ~BOT_CMD_KEY_BACKWARD;
-                       }
-                       else
-                               this.bot_cmd_keys &= ~BOT_CMD_KEY_FORWARD;
-                       break;
-               case "backward":
-                       if(enabled)
-                       {
-                               this.bot_cmd_keys |= BOT_CMD_KEY_BACKWARD;
-                               this.bot_cmd_keys &= ~BOT_CMD_KEY_FORWARD;
-                       }
-                       else
-                               this.bot_cmd_keys &= ~BOT_CMD_KEY_BACKWARD;
-                       break;
-               case "left":
-                       if(enabled)
-                       {
-                               this.bot_cmd_keys |= BOT_CMD_KEY_LEFT;
-                               this.bot_cmd_keys &= ~BOT_CMD_KEY_RIGHT;
-                       }
-                       else
-                               this.bot_cmd_keys &= ~BOT_CMD_KEY_LEFT;
-                       break;
-               case "right":
-                       if(enabled)
-                       {
-                               this.bot_cmd_keys |= BOT_CMD_KEY_RIGHT;
-                               this.bot_cmd_keys &= ~BOT_CMD_KEY_LEFT;
-                       }
-                       else
-                               this.bot_cmd_keys &= ~BOT_CMD_KEY_RIGHT;
-                       break;
-               case "jump":
-                       if(enabled)
-                               this.bot_cmd_keys |= BOT_CMD_KEY_JUMP;
-                       else
-                               this.bot_cmd_keys &= ~BOT_CMD_KEY_JUMP;
-                       break;
-               case "crouch":
-                       if(enabled)
-                               this.bot_cmd_keys |= BOT_CMD_KEY_CROUCH;
-                       else
-                               this.bot_cmd_keys &= ~BOT_CMD_KEY_CROUCH;
-                       break;
-               case "attack1":
-                       if(enabled)
-                               this.bot_cmd_keys |= BOT_CMD_KEY_ATTACK1;
-                       else
-                               this.bot_cmd_keys &= ~BOT_CMD_KEY_ATTACK1;
-                       break;
-               case "attack2":
-                       if(enabled)
-                               this.bot_cmd_keys |= BOT_CMD_KEY_ATTACK2;
-                       else
-                               this.bot_cmd_keys &= ~BOT_CMD_KEY_ATTACK2;
-                       break;
-               case "use":
-                       if(enabled)
-                               this.bot_cmd_keys |= BOT_CMD_KEY_USE;
-                       else
-                               this.bot_cmd_keys &= ~BOT_CMD_KEY_USE;
-                       break;
-               case "hook":
-                       if(enabled)
-                               this.bot_cmd_keys |= BOT_CMD_KEY_HOOK;
-                       else
-                               this.bot_cmd_keys &= ~BOT_CMD_KEY_HOOK;
-                       break;
-               case "chat":
-                       if(enabled)
-                               this.bot_cmd_keys |= BOT_CMD_KEY_CHAT;
-                       else
-                               this.bot_cmd_keys &= ~BOT_CMD_KEY_CHAT;
-                       break;
-               default:
-                       break;
-       }
-
-       return CMD_STATUS_FINISHED;
-}
-
-float bot_cmd_presskey(entity this)
-{
-       string key;
-
-       key = bot_cmd.bot_cmd_parm_string;
-
-       bot_cmd_keypress_handler(this, key,true);
-
-       return CMD_STATUS_FINISHED;
-}
-
-float bot_cmd_releasekey(entity this)
-{
-       string key;
-
-       key = bot_cmd.bot_cmd_parm_string;
-
-       return bot_cmd_keypress_handler(this, key,false);
-}
-
-float bot_cmd_pause(entity this)
-{
-       PHYS_INPUT_BUTTON_DRAG(this) = false;
-       PHYS_INPUT_BUTTON_USE(this) = false;
-       PHYS_INPUT_BUTTON_ATCK(this) = false;
-       PHYS_INPUT_BUTTON_JUMP(this) = false;
-       PHYS_INPUT_BUTTON_HOOK(this) = false;
-       PHYS_INPUT_BUTTON_CHAT(this) = false;
-       PHYS_INPUT_BUTTON_ATCK2(this) = false;
-       PHYS_INPUT_BUTTON_CROUCH(this) = false;
-
-       this.movement = '0 0 0';
-       this.bot_cmd_keys = BOT_CMD_KEY_NONE;
-
-       this.bot_exec_status |= BOT_EXEC_STATUS_PAUSED;
-       return CMD_STATUS_FINISHED;
-}
-
-float bot_cmd_moveto(entity this)
-{
-       return this.cmd_moveto(this, bot_cmd.bot_cmd_parm_vector);
-}
-
-float bot_cmd_movetotarget(entity this)
-{
-       entity e;
-       e = bot_getplace(this, bot_cmd.bot_cmd_parm_string);
-       if(!e)
-               return CMD_STATUS_ERROR;
-       return this.cmd_moveto(this, e.origin + (e.mins + e.maxs) * 0.5);
-}
-
-float bot_cmd_resetgoal(entity this)
-{
-       return this.cmd_resetgoal(this);
-}
-
-
-float bot_cmd_sound(entity this)
-{
-       string f;
-       f = bot_cmd.bot_cmd_parm_string;
-
-       float n = tokenizebyseparator(f, " ");
-
-       string sample = f;
-       float chan = CH_WEAPON_B;
-       float vol = VOL_BASE;
-       float atten = ATTEN_MIN;
-
-       if(n >= 1)
-               sample = argv(n - 1);
-       if(n >= 2)
-               chan = stof(argv(0));
-       if(n >= 3)
-               vol = stof(argv(1));
-       if(n >= 4)
-               atten = stof(argv(2));
-
-       precache_sound(f);
-       _sound(this, chan, sample, vol, atten);
-
-       return CMD_STATUS_FINISHED;
-}
-
-.entity tuba_note;
-float bot_cmd_debug_assert_canfire(entity this)
-{
-       float f = bot_cmd.bot_cmd_parm_float;
-
-       int slot = 0;
-       .entity weaponentity = weaponentities[slot];
-       if(this.(weaponentity).state != WS_READY)
-       {
-               if(f)
-               {
-                       this.colormod = '0 8 8';
-                       LOG_INFO("Bot ", this.netname, " using ", this.weaponname, " wants to fire, inhibited by weaponentity state\n");
-               }
-       }
-       else if(ATTACK_FINISHED(this, slot) > time)
-       {
-               if(f)
-               {
-                       this.colormod = '8 0 8';
-                       LOG_INFO("Bot ", this.netname, " using ", this.weaponname, " wants to fire, inhibited by ATTACK_FINISHED (", ftos(ATTACK_FINISHED(this, slot) - time), " seconds left)\n");
-               }
-       }
-       else if(this.tuba_note)
-       {
-               if(f)
-               {
-                       this.colormod = '8 0 0';
-                       LOG_INFO("Bot ", this.netname, " using ", this.weaponname, " wants to fire, bot still has an active tuba note\n");
-               }
-       }
-       else
-       {
-               if(!f)
-               {
-                       this.colormod = '8 8 0';
-                       LOG_INFO("Bot ", this.netname, " using ", this.weaponname, " thinks it has fired, but apparently did not; ATTACK_FINISHED says ", ftos(ATTACK_FINISHED(this, slot) - time), " seconds left\n");
-               }
-       }
-
-       return CMD_STATUS_FINISHED;
-}
-
-//
-
-void bot_command_executed(entity this, bool rm)
-{
-       entity cmd;
-
-       cmd = bot_cmd;
-
-       if(rm)
-               bot_dequeuecommand(this, this.bot_cmd_execution_index);
-
-       this.bot_cmd_execution_index++;
-}
-
-void bot_setcurrentcommand(entity this)
-{
-       bot_cmd = NULL;
-
-       if(!this.bot_cmd_current)
-       {
-               this.bot_cmd_current = new_pure(bot_cmd);
-               this.bot_cmd_current.is_bot_cmd = true;
-       }
-
-       bot_cmd = this.bot_cmd_current;
-       if(bot_cmd.bot_cmd_index != this.bot_cmd_execution_index || this.bot_cmd_execution_index == 0)
-       {
-               if(bot_havecommand(this, this.bot_cmd_execution_index))
-               {
-                       string cmdstring;
-                       cmdstring = bot_readcommand(this, this.bot_cmd_execution_index);
-                       if(bot_decodecommand(cmdstring))
-                       {
-                               bot_cmd.owner = this;
-                               bot_cmd.bot_cmd_index = this.bot_cmd_execution_index;
-                       }
-                       else
-                       {
-                               // Invalid command, remove from queue
-                               bot_cmd = NULL;
-                               bot_dequeuecommand(this, this.bot_cmd_execution_index);
-                               this.bot_cmd_execution_index++;
-                       }
-               }
-               else
-                       bot_cmd = NULL;
-       }
-}
-
-void bot_resetqueues()
-{
-       FOREACH_CLIENT(it.isbot, LAMBDA(
-               it.bot_cmd_execution_index = 0;
-               bot_clearqueue(it);
-               // also, cancel all barriers
-               it.bot_barrier = 0;
-               for(int i = 0; i < it.bot_places_count; ++i)
-               {
-                       strunzone(it.(bot_placenames[i]));
-                       it.(bot_placenames[i]) = string_null;
-               }
-               it.bot_places_count = 0;
-       ));
-
-       bot_barriertime = time;
-}
-
-// Here we map commands to functions and deal with complex interactions between commands and execution states
-// NOTE: Of course you need to include your commands here too :)
-float bot_execute_commands_once(entity this)
-{
-       float status, ispressingkey;
-
-       // Find command
-       bot_setcurrentcommand(this);
-
-       // if we have no bot command, better return
-       // old logic kept pressing previously pressed keys, but that has problems
-       // (namely, it means you cannot make a bot "normal" ever again)
-       // to keep a bot walking for a while, use the "wait" bot command
-       if(bot_cmd == NULL)
-               return false;
-
-       // Ignore all commands except continue when the bot is paused
-       if(this.bot_exec_status & BOT_EXEC_STATUS_PAUSED)
-       if(bot_cmd.bot_cmd_type!=BOT_CMD_CONTINUE)
-       {
-               if(bot_cmd.bot_cmd_type!=BOT_CMD_NULL)
-               {
-                       bot_command_executed(this, true);
-                       LOG_INFO( "WARNING: Commands are ignored while the bot is paused. Use the command 'continue' instead.\n");
-               }
-               return 1;
-       }
-
-       // Keep pressing keys raised by the "presskey" command
-       ispressingkey = boolean(bot_presskeys(this));
-
-       // Handle conditions
-       if (!(bot_cmd.bot_cmd_type==BOT_CMD_FI||bot_cmd.bot_cmd_type==BOT_CMD_ELSE))
-       if(this.bot_cmd_condition_status & CMD_CONDITION_true && this.bot_cmd_condition_status & CMD_CONDITION_false_BLOCK)
-       {
-               bot_command_executed(this, true);
-               return -1;
-       }
-       else if(this.bot_cmd_condition_status & CMD_CONDITION_false && this.bot_cmd_condition_status & CMD_CONDITION_true_BLOCK)
-       {
-               bot_command_executed(this, true);
-               return -1;
-       }
-
-       // Map commands to functions
-       switch(bot_cmd.bot_cmd_type)
-       {
-               case BOT_CMD_NULL:
-                       return ispressingkey;
-                       //break;
-               case BOT_CMD_PAUSE:
-                       status = bot_cmd_pause(this);
-                       break;
-               case BOT_CMD_CONTINUE:
-                       status = bot_cmd_continue(this);
-                       break;
-               case BOT_CMD_WAIT:
-                       status = bot_cmd_wait(this);
-                       break;
-               case BOT_CMD_WAIT_UNTIL:
-                       status = bot_cmd_wait_until(this);
-                       break;
-               case BOT_CMD_TURN:
-                       status = bot_cmd_turn(this);
-                       break;
-               case BOT_CMD_MOVETO:
-                       status = bot_cmd_moveto(this);
-                       break;
-               case BOT_CMD_MOVETOTARGET:
-                       status = bot_cmd_movetotarget(this);
-                       break;
-               case BOT_CMD_RESETGOAL:
-                       status = bot_cmd_resetgoal(this);
-                       break;
-               case BOT_CMD_CC:
-                       status = bot_cmd_cc(this);
-                       break;
-               case BOT_CMD_IF:
-                       status = bot_cmd_if(this);
-                       break;
-               case BOT_CMD_ELSE:
-                       status = bot_cmd_else(this);
-                       break;
-               case BOT_CMD_FI:
-                       status = bot_cmd_fi(this);
-                       break;
-               case BOT_CMD_RESETAIM:
-                       status = bot_cmd_resetaim(this);
-                       break;
-               case BOT_CMD_AIM:
-                       status = bot_cmd_aim(this);
-                       break;
-               case BOT_CMD_AIMTARGET:
-                       status = bot_cmd_aimtarget(this);
-                       break;
-               case BOT_CMD_PRESSKEY:
-                       status = bot_cmd_presskey(this);
-                       break;
-               case BOT_CMD_RELEASEKEY:
-                       status = bot_cmd_releasekey(this);
-                       break;
-               case BOT_CMD_SELECTWEAPON:
-                       status = bot_cmd_select_weapon(this);
-                       break;
-               case BOT_CMD_IMPULSE:
-                       status = bot_cmd_impulse(this);
-                       break;
-               case BOT_CMD_BARRIER:
-                       status = bot_cmd_barrier(this);
-                       break;
-               case BOT_CMD_CONSOLE:
-                       localcmd(strcat(bot_cmd.bot_cmd_parm_string, "\n"));
-                       status = CMD_STATUS_FINISHED;
-                       break;
-               case BOT_CMD_SOUND:
-                       status = bot_cmd_sound(this);
-                       break;
-               case BOT_CMD_DEBUG_ASSERT_CANFIRE:
-                       status = bot_cmd_debug_assert_canfire(this);
-                       break;
-               default:
-                       LOG_INFO(strcat("ERROR: Invalid command on queue with id '",ftos(bot_cmd.bot_cmd_type),"'\n"));
-                       return 0;
-       }
-
-       if (status==CMD_STATUS_ERROR)
-               LOG_INFO(strcat("ERROR: The command '",bot_cmd_string[bot_cmd.bot_cmd_type],"' returned an error status\n"));
-
-       // Move execution pointer
-       if(status==CMD_STATUS_EXECUTING)
-       {
-               return 1;
-       }
-       else
-       {
-               if(autocvar_g_debug_bot_commands)
-               {
-                       string parms;
-
-                       switch(bot_cmd_parm_type[bot_cmd.bot_cmd_type])
-                       {
-                               case BOT_CMD_PARAMETER_FLOAT:
-                                       parms = ftos(bot_cmd.bot_cmd_parm_float);
-                                       break;
-                               case BOT_CMD_PARAMETER_STRING:
-                                       parms = bot_cmd.bot_cmd_parm_string;
-                                       break;
-                               case BOT_CMD_PARAMETER_VECTOR:
-                                       parms = vtos(bot_cmd.bot_cmd_parm_vector);
-                                       break;
-                               default:
-                                       parms = "";
-                                       break;
-                       }
-                       clientcommand(this,strcat("say ^7", bot_cmd_string[bot_cmd.bot_cmd_type]," ",parms,"\n"));
-               }
-
-               bot_command_executed(this, true);
-       }
-
-       if(status == CMD_STATUS_FINISHED)
-               return -1;
-
-       return CMD_STATUS_ERROR;
-}
-
-// This function should be (the only) called directly from the bot ai loop
-int bot_execute_commands(entity this)
-{
-       int f;
-       do
-       {
-               f = bot_execute_commands_once(this);
-       }
-       while(f < 0);
-       return f;
-}
diff --git a/qcsrc/server/bot/scripting.qh b/qcsrc/server/bot/scripting.qh
deleted file mode 100644 (file)
index cb6cd87..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-#pragma once
-
-#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(entity, vector) cmd_moveto;
-.float(entity) 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 this);
-entity find_bot_by_name(string name);
-entity find_bot_by_number(float number);
diff --git a/qcsrc/server/bot/waypoints.qc b/qcsrc/server/bot/waypoints.qc
deleted file mode 100644 (file)
index 586f2a8..0000000
+++ /dev/null
@@ -1,1102 +0,0 @@
-#include "waypoints.qh"
-
-#include "bot.qh"
-#include "navigation.qh"
-
-#include <common/state.qh>
-
-#include "../antilag.qh"
-
-#include <common/constants.qh>
-
-#include <lib/warpzone/common.qh>
-#include <lib/warpzone/util_server.qh>
-
-// create a new spawnfunc_waypoint and automatically link it to other waypoints, and link
-// them back to it as well
-// (suitable for spawnfunc_waypoint editor)
-entity waypoint_spawn(vector m1, vector m2, float f)
-{
-       if(!(f & WAYPOINTFLAG_PERSONAL))
-       {
-               IL_EACH(g_waypoints, boxesoverlap(m1, m2, it.absmin, it.absmax),
-               {
-                       return it;
-               });
-       }
-
-       entity w = new(waypoint);
-       IL_PUSH(g_waypoints, w);
-       w.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_PLAYERCLIP | DPCONTENTS_BOTCLIP;
-       w.wpflags = f;
-       w.solid = SOLID_TRIGGER;
-       setorigin(w, (m1 + m2) * 0.5);
-       setsize(w, m1 - w.origin, m2 - w.origin);
-       if (vlen(w.size) > 0)
-               w.wpisbox = true;
-
-       if(!w.wpisbox)
-       {
-               setsize(w, STAT(PL_MIN, NULL) - '1 1 0', STAT(PL_MAX, NULL) + '1 1 0');
-               if(!move_out_of_solid(w))
-               {
-                       if(!(f & WAYPOINTFLAG_GENERATED))
-                       {
-                               LOG_TRACE("Killed a waypoint that was stuck in solid at ", vtos(w.origin), "\n");
-                               remove(w);
-                               return NULL;
-                       }
-                       else
-                       {
-                               if(autocvar_developer)
-                               {
-                                       LOG_INFO("A generated waypoint is stuck in solid at ", vtos(w.origin), "\n");
-                                       backtrace("Waypoint stuck");
-                               }
-                       }
-               }
-               setsize(w, '0 0 0', '0 0 0');
-       }
-
-       waypoint_clearlinks(w);
-       //waypoint_schedulerelink(w);
-
-       if (autocvar_g_waypointeditor)
-       {
-               m1 = w.mins;
-               m2 = w.maxs;
-               setmodel(w, MDL_WAYPOINT); w.effects = EF_LOWPRECISION;
-               setsize(w, m1, m2);
-               if (w.wpflags & WAYPOINTFLAG_ITEM)
-                       w.colormod = '1 0 0';
-               else if (w.wpflags & WAYPOINTFLAG_GENERATED)
-                       w.colormod = '1 1 0';
-               else
-                       w.colormod = '1 1 1';
-       }
-       else
-               w.model = "";
-
-       return w;
-}
-
-// add a new link to the spawnfunc_waypoint, replacing the furthest link it already has
-void waypoint_addlink(entity from, entity to)
-{
-       float c;
-
-       if (from == to)
-               return;
-       if (from.wpflags & WAYPOINTFLAG_NORELINK)
-               return;
-
-       if (from.wp00 == to) return;if (from.wp01 == to) return;if (from.wp02 == to) return;if (from.wp03 == to) return;
-       if (from.wp04 == to) return;if (from.wp05 == to) return;if (from.wp06 == to) return;if (from.wp07 == to) return;
-       if (from.wp08 == to) return;if (from.wp09 == to) return;if (from.wp10 == to) return;if (from.wp11 == to) return;
-       if (from.wp12 == to) return;if (from.wp13 == to) return;if (from.wp14 == to) return;if (from.wp15 == to) return;
-       if (from.wp16 == to) return;if (from.wp17 == to) return;if (from.wp18 == to) return;if (from.wp19 == to) return;
-       if (from.wp20 == to) return;if (from.wp21 == to) return;if (from.wp22 == to) return;if (from.wp23 == to) return;
-       if (from.wp24 == to) return;if (from.wp25 == to) return;if (from.wp26 == to) return;if (from.wp27 == to) return;
-       if (from.wp28 == to) return;if (from.wp29 == to) return;if (from.wp30 == to) return;if (from.wp31 == to) return;
-
-       if (to.wpisbox || from.wpisbox)
-       {
-               // if either is a box we have to find the nearest points on them to
-               // calculate the distance properly
-               vector v1, v2, m1, m2;
-               v1 = from.origin;
-               m1 = to.absmin;
-               m2 = to.absmax;
-               v1_x = bound(m1_x, v1_x, m2_x);
-               v1_y = bound(m1_y, v1_y, m2_y);
-               v1_z = bound(m1_z, v1_z, m2_z);
-               v2 = to.origin;
-               m1 = from.absmin;
-               m2 = from.absmax;
-               v2_x = bound(m1_x, v2_x, m2_x);
-               v2_y = bound(m1_y, v2_y, m2_y);
-               v2_z = bound(m1_z, v2_z, m2_z);
-               v2 = to.origin;
-               c = vlen(v2 - v1);
-       }
-       else
-               c = vlen(to.origin - from.origin);
-
-       if (from.wp31mincost < c) return;
-       if (from.wp30mincost < c) {from.wp31 = to;from.wp31mincost = c;return;} from.wp31 = from.wp30;from.wp31mincost = from.wp30mincost;
-       if (from.wp29mincost < c) {from.wp30 = to;from.wp30mincost = c;return;} from.wp30 = from.wp29;from.wp30mincost = from.wp29mincost;
-       if (from.wp28mincost < c) {from.wp29 = to;from.wp29mincost = c;return;} from.wp29 = from.wp28;from.wp29mincost = from.wp28mincost;
-       if (from.wp27mincost < c) {from.wp28 = to;from.wp28mincost = c;return;} from.wp28 = from.wp27;from.wp28mincost = from.wp27mincost;
-       if (from.wp26mincost < c) {from.wp27 = to;from.wp27mincost = c;return;} from.wp27 = from.wp26;from.wp27mincost = from.wp26mincost;
-       if (from.wp25mincost < c) {from.wp26 = to;from.wp26mincost = c;return;} from.wp26 = from.wp25;from.wp26mincost = from.wp25mincost;
-       if (from.wp24mincost < c) {from.wp25 = to;from.wp25mincost = c;return;} from.wp25 = from.wp24;from.wp25mincost = from.wp24mincost;
-       if (from.wp23mincost < c) {from.wp24 = to;from.wp24mincost = c;return;} from.wp24 = from.wp23;from.wp24mincost = from.wp23mincost;
-       if (from.wp22mincost < c) {from.wp23 = to;from.wp23mincost = c;return;} from.wp23 = from.wp22;from.wp23mincost = from.wp22mincost;
-       if (from.wp21mincost < c) {from.wp22 = to;from.wp22mincost = c;return;} from.wp22 = from.wp21;from.wp22mincost = from.wp21mincost;
-       if (from.wp20mincost < c) {from.wp21 = to;from.wp21mincost = c;return;} from.wp21 = from.wp20;from.wp21mincost = from.wp20mincost;
-       if (from.wp19mincost < c) {from.wp20 = to;from.wp20mincost = c;return;} from.wp20 = from.wp19;from.wp20mincost = from.wp19mincost;
-       if (from.wp18mincost < c) {from.wp19 = to;from.wp19mincost = c;return;} from.wp19 = from.wp18;from.wp19mincost = from.wp18mincost;
-       if (from.wp17mincost < c) {from.wp18 = to;from.wp18mincost = c;return;} from.wp18 = from.wp17;from.wp18mincost = from.wp17mincost;
-       if (from.wp16mincost < c) {from.wp17 = to;from.wp17mincost = c;return;} from.wp17 = from.wp16;from.wp17mincost = from.wp16mincost;
-       if (from.wp15mincost < c) {from.wp16 = to;from.wp16mincost = c;return;} from.wp16 = from.wp15;from.wp16mincost = from.wp15mincost;
-       if (from.wp14mincost < c) {from.wp15 = to;from.wp15mincost = c;return;} from.wp15 = from.wp14;from.wp15mincost = from.wp14mincost;
-       if (from.wp13mincost < c) {from.wp14 = to;from.wp14mincost = c;return;} from.wp14 = from.wp13;from.wp14mincost = from.wp13mincost;
-       if (from.wp12mincost < c) {from.wp13 = to;from.wp13mincost = c;return;} from.wp13 = from.wp12;from.wp13mincost = from.wp12mincost;
-       if (from.wp11mincost < c) {from.wp12 = to;from.wp12mincost = c;return;} from.wp12 = from.wp11;from.wp12mincost = from.wp11mincost;
-       if (from.wp10mincost < c) {from.wp11 = to;from.wp11mincost = c;return;} from.wp11 = from.wp10;from.wp11mincost = from.wp10mincost;
-       if (from.wp09mincost < c) {from.wp10 = to;from.wp10mincost = c;return;} from.wp10 = from.wp09;from.wp10mincost = from.wp09mincost;
-       if (from.wp08mincost < c) {from.wp09 = to;from.wp09mincost = c;return;} from.wp09 = from.wp08;from.wp09mincost = from.wp08mincost;
-       if (from.wp07mincost < c) {from.wp08 = to;from.wp08mincost = c;return;} from.wp08 = from.wp07;from.wp08mincost = from.wp07mincost;
-       if (from.wp06mincost < c) {from.wp07 = to;from.wp07mincost = c;return;} from.wp07 = from.wp06;from.wp07mincost = from.wp06mincost;
-       if (from.wp05mincost < c) {from.wp06 = to;from.wp06mincost = c;return;} from.wp06 = from.wp05;from.wp06mincost = from.wp05mincost;
-       if (from.wp04mincost < c) {from.wp05 = to;from.wp05mincost = c;return;} from.wp05 = from.wp04;from.wp05mincost = from.wp04mincost;
-       if (from.wp03mincost < c) {from.wp04 = to;from.wp04mincost = c;return;} from.wp04 = from.wp03;from.wp04mincost = from.wp03mincost;
-       if (from.wp02mincost < c) {from.wp03 = to;from.wp03mincost = c;return;} from.wp03 = from.wp02;from.wp03mincost = from.wp02mincost;
-       if (from.wp01mincost < c) {from.wp02 = to;from.wp02mincost = c;return;} from.wp02 = from.wp01;from.wp02mincost = from.wp01mincost;
-       if (from.wp00mincost < c) {from.wp01 = to;from.wp01mincost = c;return;} from.wp01 = from.wp00;from.wp01mincost = from.wp00mincost;
-       from.wp00 = to;from.wp00mincost = c;return;
-}
-
-// relink this spawnfunc_waypoint
-// (precompile a list of all reachable waypoints from this spawnfunc_waypoint)
-// (SLOW!)
-void waypoint_think(entity this)
-{
-       vector sv, sm1, sm2, ev, em1, em2, dv;
-
-       bot_calculate_stepheightvec();
-
-       bot_navigation_movemode = ((autocvar_bot_navigation_ignoreplayers) ? MOVE_NOMONSTERS : MOVE_NORMAL);
-
-       //dprint("waypoint_think wpisbox = ", ftos(this.wpisbox), "\n");
-       sm1 = this.origin + this.mins;
-       sm2 = this.origin + this.maxs;
-       IL_EACH(g_waypoints, true,
-       {
-               if (boxesoverlap(this.absmin, this.absmax, it.absmin, it.absmax))
-               {
-                       waypoint_addlink(this, it);
-                       waypoint_addlink(it, this);
-               }
-               else
-               {
-                       ++relink_total;
-                       if(!checkpvs(this.origin, it))
-                       {
-                               ++relink_pvsculled;
-                               continue;
-                       }
-                       sv = it.origin;
-                       sv.x = bound(sm1_x, sv.x, sm2_x);
-                       sv.y = bound(sm1_y, sv.y, sm2_y);
-                       sv.z = bound(sm1_z, sv.z, sm2_z);
-                       ev = this.origin;
-                       em1 = it.origin + it.mins;
-                       em2 = it.origin + it.maxs;
-                       ev.x = bound(em1_x, ev.x, em2_x);
-                       ev.y = bound(em1_y, ev.y, em2_y);
-                       ev.z = bound(em1_z, ev.z, em2_z);
-                       dv = ev - sv;
-                       dv.z = 0;
-                       if(vdist(dv, >=, 1050)) // max search distance in XY
-                       {
-                               ++relink_lengthculled;
-                               continue;
-                       }
-                       navigation_testtracewalk = 0;
-                       if (!this.wpisbox)
-                       {
-                               tracebox(sv - STAT(PL_MIN, NULL).z * '0 0 1', STAT(PL_MIN, NULL), STAT(PL_MAX, NULL), sv, false, this);
-                               if (!trace_startsolid)
-                               {
-                                       //dprint("sv deviation", vtos(trace_endpos - sv), "\n");
-                                       sv = trace_endpos + '0 0 1';
-                               }
-                       }
-                       if (!it.wpisbox)
-                       {
-                               tracebox(ev - STAT(PL_MIN, NULL).z * '0 0 1', STAT(PL_MIN, NULL), STAT(PL_MAX, NULL), ev, false, it);
-                               if (!trace_startsolid)
-                               {
-                                       //dprint("ev deviation", vtos(trace_endpos - ev), "\n");
-                                       ev = trace_endpos + '0 0 1';
-                               }
-                       }
-                       //traceline(this.origin, it.origin, false, NULL);
-                       //if (trace_fraction == 1)
-                       if (!this.wpisbox && tracewalk(this, sv, STAT(PL_MIN, NULL), STAT(PL_MAX, NULL), ev, MOVE_NOMONSTERS))
-                               waypoint_addlink(this, it);
-                       else
-                               relink_walkculled += 0.5;
-                       if (!it.wpisbox && tracewalk(it, ev, STAT(PL_MIN, NULL), STAT(PL_MAX, NULL), sv, MOVE_NOMONSTERS))
-                               waypoint_addlink(it, this);
-                       else
-                               relink_walkculled += 0.5;
-               }
-       });
-       navigation_testtracewalk = 0;
-       this.wplinked = true;
-}
-
-void waypoint_clearlinks(entity wp)
-{
-       // clear links to other waypoints
-       float f;
-       f = 10000000;
-       wp.wp00 = wp.wp01 = wp.wp02 = wp.wp03 = wp.wp04 = wp.wp05 = wp.wp06 = wp.wp07 = NULL;
-       wp.wp08 = wp.wp09 = wp.wp10 = wp.wp11 = wp.wp12 = wp.wp13 = wp.wp14 = wp.wp15 = NULL;
-       wp.wp16 = wp.wp17 = wp.wp18 = wp.wp19 = wp.wp20 = wp.wp21 = wp.wp22 = wp.wp23 = NULL;
-       wp.wp24 = wp.wp25 = wp.wp26 = wp.wp27 = wp.wp28 = wp.wp29 = wp.wp30 = wp.wp31 = NULL;
-
-       wp.wp00mincost = wp.wp01mincost = wp.wp02mincost = wp.wp03mincost = wp.wp04mincost = wp.wp05mincost = wp.wp06mincost = wp.wp07mincost = f;
-       wp.wp08mincost = wp.wp09mincost = wp.wp10mincost = wp.wp11mincost = wp.wp12mincost = wp.wp13mincost = wp.wp14mincost = wp.wp15mincost = f;
-       wp.wp16mincost = wp.wp17mincost = wp.wp18mincost = wp.wp19mincost = wp.wp20mincost = wp.wp21mincost = wp.wp22mincost = wp.wp23mincost = f;
-       wp.wp24mincost = wp.wp25mincost = wp.wp26mincost = wp.wp27mincost = wp.wp28mincost = wp.wp29mincost = wp.wp30mincost = wp.wp31mincost = f;
-
-       wp.wplinked = false;
-}
-
-// tell a spawnfunc_waypoint to relink
-void waypoint_schedulerelink(entity wp)
-{
-       if (wp == NULL)
-               return;
-       // TODO: add some sort of visible box in edit mode for box waypoints
-       if (autocvar_g_waypointeditor)
-       {
-               vector m1, m2;
-               m1 = wp.mins;
-               m2 = wp.maxs;
-               setmodel(wp, MDL_WAYPOINT); wp.effects = EF_LOWPRECISION;
-               setsize(wp, m1, m2);
-               if (wp.wpflags & WAYPOINTFLAG_ITEM)
-                       wp.colormod = '1 0 0';
-               else if (wp.wpflags & WAYPOINTFLAG_GENERATED)
-                       wp.colormod = '1 1 0';
-               else
-                       wp.colormod = '1 1 1';
-       }
-       else
-               wp.model = "";
-       wp.wpisbox = vlen(wp.size) > 0;
-       wp.enemy = NULL;
-       if (!(wp.wpflags & WAYPOINTFLAG_PERSONAL))
-               wp.owner = NULL;
-       if (!(wp.wpflags & WAYPOINTFLAG_NORELINK))
-               waypoint_clearlinks(wp);
-       // schedule an actual relink on next frame
-       setthink(wp, waypoint_think);
-       wp.nextthink = time;
-       wp.effects = EF_LOWPRECISION;
-}
-
-// spawnfunc_waypoint map entity
-spawnfunc(waypoint)
-{
-       IL_PUSH(g_waypoints, this);
-
-       setorigin(this, this.origin);
-       // schedule a relink after other waypoints have had a chance to spawn
-       waypoint_clearlinks(this);
-       //waypoint_schedulerelink(this);
-}
-
-// remove a spawnfunc_waypoint, and schedule all neighbors to relink
-void waypoint_remove(entity e)
-{
-       // tell all linked waypoints that they need to relink
-       waypoint_schedulerelink(e.wp00);
-       waypoint_schedulerelink(e.wp01);
-       waypoint_schedulerelink(e.wp02);
-       waypoint_schedulerelink(e.wp03);
-       waypoint_schedulerelink(e.wp04);
-       waypoint_schedulerelink(e.wp05);
-       waypoint_schedulerelink(e.wp06);
-       waypoint_schedulerelink(e.wp07);
-       waypoint_schedulerelink(e.wp08);
-       waypoint_schedulerelink(e.wp09);
-       waypoint_schedulerelink(e.wp10);
-       waypoint_schedulerelink(e.wp11);
-       waypoint_schedulerelink(e.wp12);
-       waypoint_schedulerelink(e.wp13);
-       waypoint_schedulerelink(e.wp14);
-       waypoint_schedulerelink(e.wp15);
-       waypoint_schedulerelink(e.wp16);
-       waypoint_schedulerelink(e.wp17);
-       waypoint_schedulerelink(e.wp18);
-       waypoint_schedulerelink(e.wp19);
-       waypoint_schedulerelink(e.wp20);
-       waypoint_schedulerelink(e.wp21);
-       waypoint_schedulerelink(e.wp22);
-       waypoint_schedulerelink(e.wp23);
-       waypoint_schedulerelink(e.wp24);
-       waypoint_schedulerelink(e.wp25);
-       waypoint_schedulerelink(e.wp26);
-       waypoint_schedulerelink(e.wp27);
-       waypoint_schedulerelink(e.wp28);
-       waypoint_schedulerelink(e.wp29);
-       waypoint_schedulerelink(e.wp30);
-       waypoint_schedulerelink(e.wp31);
-       // and now remove the spawnfunc_waypoint
-       remove(e);
-}
-
-// empties the map of waypoints
-void waypoint_removeall()
-{
-       IL_EACH(g_waypoints, true,
-       {
-               remove(it);
-       });
-}
-
-// tell all waypoints to relink
-// (is this useful at all?)
-void waypoint_schedulerelinkall()
-{
-       relink_total = relink_walkculled = relink_pvsculled = relink_lengthculled = 0;
-       IL_EACH(g_waypoints, true,
-       {
-               waypoint_schedulerelink(it);
-       });
-}
-
-// Load waypoint links from file
-float waypoint_load_links()
-{
-       string filename, s;
-       float file, tokens, c = 0, found;
-       entity wp_from = NULL, wp_to;
-       vector wp_to_pos, wp_from_pos;
-       filename = strcat("maps/", mapname);
-       filename = strcat(filename, ".waypoints.cache");
-       file = fopen(filename, FILE_READ);
-
-       if (file < 0)
-       {
-               LOG_TRACE("waypoint links load from ");
-               LOG_TRACE(filename);
-               LOG_TRACE(" failed\n");
-               return false;
-       }
-
-       while ((s = fgets(file)))
-       {
-               tokens = tokenizebyseparator(s, "*");
-
-               if (tokens!=2)
-               {
-                       // bad file format
-                       fclose(file);
-                       return false;
-               }
-
-               wp_from_pos     = stov(argv(0));
-               wp_to_pos       = stov(argv(1));
-
-               // Search "from" waypoint
-               if(!wp_from || wp_from.origin!=wp_from_pos)
-               {
-                       wp_from = findradius(wp_from_pos, 1);
-                       found = false;
-                       while(wp_from)
-                       {
-                               if(vdist(wp_from.origin - wp_from_pos, <, 1))
-                               if(wp_from.classname == "waypoint")
-                               {
-                                       found = true;
-                                       break;
-                               }
-                               wp_from = wp_from.chain;
-                       }
-
-                       if(!found)
-                       {
-                               LOG_TRACE("waypoint_load_links: couldn't find 'from' waypoint at ", vtos(wp_from.origin),"\n");
-                               continue;
-                       }
-
-               }
-
-               // Search "to" waypoint
-               wp_to = findradius(wp_to_pos, 1);
-               found = false;
-               while(wp_to)
-               {
-                       if(vdist(wp_to.origin - wp_to_pos, <, 1))
-                       if(wp_to.classname == "waypoint")
-                       {
-                               found = true;
-                               break;
-                       }
-                       wp_to = wp_to.chain;
-               }
-
-               if(!found)
-               {
-                       LOG_TRACE("waypoint_load_links: couldn't find 'to' waypoint at ", vtos(wp_to.origin),"\n");
-                       continue;
-               }
-
-               ++c;
-               waypoint_addlink(wp_from, wp_to);
-       }
-
-       fclose(file);
-
-       LOG_TRACE("loaded ", ftos(c), " waypoint links from maps/", mapname, ".waypoints.cache\n");
-
-       botframe_cachedwaypointlinks = true;
-       return true;
-}
-
-void waypoint_load_links_hardwired()
-{
-       string filename, s;
-       float file, tokens, c = 0, found;
-       entity wp_from = NULL, wp_to;
-       vector wp_to_pos, wp_from_pos;
-       filename = strcat("maps/", mapname);
-       filename = strcat(filename, ".waypoints.hardwired");
-       file = fopen(filename, FILE_READ);
-
-       botframe_loadedforcedlinks = true;
-
-       if (file < 0)
-       {
-               LOG_TRACE("waypoint links load from ", filename, " failed\n");
-               return;
-       }
-
-       while ((s = fgets(file)))
-       {
-               if(substring(s, 0, 2)=="//")
-                       continue;
-
-               if(substring(s, 0, 1)=="#")
-                       continue;
-
-               tokens = tokenizebyseparator(s, "*");
-
-               if (tokens!=2)
-                       continue;
-
-               wp_from_pos     = stov(argv(0));
-               wp_to_pos       = stov(argv(1));
-
-               // Search "from" waypoint
-               if(!wp_from || wp_from.origin!=wp_from_pos)
-               {
-                       wp_from = findradius(wp_from_pos, 5);
-                       found = false;
-                       while(wp_from)
-                       {
-                               if(vdist(wp_from.origin - wp_from_pos, <, 5))
-                               if(wp_from.classname == "waypoint")
-                               {
-                                       found = true;
-                                       break;
-                               }
-                               wp_from = wp_from.chain;
-                       }
-
-                       if(!found)
-                       {
-                               LOG_INFO(strcat("NOTICE: Can not find waypoint at ", vtos(wp_from_pos), ". Path skipped\n"));
-                               continue;
-                       }
-               }
-
-               // Search "to" waypoint
-               wp_to = findradius(wp_to_pos, 5);
-               found = false;
-               while(wp_to)
-               {
-                       if(vdist(wp_to.origin - wp_to_pos, <, 5))
-                       if(wp_to.classname == "waypoint")
-                       {
-                               found = true;
-                               break;
-                       }
-                       wp_to = wp_to.chain;
-               }
-
-               if(!found)
-               {
-                       LOG_INFO(strcat("NOTICE: Can not find waypoint at ", vtos(wp_to_pos), ". Path skipped\n"));
-                       continue;
-               }
-
-               ++c;
-               waypoint_addlink(wp_from, wp_to);
-               wp_from.wphardwired = true;
-               wp_to.wphardwired = true;
-       }
-
-       fclose(file);
-
-       LOG_TRACE("loaded ", ftos(c), " waypoint links from maps/", mapname, ".waypoints.hardwired\n");
-}
-
-entity waypoint_get_link(entity w, float i)
-{
-       switch(i)
-       {
-               case  0:return w.wp00;
-               case  1:return w.wp01;
-               case  2:return w.wp02;
-               case  3:return w.wp03;
-               case  4:return w.wp04;
-               case  5:return w.wp05;
-               case  6:return w.wp06;
-               case  7:return w.wp07;
-               case  8:return w.wp08;
-               case  9:return w.wp09;
-               case 10:return w.wp10;
-               case 11:return w.wp11;
-               case 12:return w.wp12;
-               case 13:return w.wp13;
-               case 14:return w.wp14;
-               case 15:return w.wp15;
-               case 16:return w.wp16;
-               case 17:return w.wp17;
-               case 18:return w.wp18;
-               case 19:return w.wp19;
-               case 20:return w.wp20;
-               case 21:return w.wp21;
-               case 22:return w.wp22;
-               case 23:return w.wp23;
-               case 24:return w.wp24;
-               case 25:return w.wp25;
-               case 26:return w.wp26;
-               case 27:return w.wp27;
-               case 28:return w.wp28;
-               case 29:return w.wp29;
-               case 30:return w.wp30;
-               case 31:return w.wp31;
-               default:return NULL;
-       }
-}
-
-// Save all waypoint links to a file
-void waypoint_save_links()
-{
-       string filename = sprintf("maps/%s.waypoints.cache", mapname);
-       int file = fopen(filename, FILE_WRITE);
-       if (file < 0)
-       {
-               LOG_INFOF("waypoint link save to %s failed\n", filename);
-               return;
-       }
-
-       int c = 0;
-       IL_EACH(g_waypoints, true,
-       {
-               for(int j = 0; j < 32; ++j)
-               {
-                       entity link = waypoint_get_link(it, j);
-                       if(link)
-                       {
-                               string s = strcat(vtos(it.origin), "*", vtos(link.origin), "\n");
-                               fputs(file, s);
-                               ++c;
-                       }
-               }
-       });
-       fclose(file);
-       botframe_cachedwaypointlinks = true;
-
-       LOG_INFOF("saved %d waypoint links to maps/%s.waypoints.cache\n", c, mapname);
-}
-
-// save waypoints to gamedir/data/maps/mapname.waypoints
-void waypoint_saveall()
-{
-       string filename = sprintf("maps/%s.waypoints", mapname);
-       int file = fopen(filename, FILE_WRITE);
-       if (file < 0)
-       {
-               waypoint_save_links(); // save anyway?
-               botframe_loadedforcedlinks = false;
-
-               LOG_INFOF("waypoint links: save to %s failed\n", filename);
-               return;
-       }
-
-       int c = 0;
-       IL_EACH(g_waypoints, true,
-       {
-               if(it.wpflags & WAYPOINTFLAG_GENERATED)
-                       continue;
-
-               for(int j = 0; j < 32; ++j)
-               {
-                       string s;
-                       s = strcat(vtos(it.origin + it.mins), "\n");
-                       s = strcat(s, vtos(it.origin + it.maxs));
-                       s = strcat(s, "\n");
-                       s = strcat(s, ftos(it.wpflags));
-                       s = strcat(s, "\n");
-                       fputs(file, s);
-                       ++c;
-               }
-       });
-       fclose(file);
-       waypoint_save_links();
-       botframe_loadedforcedlinks = false;
-
-       LOG_INFOF("saved %d waypoints to maps/%s.waypoints\n", c, mapname);
-}
-
-// load waypoints from file
-float waypoint_loadall()
-{
-       string filename, s;
-       float file, cwp, cwb, fl;
-       vector m1, m2;
-       cwp = 0;
-       cwb = 0;
-       filename = strcat("maps/", mapname);
-       filename = strcat(filename, ".waypoints");
-       file = fopen(filename, FILE_READ);
-       if (file >= 0)
-       {
-               while ((s = fgets(file)))
-               {
-                       m1 = stov(s);
-                       s = fgets(file);
-                       if (!s)
-                               break;
-                       m2 = stov(s);
-                       s = fgets(file);
-                       if (!s)
-                               break;
-                       fl = stof(s);
-                       waypoint_spawn(m1, m2, fl);
-                       if (m1 == m2)
-                               cwp = cwp + 1;
-                       else
-                               cwb = cwb + 1;
-               }
-               fclose(file);
-               LOG_TRACE("loaded ", ftos(cwp), " waypoints and ", ftos(cwb), " wayboxes from maps/", mapname, ".waypoints\n");
-       }
-       else
-       {
-               LOG_TRACE("waypoint load from ", filename, " failed\n");
-       }
-       return cwp + cwb;
-}
-
-vector waypoint_fixorigin(vector position)
-{
-       tracebox(position + '0 0 1' * (1 - STAT(PL_MIN, NULL).z), STAT(PL_MIN, NULL), STAT(PL_MAX, NULL), position + '0 0 -512', MOVE_NOMONSTERS, NULL);
-       if(trace_fraction < 1)
-               position = trace_endpos;
-       //traceline(position, position + '0 0 -512', MOVE_NOMONSTERS, NULL);
-       //print("position is ", ftos(trace_endpos_z - position_z), " above solid\n");
-       return position;
-}
-
-void waypoint_spawnforitem_force(entity e, vector org)
-{
-       // Fix the waypoint altitude if necessary
-       org = waypoint_fixorigin(org);
-
-       // don't spawn an item spawnfunc_waypoint if it already exists
-       IL_EACH(g_waypoints, true,
-       {
-               if(it.wpisbox)
-               {
-                       if(boxesoverlap(org, org, it.absmin, it.absmax))
-                       {
-                               e.nearestwaypoint = it;
-                               return;
-                       }
-               }
-               else
-               {
-                       if(vdist(it.origin - org, <, 16))
-                       {
-                               e.nearestwaypoint = it;
-                               return;
-                       }
-               }
-       });
-
-       e.nearestwaypoint = waypoint_spawn(org, org, WAYPOINTFLAG_GENERATED | WAYPOINTFLAG_ITEM);
-}
-
-void waypoint_spawnforitem(entity e)
-{
-       if(!bot_waypoints_for_items)
-               return;
-
-       waypoint_spawnforitem_force(e, e.origin);
-}
-
-void waypoint_spawnforteleporter_boxes(entity e, vector org1, vector org2, vector destination1, vector destination2, float timetaken)
-{
-       entity w;
-       entity dw;
-       w = waypoint_spawn(org1, org2, WAYPOINTFLAG_GENERATED | WAYPOINTFLAG_TELEPORT | WAYPOINTFLAG_NORELINK);
-       dw = waypoint_spawn(destination1, destination2, WAYPOINTFLAG_GENERATED);
-       // one way link to the destination
-       w.wp00 = dw;
-       w.wp00mincost = timetaken; // this is just for jump pads
-       // the teleporter's nearest spawnfunc_waypoint is this one
-       // (teleporters are not goals, so this is probably useless)
-       e.nearestwaypoint = w;
-       e.nearestwaypointtimeout = time + 1000000000;
-}
-
-void waypoint_spawnforteleporter_v(entity e, vector org, vector destination, float timetaken)
-{
-       org = waypoint_fixorigin(org);
-       destination = waypoint_fixorigin(destination);
-       waypoint_spawnforteleporter_boxes(e, org, org, destination, destination, timetaken);
-}
-
-void waypoint_spawnforteleporter(entity e, vector destination, float timetaken)
-{
-       destination = waypoint_fixorigin(destination);
-       waypoint_spawnforteleporter_boxes(e, e.absmin, e.absmax, destination, destination, timetaken);
-}
-
-entity waypoint_spawnpersonal(entity this, vector position)
-{
-       entity w;
-
-       // drop the waypoint to a proper location:
-       //   first move it up by a player height
-       //   then move it down to hit the floor with player bbox size
-       position = waypoint_fixorigin(position);
-
-       w = waypoint_spawn(position, position, WAYPOINTFLAG_GENERATED | WAYPOINTFLAG_PERSONAL);
-       w.nearestwaypoint = NULL;
-       w.nearestwaypointtimeout = 0;
-       w.owner = this;
-
-       waypoint_schedulerelink(w);
-
-       return w;
-}
-
-void botframe_showwaypointlinks()
-{
-       if (time < botframe_waypointeditorlightningtime)
-               return;
-       botframe_waypointeditorlightningtime = time + 0.5;
-       FOREACH_CLIENT(IS_PLAYER(it) && !it.isbot,
-       {
-               if(IS_ONGROUND(it) || it.waterlevel > WATERLEVEL_NONE)
-               {
-                       //navigation_testtracewalk = true;
-                       entity head = navigation_findnearestwaypoint(it, false);
-               //      print("currently selected WP is ", etos(head), "\n");
-                       //navigation_testtracewalk = false;
-                       if (head)
-                       {
-                               entity w;
-                               w = head     ;if (w) te_lightning2(NULL, w.origin, it.origin);
-                               w = head.wp00;if (w) te_lightning2(NULL, w.origin, head.origin);
-                               w = head.wp01;if (w) te_lightning2(NULL, w.origin, head.origin);
-                               w = head.wp02;if (w) te_lightning2(NULL, w.origin, head.origin);
-                               w = head.wp03;if (w) te_lightning2(NULL, w.origin, head.origin);
-                               w = head.wp04;if (w) te_lightning2(NULL, w.origin, head.origin);
-                               w = head.wp05;if (w) te_lightning2(NULL, w.origin, head.origin);
-                               w = head.wp06;if (w) te_lightning2(NULL, w.origin, head.origin);
-                               w = head.wp07;if (w) te_lightning2(NULL, w.origin, head.origin);
-                               w = head.wp08;if (w) te_lightning2(NULL, w.origin, head.origin);
-                               w = head.wp09;if (w) te_lightning2(NULL, w.origin, head.origin);
-                               w = head.wp10;if (w) te_lightning2(NULL, w.origin, head.origin);
-                               w = head.wp11;if (w) te_lightning2(NULL, w.origin, head.origin);
-                               w = head.wp12;if (w) te_lightning2(NULL, w.origin, head.origin);
-                               w = head.wp13;if (w) te_lightning2(NULL, w.origin, head.origin);
-                               w = head.wp14;if (w) te_lightning2(NULL, w.origin, head.origin);
-                               w = head.wp15;if (w) te_lightning2(NULL, w.origin, head.origin);
-                               w = head.wp16;if (w) te_lightning2(NULL, w.origin, head.origin);
-                               w = head.wp17;if (w) te_lightning2(NULL, w.origin, head.origin);
-                               w = head.wp18;if (w) te_lightning2(NULL, w.origin, head.origin);
-                               w = head.wp19;if (w) te_lightning2(NULL, w.origin, head.origin);
-                               w = head.wp20;if (w) te_lightning2(NULL, w.origin, head.origin);
-                               w = head.wp21;if (w) te_lightning2(NULL, w.origin, head.origin);
-                               w = head.wp22;if (w) te_lightning2(NULL, w.origin, head.origin);
-                               w = head.wp23;if (w) te_lightning2(NULL, w.origin, head.origin);
-                               w = head.wp24;if (w) te_lightning2(NULL, w.origin, head.origin);
-                               w = head.wp25;if (w) te_lightning2(NULL, w.origin, head.origin);
-                               w = head.wp26;if (w) te_lightning2(NULL, w.origin, head.origin);
-                               w = head.wp27;if (w) te_lightning2(NULL, w.origin, head.origin);
-                               w = head.wp28;if (w) te_lightning2(NULL, w.origin, head.origin);
-                               w = head.wp29;if (w) te_lightning2(NULL, w.origin, head.origin);
-                               w = head.wp30;if (w) te_lightning2(NULL, w.origin, head.origin);
-                               w = head.wp31;if (w) te_lightning2(NULL, w.origin, head.origin);
-                       }
-               }
-       });
-}
-
-float botframe_autowaypoints_fixdown(vector v)
-{
-       tracebox(v, STAT(PL_MIN, NULL), STAT(PL_MAX, NULL), v + '0 0 -64', MOVE_NOMONSTERS, NULL);
-       if(trace_fraction >= 1)
-               return 0;
-       return 1;
-}
-
-float botframe_autowaypoints_createwp(vector v, entity p, .entity fld, float f)
-{
-       IL_EACH(g_waypoints, boxesoverlap(v - '32 32 32', v + '32 32 32', it.absmin, it.absmax),
-       {
-               // if a matching spawnfunc_waypoint already exists, don't add a duplicate
-               return 0;
-       });
-
-       waypoint_schedulerelink(p.(fld) = waypoint_spawn(v, v, f));
-       return 1;
-}
-
-// return value:
-//    1 = WP created
-//    0 = no action needed
-//   -1 = temp fail, try from world too
-//   -2 = permanent fail, do not retry
-float botframe_autowaypoints_fix_from(entity p, float walkfromwp, entity wp, .entity fld)
-{
-       // make it possible to go from p to wp, if we can
-       // if wp is NULL, nearest is chosen
-
-       entity w;
-       vector porg;
-       float t, tmin, tmax;
-       vector o;
-       vector save;
-
-       if(!botframe_autowaypoints_fixdown(p.origin))
-               return -2;
-       porg = trace_endpos;
-
-       if(wp)
-       {
-               // if any WP w fulfills wp -> w -> porg and w is closer than wp, then switch from wp to w
-
-               // if wp -> porg, then OK
-               float maxdist;
-               if(navigation_waypoint_will_link(wp.origin, porg, p, walkfromwp, 1050))
-               {
-                       // we may find a better one
-                       maxdist = vlen(wp.origin - porg);
-               }
-               else
-               {
-                       // accept any "good"
-                       maxdist = 2100;
-               }
-
-               float bestdist = maxdist;
-               IL_EACH(g_waypoints, it != wp && !(it.wpflags & WAYPOINTFLAG_NORELINK),
-               {
-                       float d = vlen(wp.origin - it.origin) + vlen(it.origin - porg);
-                       if(d < bestdist)
-                       if(navigation_waypoint_will_link(wp.origin, it.origin, p, walkfromwp, 1050))
-                       if(navigation_waypoint_will_link(it.origin, porg, p, walkfromwp, 1050))
-                       {
-                               bestdist = d;
-                               p.(fld) = it;
-                       }
-               });
-               if(bestdist < maxdist)
-               {
-                       LOG_INFO("update chain to new nearest WP ", etos(p.(fld)), "\n");
-                       return 0;
-               }
-
-               if(bestdist < 2100)
-               {
-                       // we know maxdist < 2100
-                       // so wp -> porg is still valid
-                       // all is good
-                       p.(fld) = wp;
-                       return 0;
-               }
-
-               // otherwise, no existing WP can fix our issues
-       }
-       else
-       {
-               save = p.origin;
-               setorigin(p, porg);
-               w = navigation_findnearestwaypoint(p, walkfromwp);
-               setorigin(p, save);
-               if(w)
-               {
-                       p.(fld) = w;
-                       return 0;
-               }
-       }
-
-       tmin = 0;
-       tmax = 1;
-       for (;;)
-       {
-               if(tmax - tmin < 0.001)
-               {
-                       // did not get a good candidate
-                       return -1;
-               }
-
-               t = (tmin + tmax) * 0.5;
-               o = antilag_takebackorigin(p, CS(p), time - t);
-               if(!botframe_autowaypoints_fixdown(o))
-                       return -2;
-               o = trace_endpos;
-
-               if(wp)
-               {
-                       if(!navigation_waypoint_will_link(wp.origin, o, p, walkfromwp, 1050))
-                       {
-                               // we cannot walk from wp.origin to o
-                               // get closer to tmax
-                               tmin = t;
-                               continue;
-                       }
-               }
-               else
-               {
-                       save = p.origin;
-                       setorigin(p, o);
-                       w = navigation_findnearestwaypoint(p, walkfromwp);
-                       setorigin(p, save);
-                       if(!w)
-                       {
-                               // we cannot walk from any WP to o
-                               // get closer to tmax
-                               tmin = t;
-                               continue;
-                       }
-               }
-
-               // if we get here, o is valid regarding waypoints
-               // check if o is connected right to the player
-               // we break if it succeeds, as that means o is a good waypoint location
-               if(navigation_waypoint_will_link(o, porg, p, walkfromwp, 1050))
-                       break;
-
-               // o is no good, we need to get closer to the player
-               tmax = t;
-       }
-
-       LOG_INFO("spawning a waypoint for connecting to ", etos(wp), "\n");
-       botframe_autowaypoints_createwp(o, p, fld, 0);
-       return 1;
-}
-
-// automatically create missing waypoints
-.entity botframe_autowaypoints_lastwp0, botframe_autowaypoints_lastwp1;
-void botframe_autowaypoints_fix(entity p, float walkfromwp, .entity fld)
-{
-       float r = botframe_autowaypoints_fix_from(p, walkfromwp, p.(fld), fld);
-       if(r != -1)
-               return;
-       r = botframe_autowaypoints_fix_from(p, walkfromwp, NULL, fld);
-       if(r != -1)
-               return;
-
-       LOG_INFO("emergency: got no good nearby WP to build a link from, starting a new chain\n");
-       if(!botframe_autowaypoints_fixdown(p.origin))
-               return; // shouldn't happen, caught above
-       botframe_autowaypoints_createwp(trace_endpos, p, fld, WAYPOINTFLAG_PROTECTED);
-}
-
-void botframe_deleteuselesswaypoints()
-{
-       FOREACH_ENTITY_FLOAT(bot_pickup, true,
-       {
-               // NOTE: this protects waypoints if they're the ONLY nearest
-               // waypoint. That's the intention.
-               navigation_findnearestwaypoint(it, false);  // Walk TO item.
-               navigation_findnearestwaypoint(it, true);  // Walk FROM item.
-       });
-       IL_EACH(g_waypoints, true,
-       {
-               it.wpflags |= WAYPOINTFLAG_DEAD_END;
-               it.wpflags &= ~WAYPOINTFLAG_USEFUL;
-               // WP is useful if:
-               if (it.wpflags & WAYPOINTFLAG_ITEM)
-                       it.wpflags |= WAYPOINTFLAG_USEFUL;
-               if (it.wpflags & WAYPOINTFLAG_TELEPORT)
-                       it.wpflags |= WAYPOINTFLAG_USEFUL;
-               if (it.wpflags & WAYPOINTFLAG_PROTECTED)
-                       it.wpflags |= WAYPOINTFLAG_USEFUL;
-               // b) WP is closest WP for an item/spawnpoint/other entity
-               //    This has been done above by protecting these WPs.
-       });
-       // c) There are w1, w, w2 so that w1 -> w, w -> w2 and not w1 -> w2.
-       IL_EACH(g_waypoints, !(it.wpflags & WAYPOINTFLAG_PERSONAL),
-       {
-               for (int m = 0; m < 32; ++m)
-               {
-                       entity w = waypoint_get_link(it, m);
-                       if (!w)
-                               break;
-                       if (w.wpflags & WAYPOINTFLAG_PERSONAL)
-                               continue;
-                       if (w.wpflags & WAYPOINTFLAG_USEFUL)
-                               continue;
-                       for (int j = 0; j < 32; ++j)
-                       {
-                               entity w2 = waypoint_get_link(w, j);
-                               if (!w2)
-                                       break;
-                               if (it == w2)
-                                       continue;
-                               if (w2.wpflags & WAYPOINTFLAG_PERSONAL)
-                                       continue;
-                               // If we got here, it != w2 exist with it -> w
-                               // and w -> w2. That means the waypoint is not
-                               // a dead end.
-                               w.wpflags &= ~WAYPOINTFLAG_DEAD_END;
-                               for (int k = 0; k < 32; ++k)
-                               {
-                                       if (waypoint_get_link(it, k) == w2)
-                                               continue;
-                                       // IF WE GET HERE, w is proven useful
-                                       // to get from it to w2!
-                                       w.wpflags |= WAYPOINTFLAG_USEFUL;
-                                       goto next;
-                               }
-                       }
-LABEL(next)
-               }
-       });
-       // d) The waypoint is a dead end. Dead end waypoints must be kept as
-       //     they are needed to complete routes while autowaypointing.
-
-       IL_EACH(g_waypoints, !(it.wpflags & (WAYPOINTFLAG_USEFUL | WAYPOINTFLAG_DEAD_END)),
-       {
-               LOG_INFOF("Removed a waypoint at %v. Try again for more!\n", it.origin);
-               te_explosion(it.origin);
-               waypoint_remove(it);
-               break;
-       });
-
-       IL_EACH(g_waypoints, true,
-       {
-               it.wpflags &= ~(WAYPOINTFLAG_USEFUL | WAYPOINTFLAG_DEAD_END); // temp flag
-       });
-}
-
-void botframe_autowaypoints()
-{
-       FOREACH_CLIENT(IS_PLAYER(it) && IS_REAL_CLIENT(it) && !IS_DEAD(it), LAMBDA(
-               // going back is broken, so only fix waypoints to walk TO the player
-               //botframe_autowaypoints_fix(p, false, botframe_autowaypoints_lastwp0);
-               botframe_autowaypoints_fix(it, true, botframe_autowaypoints_lastwp1);
-               //te_explosion(p.botframe_autowaypoints_lastwp0.origin);
-       ));
-
-       if (autocvar_g_waypointeditor_auto >= 2) {
-               botframe_deleteuselesswaypoints();
-       }
-}
-
diff --git a/qcsrc/server/bot/waypoints.qh b/qcsrc/server/bot/waypoints.qh
deleted file mode 100644 (file)
index 23c0fa6..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-#pragma once
-/*
- * Globals and Fields
- */
-
-const int WAYPOINTFLAG_GENERATED = BIT(23);
-const int WAYPOINTFLAG_ITEM = BIT(22);
-const int WAYPOINTFLAG_TELEPORT = BIT(21);
-const int WAYPOINTFLAG_NORELINK = BIT(20);
-const int WAYPOINTFLAG_PERSONAL = BIT(19);
-const int WAYPOINTFLAG_PROTECTED = BIT(18);  // Useless WP detection never kills these.
-const int WAYPOINTFLAG_USEFUL = BIT(17);  // Useless WP detection temporary flag.
-const int WAYPOINTFLAG_DEAD_END = BIT(16);  // Useless WP detection temporary flag.
-
-// fields you can query using prvm_global server to get some statistics about waypoint linking culling
-float relink_total, relink_walkculled, relink_pvsculled, relink_lengthculled;
-
-float botframe_waypointeditorlightningtime;
-float botframe_loadedforcedlinks;
-float botframe_cachedwaypointlinks;
-
-.entity wp00, wp01, wp02, wp03, wp04, wp05, wp06, wp07, wp08, wp09, wp10, wp11, wp12, wp13, wp14, wp15;
-.entity wp16, wp17, wp18, wp19, wp20, wp21, wp22, wp23, wp24, wp25, wp26, wp27, wp28, wp29, wp30, wp31;
-
-// itemscore = (howmuchmoreIwant / howmuchIcanwant) / itemdistance
-.float wp00mincost, wp01mincost, wp02mincost, wp03mincost, wp04mincost, wp05mincost, wp06mincost, wp07mincost;
-.float wp08mincost, wp09mincost, wp10mincost, wp11mincost, wp12mincost, wp13mincost, wp14mincost, wp15mincost;
-.float wp16mincost, wp17mincost, wp18mincost, wp19mincost, wp20mincost, wp21mincost, wp22mincost, wp23mincost;
-.float wp24mincost, wp25mincost, wp26mincost, wp27mincost, wp28mincost, wp29mincost, wp30mincost, wp31mincost;
-
-.float wpfire, wpcost, wpconsidered, wpisbox, wplinked, wphardwired;
-.int wpflags;
-
-.vector wpnearestpoint;
-
-/*
- * Functions
- */
-
-spawnfunc(waypoint);
-void waypoint_addlink(entity from, entity to);
-void waypoint_think(entity this);
-void waypoint_clearlinks(entity wp);
-void waypoint_schedulerelink(entity wp);
-
-void waypoint_remove(entity e);
-void waypoint_removeall();
-void waypoint_schedulerelinkall();
-void waypoint_load_links_hardwired();
-void waypoint_save_links();
-void waypoint_saveall();
-
-void waypoint_spawnforitem_force(entity e, vector org);
-void waypoint_spawnforitem(entity e);
-void waypoint_spawnforteleporter(entity e, vector destination, float timetaken);
-void waypoint_spawnforteleporter_v(entity e, vector org, vector destination, float timetaken);
-void botframe_showwaypointlinks();
-
-float waypoint_loadall();
-float waypoint_load_links();
-
-entity waypoint_spawn(vector m1, vector m2, float f);
-entity waypoint_spawnpersonal(entity this, vector position);
-
-vector waypoint_fixorigin(vector position);
-
-void botframe_autowaypoints();
index 163337e036ce7a22ceeab2d4b5aca3b72f192fa7..5097bd8a145bf3254beb73c947e9d8ccba9f0f81 100644 (file)
@@ -260,7 +260,7 @@ void CampaignPostIntermission()
        if(campaign_won && campaign_entries < 2)
        {
                // last map won!
-               LOG_DEBUG("^2test run: campaign looks GOOD\n");
+               LOG_DEBUG("^2test run: campaign looks GOOD");
                localcmd("togglemenu 1\n");
                CampaignFile_Unload();
                return;
index 86f46b067f28679d19958c57feac658144e364dc..f31b3e5c2fba778c65c908de8aba6d2ef89d2528 100644 (file)
@@ -240,7 +240,7 @@ float CheatImpulse(entity this, int imp)
                                        sprint(this, "Emergency teleport used info_autoscreenshot location\n");
                                        setorigin(this, e.origin);
                                        this.angles = e.angles;
-                                       remove(e);
+                                       delete(e);
                                        // should we? this.angles_x = -this.angles_x;
                                        this.fixangle = true;
                                        this.velocity = '0 0 0';
@@ -274,7 +274,7 @@ float CheatImpulse(entity this, int imp)
                        e2 = spawn();
                        setorigin(e2, e.origin);
                        RadiusDamage(e2, this, 1000, 0, 128, NULL, NULL, 500, DEATH_CHEAT.m_id, e);
-                       remove(e2);
+                       delete(e2);
 
                        LOG_INFO("404 Sportsmanship not found.\n");
                        DID_CHEAT();
@@ -323,7 +323,7 @@ float CheatCommand(entity this, int argc)
                                // arguments:
                                //   effectname
                                effectnum = _particleeffectnum(argv(1));
-                               W_SetupShot(this, false, false, SND_Null, CH_WEAPON_A, 0);
+                               W_SetupShot(this, weaponentities[0], false, false, SND_Null, CH_WEAPON_A, 0);
                                traceline(w_shotorg, w_shotorg + w_shotdir * MAX_SHOT_DISTANCE, MOVE_NORMAL, this);
                                __trailparticles(this, effectnum, w_shotorg, trace_endpos);
                                DID_CHEAT();
@@ -338,7 +338,7 @@ float CheatCommand(entity this, int argc)
                                // arguments:
                                //   modelname mode
                                f = stof(argv(2));
-                               W_SetupShot(this, false, false, SND_Null, CH_WEAPON_A, 0);
+                               W_SetupShot(this, weaponentities[0], false, false, SND_Null, CH_WEAPON_A, 0);
                                traceline(w_shotorg, w_shotorg + w_shotdir * 2048, MOVE_NORMAL, this);
                                if((trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT) || trace_fraction == 1)
                                {
@@ -364,7 +364,7 @@ float CheatCommand(entity this, int argc)
                                                tracebox(e.origin, e.mins, e.maxs, e.origin, MOVE_NORMAL, e);
                                                if(trace_startsolid)
                                                {
-                                                       remove(e);
+                                                       delete(e);
                                                        sprint(this, "cannot make stuff there (no space)\n");
                                                }
                                                else
@@ -480,13 +480,13 @@ float CheatCommand(entity this, int argc)
                                RandomSelection_Add(e, 0, string_null, 1, 1 / vlen(e.origin + (e.mins + e.maxs) * 0.5 - trace_endpos));
                        if(RandomSelection_chosen_ent)
                        {
-                               remove(RandomSelection_chosen_ent.killindicator.killindicator);
-                               remove(RandomSelection_chosen_ent.killindicator);
+                               delete(RandomSelection_chosen_ent.killindicator.killindicator);
+                               delete(RandomSelection_chosen_ent.killindicator);
                                if(RandomSelection_chosen_ent.aiment)
-                                       remove(RandomSelection_chosen_ent.aiment);
+                                       delete(RandomSelection_chosen_ent.aiment);
                                if(RandomSelection_chosen_ent.enemy)
-                                       remove(RandomSelection_chosen_ent.enemy);
-                               remove(RandomSelection_chosen_ent);
+                                       delete(RandomSelection_chosen_ent.enemy);
+                               delete(RandomSelection_chosen_ent);
                        }
                        DID_CHEAT();
                        break;
@@ -604,15 +604,15 @@ float CheatCommand(entity this, int argc)
                case "drag_clear":
                        IS_CHEAT(this, 0, argc, 0);
                        for(entity e = NULL; (e = find(e, classname, "dragbox_box")); )
-                               remove(e);
+                               delete(e);
                        for(entity e = NULL; (e = find(e, classname, "dragbox_corner_1")); )
-                               remove(e);
+                               delete(e);
                        for(entity e = NULL; (e = find(e, classname, "dragbox_corner_2")); )
-                               remove(e);
+                               delete(e);
                        for(entity e = NULL; (e = find(e, classname, "dragpoint")); )
-                               remove(e);
+                               delete(e);
                        for(entity e = NULL; (e = find(e, classname, "drag_digit")); )
-                               remove(e);
+                               delete(e);
                        DID_CHEAT();
                        break;
                case "god":
@@ -675,7 +675,7 @@ float CheatCommand(entity this, int argc)
                        entity e = spawn();
                        e.target = argv(1);
                        SUB_UseTargets(e, this, NULL);
-                       remove(e);
+                       delete(e);
                        DID_CHEAT();
                        break;
                case "killtarget":
@@ -683,7 +683,7 @@ float CheatCommand(entity this, int argc)
                        entity e2 = spawn();
                        e2.killtarget = argv(1);
                        SUB_UseTargets(e2, this, NULL);
-                       remove(e2);
+                       delete(e2);
                        DID_CHEAT();
                        break;
                case "teleporttotarget":
@@ -695,7 +695,7 @@ float CheatCommand(entity this, int argc)
                        if(!wasfreed(ent))
                        {
                                Simple_TeleportPlayer(ent, this);
-                               remove(ent);
+                               delete(ent);
                                DID_CHEAT();
                        }
                        break;
index fe307fc01ac5872538b0ffd5aada4cdd964cab24..0a608e979bff5da3e4b535fed7019bc0a9fb2301 100644 (file)
@@ -19,8 +19,7 @@
 #include "campaign.qh"
 #include "command/common.qh"
 
-#include "bot/bot.qh"
-#include "bot/navigation.qh"
+#include "bot/api.qh"
 
 #include "../common/ent_cs.qh"
 #include <common/state.qh>
@@ -75,6 +74,30 @@ void send_CSQC_teamnagger() {
        WriteHeader(MSG_BROADCAST, TE_CSQC_TEAMNAGGER);
 }
 
+int CountSpectators(entity player, entity to)
+{
+       if(!player) { return 0; } // not sure how, but best to be safe
+
+       int spec_count = 0;
+
+       FOREACH_CLIENT(IS_REAL_CLIENT(it) && IS_SPEC(it) && it != to && it.enemy == player,
+       {
+               spec_count++;
+       });
+
+       return spec_count;
+}
+
+void WriteSpectators(entity player, entity to)
+{
+       if(!player) { return; } // not sure how, but best to be safe
+
+       FOREACH_CLIENT(IS_REAL_CLIENT(it) && IS_SPEC(it) && it != to && it.enemy == player,
+       {
+               WriteByte(MSG_ENTITY, num_for_edict(it));
+       });
+}
+
 bool ClientData_Send(entity this, entity to, int sf)
 {
        assert(to == this.owner, return false);
@@ -87,6 +110,7 @@ bool ClientData_Send(entity this, entity to, int sf)
        if (to.spectatee_status)    sf |= 2; // spectator ent number follows
        if (e.zoomstate)            sf |= 4; // zoomed
        if (e.porto_v_angle_held)   sf |= 8; // angles held
+       if (autocvar_sv_showspectators) sf |= 16; // show spectators
 
        WriteHeader(MSG_ENTITY, ENT_CLIENT_CLIENTDATA);
        WriteByte(MSG_ENTITY, sf);
@@ -100,6 +124,14 @@ bool ClientData_Send(entity this, entity to, int sf)
                WriteAngle(MSG_ENTITY, e.v_angle.x);
                WriteAngle(MSG_ENTITY, e.v_angle.y);
        }
+
+       if(sf & 16)
+       {
+               float specs = CountSpectators(e, to);
+               WriteByte(MSG_ENTITY, specs);
+               WriteSpectators(e, to);
+       }
+
        return true;
 }
 
@@ -112,7 +144,7 @@ void ClientData_Attach(entity this)
 
 void ClientData_Detach(entity this)
 {
-       remove(this.clientdata);
+       delete(this.clientdata);
        this.clientdata = NULL;
 }
 
@@ -215,7 +247,7 @@ void PutObserverInServer(entity this)
                // needed for player sounds
                this.model = "";
                FixPlayermodel(this);
-        } 
+        }
         setmodel(this, MDL_Null);
         setsize(this, STAT(PL_CROUCH_MIN, NULL), STAT(PL_CROUCH_MAX, NULL));
         this.view_ofs = '0 0 0';
@@ -224,6 +256,7 @@ void PutObserverInServer(entity this)
     RemoveGrapplingHook(this);
        Portal_ClearAll(this);
        Unfreeze(this);
+       SetSpectatee(this, NULL);
 
        if (this.alivetime)
        {
@@ -318,6 +351,10 @@ void PutObserverInServer(entity this)
        this.oldvelocity = this.velocity;
        this.fire_endtime = -1;
        this.event_damage = func_null;
+
+       STAT(ACTIVEWEAPON, this) = WEP_Null.m_id;
+       STAT(SWITCHINGWEAPON, this) = WEP_Null.m_id;
+       STAT(SWITCHWEAPON, this) = WEP_Null.m_id;
 }
 
 int player_getspecies(entity this)
@@ -463,7 +500,7 @@ void PutClientInServer(entity this)
                PutObserverInServer(this);
        } else if (IS_PLAYER(this)) {
                if (this.vehicle) vehicles_exit(this.vehicle, VHEF_RELEASE);
-               
+
                PlayerState_attach(this);
                accuracy_resend(this);
 
@@ -639,7 +676,7 @@ void PutClientInServer(entity this)
                if (autocvar_spawn_debug)
                {
                        sprint(this, strcat("spawnpoint origin:  ", vtos(spot.origin), "\n"));
-                       remove(spot); // usefull for checking if there are spawnpoints, that let drop through the floor
+                       delete(spot); // usefull for checking if there are spawnpoints, that let drop through the floor
                }
 
                PS(this).m_switchweapon = w_getbestweapon(this);
@@ -797,7 +834,7 @@ void ClientKill_Now(entity this)
        }
 
        if(this.killindicator && !wasfreed(this.killindicator))
-               remove(this.killindicator);
+               delete(this.killindicator);
 
        this.killindicator = NULL;
 
@@ -814,14 +851,14 @@ void KillIndicator_Think(entity this)
        if (gameover)
        {
                this.owner.killindicator = NULL;
-               remove(this);
+               delete(this);
                return;
        }
 
        if (this.owner.alpha < 0 && !this.owner.vehicle)
        {
                this.owner.killindicator = NULL;
-               remove(this);
+               delete(this);
                return;
        }
 
@@ -1187,6 +1224,8 @@ void ClientDisconnect(entity this)
 
        Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_QUIT_DISCONNECT, this.netname);
 
+       SetSpectatee(this, NULL);
+
     MUTATOR_CALLHOOK(ClientDisconnect, this);
 
        ClientState_detach(this);
@@ -1201,8 +1240,8 @@ void ClientDisconnect(entity this)
 
        this.flags &= ~FL_CLIENT;
 
-       if (this.chatbubbleentity) remove(this.chatbubbleentity);
-       if (this.killindicator) remove(this.killindicator);
+       if (this.chatbubbleentity) delete(this.chatbubbleentity);
+       if (this.killindicator) delete(this.killindicator);
 
        WaypointSprite_PlayerGone(this);
 
@@ -1211,7 +1250,7 @@ void ClientDisconnect(entity this)
        if (this.netname_previous) strunzone(this.netname_previous);
        if (this.clientstatus) strunzone(this.clientstatus);
        if (this.weaponorder_byimpulse) strunzone(this.weaponorder_byimpulse);
-       if (this.personal) remove(this.personal);
+       if (this.personal) delete(this.personal);
 
        this.playerid = 0;
        ReadyCount();
@@ -1225,7 +1264,7 @@ void ChatBubbleThink(entity this)
        {
                if(this.owner) // but why can that ever be NULL?
                        this.owner.chatbubbleentity = NULL;
-               remove(this);
+               delete(this);
                return;
        }
 
@@ -1672,6 +1711,8 @@ bool SpectateSet(entity this)
        if(!IS_PLAYER(this.enemy))
                return false;
 
+       ClientData_Touch(this.enemy);
+
        msg_entity = this;
        WriteByte(MSG_ONE, SVC_SETVIEW);
        WriteEntity(MSG_ONE, this.enemy);
@@ -1692,8 +1733,27 @@ void SetSpectatee(entity this, entity spectatee)
 
        // WEAPONTODO
        // these are required to fix the spectator bug with arc
-       if(old_spectatee && old_spectatee.arc_beam) { old_spectatee.arc_beam.SendFlags |= ARC_SF_SETTINGS; }
-       if(this.enemy && this.enemy.arc_beam) { this.enemy.arc_beam.SendFlags |= ARC_SF_SETTINGS; }
+       if(old_spectatee)
+       {
+               for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+               {
+                       .entity weaponentity = weaponentities[slot];
+                       if(old_spectatee.(weaponentity).arc_beam)
+                               old_spectatee.(weaponentity).arc_beam.SendFlags |= ARC_SF_SETTINGS;
+               }
+       }
+       if(this.enemy)
+       {
+               for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+               {
+                       .entity weaponentity = weaponentities[slot];
+                       if(this.enemy.(weaponentity).arc_beam)
+                               this.enemy.(weaponentity).arc_beam.SendFlags |= ARC_SF_SETTINGS;
+               }
+       }
+
+       // needed to update spectator list
+       if(old_spectatee) { ClientData_Touch(old_spectatee); }
 }
 
 bool Spectate(entity this, entity pl)
@@ -1791,6 +1851,8 @@ void LeaveSpectatorMode(entity this)
                {
                        TRANSMUTE(Player, this);
 
+                       SetSpectatee(this, NULL);
+
                        if(autocvar_g_campaign || autocvar_g_balance_teams)
                                { JoinBestTeam(this, false, true); }
 
@@ -2283,7 +2345,6 @@ void PlayerPreThink (entity this)
                this.prevorigin = this.origin;
 
                bool do_crouch = PHYS_INPUT_BUTTON_CROUCH(this);
-        .entity weaponentity = weaponentities[0]; // TODO: unhardcode
                if (this.hook.state) {
                        do_crouch = false;
                } else if (this.waterlevel >= WATERLEVEL_SWIMMING) {
@@ -2292,10 +2353,6 @@ void PlayerPreThink (entity this)
                        do_crouch = false;
                } else if (STAT(FROZEN, this)) {
                        do_crouch = false;
-        } else if ((PS(this).m_weapon.spawnflags & WEP_TYPE_MELEE_PRI) && this.(weaponentity).wframe == WFRAME_FIRE1 && time < this.(weaponentity).weapon_nextthink) {
-                       do_crouch = false;
-        } else if ((PS(this).m_weapon.spawnflags & WEP_TYPE_MELEE_SEC) && this.(weaponentity).wframe == WFRAME_FIRE2 && time < this.(weaponentity).weapon_nextthink) {
-                       do_crouch = false;
         }
 
                if (do_crouch) {
@@ -2321,7 +2378,13 @@ void PlayerPreThink (entity this)
                {
                        this.items &= ~this.items_added;
 
-                       W_WeaponFrame(this);
+                       //for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+                       //{
+                               //.entity weaponentity = weaponentities[slot];
+                               //W_WeaponFrame(this, weaponentity);
+                       //}
+                       .entity weaponentity = weaponentities[0]; // TODO
+                       W_WeaponFrame(this, weaponentity);
 
                        this.items_added = 0;
                        if (this.items & ITEM_Jetpack.m_itemid && (this.items & ITEM_JetpackRegen.m_itemid || this.ammo_fuel >= 0.01))
@@ -2428,7 +2491,7 @@ void DrownPlayer(entity this)
 
 void Player_Physics(entity this)
 {
-       this.movetype = ((this.move_qcphysics) ? MOVETYPE_NONE : this.move_movetype);
+       set_movetype(this, ((this.move_qcphysics) ? MOVETYPE_NONE : this.move_movetype));
 
        if(!this.move_qcphysics)
                return;
@@ -2438,7 +2501,7 @@ void Player_Physics(entity this)
        if(mt == MOVETYPE_PUSH || mt == MOVETYPE_FAKEPUSH || mt == MOVETYPE_PHYSICS)
        {
                this.move_qcphysics = false;
-               this.movetype = mt;
+               set_movetype(this, mt);
                return;
        }
 
index d540bb16ac8bcc8aee6484da3b4c850ea853aa51..35ff6e961c61808a8f5f3cdd0f87e288653bd4f5 100644 (file)
@@ -4,31 +4,31 @@ void ClientState_attach(entity this);
 
 CLASS(Client, Object)
     /** Client name */
-    ATTRIB(Client, netname, string, this.netname)
-    ATTRIB(Client, colormap, int, this.colormap)
-    ATTRIB(Client, team, int, this.team)
-    ATTRIB(Client, clientcolors, int, this.clientcolors)
+    ATTRIB(Client, netname, string, this.netname);
+    ATTRIB(Client, colormap, int, this.colormap);
+    ATTRIB(Client, team, int, this.team);
+    ATTRIB(Client, clientcolors, int, this.clientcolors);
     /** Client IP */
-    ATTRIB(Client, netaddress, string, this.netaddress)
-    ATTRIB(Client, playermodel, string, this.playermodel)
-    ATTRIB(Client, playerskin, int, this.playerskin)
+    ATTRIB(Client, netaddress, string, this.netaddress);
+    ATTRIB(Client, playermodel, string, this.playermodel);
+    ATTRIB(Client, playerskin, int, this.playerskin);
 
     /** fingerprint of CA key the player used to authenticate */
-    ATTRIB(Client, crypto_keyfp, string, this.crypto_keyfp)
+    ATTRIB(Client, crypto_keyfp, string, this.crypto_keyfp);
     /** fingerprint of CA key the server used to authenticate to the player */
-    ATTRIB(Client, crypto_mykeyfp, string, this.crypto_mykeyfp)
+    ATTRIB(Client, crypto_mykeyfp, string, this.crypto_mykeyfp);
     /** fingerprint of ID used by the player entity, or string_null if not identified */
-    ATTRIB(Client, crypto_idfp, string, this.crypto_idfp)
+    ATTRIB(Client, crypto_idfp, string, this.crypto_idfp);
     /** set if the player's ID has been signed */
-    ATTRIB(Client, crypto_idfp_signed, bool, this.crypto_idfp_signed)
+    ATTRIB(Client, crypto_idfp_signed, bool, this.crypto_idfp_signed);
     /** the string "AES128" if encrypting, and string_null if plaintext */
-    ATTRIB(Client, crypto_encryptmethod, string, this.crypto_encryptmethod)
+    ATTRIB(Client, crypto_encryptmethod, string, this.crypto_encryptmethod);
     /** the string "HMAC-SHA256" if signing, and string_null if plaintext */
-    ATTRIB(Client, crypto_signmethod, string, this.crypto_signmethod)
+    ATTRIB(Client, crypto_signmethod, string, this.crypto_signmethod);
 
     // custom
 
-    ATTRIB(Client, playerid, int, this.playerid)
+    ATTRIB(Client, playerid, int, this.playerid);
 
     METHOD(Client, m_unwind, bool(Client this));
 
index 5e276c4a3a3a16024b914cec67800e4c65e59841..00c4ec22cd869a0a1cac51f6df9e52be43a52b67 100644 (file)
@@ -1,12 +1,11 @@
 #include "cl_impulse.qh"
 #include "round_handler.qh"
 
-#include "bot/waypoints.qh"
+#include "bot/api.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"
@@ -248,7 +247,7 @@ IMPULSE(weapon_drop)
 {
        if (this.vehicle) return;
        if (IS_DEAD(this)) return;
-       W_ThrowWeapon(this, W_CalculateProjectileVelocity(this, this.velocity, v_forward * 750, false), '0 0 0', true);
+       W_ThrowWeapon(this, weaponentities[0], W_CalculateProjectileVelocity(this, this.velocity, v_forward * 750, false), '0 0 0', true);
 }
 
 IMPULSE(weapon_reload)
@@ -258,8 +257,11 @@ IMPULSE(weapon_reload)
        if (forbidWeaponUse(this)) return;
        Weapon w = PS(this).m_weapon;
        entity actor = this;
-       .entity weaponentity = weaponentities[0]; // TODO: unhardcode
-       w.wr_reload(w, actor, weaponentity);
+       for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+       {
+               .entity weaponentity = weaponentities[slot];
+               w.wr_reload(w, actor, weaponentity);
+       }
 }
 
 void ImpulseCommands(entity this)
@@ -463,7 +465,7 @@ IMPULSE(waypoint_clear_personal)
        WaypointSprite_ClearPersonal(this);
        if (this.personal)
        {
-               remove(this.personal);
+               delete(this.personal);
                this.personal = NULL;
        }
        sprint(this, "personal waypoint cleared\n");
@@ -474,7 +476,7 @@ IMPULSE(waypoint_clear)
        WaypointSprite_ClearOwned(this);
        if (this.personal)
        {
-               remove(this.personal);
+               delete(this.personal);
                this.personal = NULL;
        }
        sprint(this, "all waypoints cleared\n");
index 098a176c8cc1919eb8a2bfedaef7394cbc12a2e4..1ae97c99e5c23020ea6d79fcbd567ce21f721d4f 100644 (file)
@@ -1,6 +1,6 @@
 #include "cl_player.qh"
 
-#include "bot/bot.qh"
+#include "bot/api.qh"
 #include "cheats.qh"
 #include "g_damage.qh"
 #include "g_subs.qh"
@@ -532,7 +532,7 @@ void PlayerDamage(entity this, entity inflictor, entity attacker, float damage,
                // get rid of kill indicator
                if(this.killindicator)
                {
-                       remove(this.killindicator);
+                       delete(this.killindicator);
                        this.killindicator = NULL;
                        if(this.killindicator_teamchange)
                                defer_ClientKill_Now_TeamChange = true;
@@ -559,7 +559,13 @@ void PlayerDamage(entity this, entity inflictor, entity attacker, float damage,
                excess = M_ARGV(4, float);
 
                Weapon wep = PS(this).m_weapon;
-               wep.wr_playerdeath(wep, this);
+               /*for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+               {
+                       .entity weaponentity = weaponentities[slot];
+                       wep.wr_playerdeath(wep, this, weaponentity);
+               }*/
+               .entity weaponentity = weaponentities[0]; // TODO: unhardcode
+               wep.wr_playerdeath(wep, this, weaponentity);
 
                RemoveGrapplingHook(this);
 
index 81dc1a60ea1549d58c4f909b03ff2cbee4b030f6..d980a0f4cf2d42334e070e5d0d12e6b7bc11b8e9 100644 (file)
@@ -189,7 +189,7 @@ void timeout_handler_reset(entity this)
        timeout_time = 0;
        timeout_leadtime = 0;
 
-       remove(this);
+       delete(this);
 }
 
 void timeout_handler_think(entity this)
index b12977823eadf5f2466a6a5ee3d5e59fc3fcc756..71f5e270b1e80cef9e8aa59d2c0285aa3aa84846 100644 (file)
@@ -45,7 +45,7 @@ float FullTraceFraction(vector a, vector mi, vector ma, vector b)
                c = trace_endpos;
        }
 
-       if (n > 200) LOG_TRACE("HOLY SHIT! FullTraceFraction: ", ftos(n), " total traces, ", ftos(m), " iterations\n");
+       if (n > 200) LOG_TRACE("HOLY SHIT! FullTraceFraction: ", ftos(n), " total traces, ", ftos(m), " iterations");
 
        return white / (black + white);
 }
@@ -207,7 +207,7 @@ void RadarMap_Next()
                localcmd(strcat("defer 1 \"sv_cmd radarmap --flags ", ftos(radarmapper.count), strcat(" --res ", ftos(radarmapper.size.x), " ", ftos(radarmapper.size.y), " --sharpen ", ftos(radarmapper.ltime), " --qual ", ftos(radarmapper.size.z)), "\"\n"));
                GotoNextMap(0);
        }
-       remove(radarmapper);
+       delete(radarmapper);
        radarmapper = NULL;
 }
 void RadarMap_Think(entity this)
@@ -253,7 +253,7 @@ void RadarMap_Think(entity this)
                if (this.cnt < 0)
                {
                        LOG_INFO("Error writing ", this.netname, "\n");
-                       remove(this);
+                       delete(this);
                        radarmapper = NULL;
                        return;
                }
@@ -439,7 +439,7 @@ float RadarMap_Make(float argc)
 
                                default:
                                        i = argc;
-                                       remove(radarmapper);
+                                       delete(radarmapper);
                                        radarmapper = NULL;
                                        break;
                        }
index 895318affc8261a3e3da6f16e7be025e7443a506..bb59566d2a7e6da9bdf9231589aba6299f4e8f6f 100644 (file)
@@ -16,9 +16,7 @@
 #include "../playerdemo.qh"
 #include "../teamplay.qh"
 
-#include "../bot/bot.qh"
-#include "../bot/navigation.qh"
-#include "../bot/scripting.qh"
+#include "../bot/api.qh"
 
 #include "../mutators/all.qh"
 
@@ -41,11 +39,11 @@ void PutObserverInServer(entity this);
 //  used by GameCommand_make_mapinfo()
 void make_mapinfo_Think(entity this)
 {
-       if (MapInfo_FilterGametype(MAPINFO_TYPE_ALL, 0, 0, 0, 1))
+       if (_MapInfo_FilterGametype(MAPINFO_TYPE_ALL, 0, 0, 0, 1))
        {
                LOG_INFO("Done rebuiling mapinfos.\n");
                MapInfo_FilterGametype(MapInfo_CurrentGametype(), MapInfo_CurrentFeatures(), MapInfo_RequiredFlags(), MapInfo_ForbiddenFlags(), 0);
-               remove(this);
+               delete(this);
        }
        else
        {
@@ -141,7 +139,7 @@ void GameCommand_adminmsg(float request, float argc)
                                        }
 
                                        successful = strcat(successful, (successful ? ", " : ""), client.netname);
-                                       LOG_TRACE("Message sent to ", client.netname, "\n");
+                                       LOG_TRACE("Message sent to ", client.netname);
                                        continue;
                                }
 
@@ -742,7 +740,7 @@ void GameCommand_gametype(float request, float argc)
                        if (argv(1) != "")
                        {
                                string s = argv(1);
-                               float t = MapInfo_Type_FromString(s), tsave = MapInfo_CurrentGametype();
+                               Gametype t = MapInfo_Type_FromString(s), tsave = MapInfo_CurrentGametype();
 
                                if (t)
                                {
@@ -830,7 +828,7 @@ void GameCommand_gettaginfo(float request, float argc)
                                        LOG_INFO("bone not found\n");
                                }
 
-                               remove(tmp_entity);
+                               delete(tmp_entity);
                                return;
                        }
                }
@@ -889,7 +887,7 @@ void GameCommand_animbench(float request, float argc)
                                LOG_INFO("model ", tmp_entity.model, " frame ", ftos(f1), " animtime ", ftos(n / t1), "/s\n");
                                LOG_INFO("model ", tmp_entity.model, " frame ", ftos(f2), " animtime ", ftos(n / t2), "/s\n");
 
-                               remove(tmp_entity);
+                               delete(tmp_entity);
                                return;
                        }
                }
index 0aa48c2fe705884650d4c3a258c4dbe20cbc677b..72bedd982ca79797397b9d811b8362752a9b2b95 100644 (file)
@@ -344,7 +344,7 @@ void reset_map(bool dorespawn)
                        continue;
                }
                if (it.team_saved) it.team = it.team_saved;
-               if (it.flags & FL_PROJECTILE) remove(it);  // remove any projectiles left
+               if (it.flags & FL_PROJECTILE) delete(it);  // remove any projectiles left
        });
 
        // Waypoints and assault start come LAST
@@ -392,7 +392,7 @@ void ReadyRestart_think(entity this)
        restart_mapalreadyrestarted = true;
        reset_map(true);
        Score_ClearAll();
-       remove(this);
+       delete(this);
 }
 
 // Forces a restart of the game without actually reloading the map // this is a mess...
index a1c180cef831779830352ecfe6c0ad67c43409a7..53aa317e6874c97cba35cde6a7f3276284a9de3b 100644 (file)
@@ -35,7 +35,7 @@ float player_count;
 float currentbots;
 float bots_would_leave;
 
-void UpdateFrags(entity player, float f);
+void UpdateFrags(entity player, int f);
 .float totalfrags;
 
 float team1_score, team2_score, team3_score, team4_score;
@@ -449,3 +449,15 @@ STATIC_INIT(g_monsters) { g_monsters = IL_NEW(); }
 
 IntrusiveList g_waypoints;
 STATIC_INIT(g_waypoints) { g_waypoints = IL_NEW(); }
+
+IntrusiveList g_vehicles;
+STATIC_INIT(g_vehicles) { g_vehicles = IL_NEW(); }
+
+IntrusiveList g_turrets;
+STATIC_INIT(g_turrets) { g_turrets = IL_NEW(); }
+
+IntrusiveList g_mines;
+STATIC_INIT(g_mines) { g_mines = IL_NEW(); }
+
+IntrusiveList g_projectiles;
+STATIC_INIT(g_projectiles) { g_projectiles = IL_NEW(); }
index 5fbe6423098baefaee5d25f93651c7d2c32e1971..d7e9b07c05279a5c26a7f67655d9039ca4339c1a 100644 (file)
@@ -1,6 +1,6 @@
 #include "g_damage.qh"
 
-#include "bot/bot.qh"
+#include "bot/api.qh"
 #include "g_hook.qh"
 #include "mutators/all.qh"
 #include "scores.qh"
@@ -25,7 +25,7 @@
 #include "../lib/csqcmodel/sv_model.qh"
 #include "../lib/warpzone/common.qh"
 
-void UpdateFrags(entity player, float f)
+void UpdateFrags(entity player, int f)
 {
        PlayerTeamScore_AddScore(player, f);
 }
@@ -503,7 +503,7 @@ void Ice_Think(entity this)
 {
        if(!STAT(FROZEN, this.owner) || this.owner.iceblock != this)
        {
-               remove(this);
+               delete(this);
                return;
        }
        setorigin(this, this.owner.origin - '0 0 16');
@@ -569,7 +569,7 @@ void Unfreeze (entity targ)
 
        // remove the ice block
        if(targ.iceblock)
-               remove(targ.iceblock);
+               delete(targ.iceblock);
        targ.iceblock = NULL;
 }
 
@@ -1251,14 +1251,14 @@ void fireburner_think(entity this)
        // for players, this is done in the regular loop
        if(wasfreed(this.owner))
        {
-               remove(this);
+               delete(this);
                return;
        }
        Fire_ApplyEffect(this.owner);
        if(!Fire_IsBurning(this.owner))
        {
                this.owner.fire_burner = NULL;
-               remove(this);
+               delete(this);
                return;
        }
        Fire_ApplyDamage(this.owner);
index e2c5ea2b35d7a3f665df6a222cb9535e599c1c98..f11c82c84d2bd1c0019fa350322687ba60997eb4 100644 (file)
@@ -52,7 +52,7 @@ float damage_gooddamage;
 
 float IsFlying(entity a);
 
-void UpdateFrags(entity player, float f);
+void UpdateFrags(entity player, int f);
 
 // NOTE: f=0 means still count as a (positive) kill, but count no frags for it
 void W_SwitchWeapon_Force(Player this, Weapon w);
index 88d63e384c11261fc3cb70499cda902c512822cc..1b2662d6e4ede1927712d46266b2afc2f9533771 100644 (file)
@@ -74,7 +74,7 @@ void RemoveGrapplingHook(entity pl)
 {
        if(pl.hook == NULL)
                return;
-       remove(pl.hook);
+       delete(pl.hook);
        pl.hook = NULL;
        if(pl.move_movetype == MOVETYPE_FLY)
                set_movetype(pl, MOVETYPE_WALK);
@@ -87,7 +87,7 @@ void GrapplingHookReset(entity this)
        if(this.realowner.hook == this)
                RemoveGrapplingHook(this.owner);
        else // in any case:
-               remove(this);
+               delete(this);
 }
 
 void GrapplingHookThink(entity this);
@@ -370,6 +370,7 @@ void FireGrapplingHook(entity actor)
        missile.reset = GrapplingHookReset;
        missile.classname = "grapplinghook";
        missile.flags = FL_PROJECTILE;
+       IL_PUSH(g_projectiles, missile);
 
        set_movetype(missile, ((autocvar_g_balance_grapplehook_gravity) ? MOVETYPE_TOSS : MOVETYPE_FLY));
        PROJECTILE_MAKETRIGGER(missile);
index e79bbcaf76a5dd707acc48b764db9109d0bf13e5..425716d2da7cb92dc3001d2383947b7a4eab86dd 100644 (file)
@@ -37,7 +37,7 @@ flags:
 void dynlight_think(entity this)
 {
        if(!this.owner)
-               remove(this);
+               delete(this);
 
        this.nextthink = time + 0.1;
 }
index e4affe265f8b7dd768089358b36198fa027c1ce1..e8e50c7184134148406c439b092c96e2b5161137 100644 (file)
@@ -8,7 +8,7 @@
 
 spawnfunc(info_null)
 {
-       remove(this);
+       delete(this);
        // if anything breaks, tell the mapper to fix his map! info_null is meant to remove itself immediately.
 }
 
@@ -141,10 +141,10 @@ float tracebox_inverted (vector v1, vector mi, vector ma, vector v2, float nomon
 
                if(c == 50)
                {
-                       LOG_TRACE("HOLY SHIT! When tracing from ", vtos(v1), " to ", vtos(v2), "\n");
-                       LOG_TRACE("  Nudging gets us nowhere at ", vtos(pos), "\n");
-                       LOG_TRACE("  trace_endpos is ", vtos(trace_endpos), "\n");
-                       LOG_TRACE("  trace distance is ", ftos(vlen(pos - trace_endpos)), "\n");
+                       LOG_TRACE("HOLY SHIT! When tracing from ", vtos(v1), " to ", vtos(v2));
+                       LOG_TRACE("  Nudging gets us nowhere at ", vtos(pos));
+                       LOG_TRACE("  trace_endpos is ", vtos(trace_endpos));
+                       LOG_TRACE("  trace distance is ", ftos(vlen(pos - trace_endpos)));
                }
 
                stopentity = trace_ent;
@@ -281,7 +281,7 @@ void LODmodel_attach(entity this)
                if(e)
                {
                        this.lodmodel1 = e.model;
-                       remove(e);
+                       delete(e);
                }
        }
        if(this.lodtarget2 != "")
@@ -290,7 +290,7 @@ void LODmodel_attach(entity this)
                if(e)
                {
                        this.lodmodel2 = e.model;
-                       remove(e);
+                       delete(e);
                }
        }
 
index 1dc8bbcacda23acafc00df4b96cf15d4d5cdb07e..30cf5517f7ca5f2c3dc095695ace5d4cce3e632f 100644 (file)
@@ -2,7 +2,7 @@
 
 #include "anticheat.qh"
 #include "antilag.qh"
-#include "bot/bot.qh"
+#include "bot/api.qh"
 #include "campaign.qh"
 #include "cheats.qh"
 #include "cl_client.qh"
@@ -646,9 +646,6 @@ spawnfunc(worldspawn)
                }
        }
 
-       float fd, l;
-       string s;
-
        cvar = cvar_normal;
        cvar_string = cvar_string_normal;
        cvar_set = cvar_set_normal;
@@ -661,8 +658,6 @@ spawnfunc(worldspawn)
 
        cvar_changes_init(); // do this very early now so it REALLY matches the server config
 
-       compressShortVector_init();
-
        maxclients = 0;
        for (entity head = nextent(NULL); head; head = nextent(head))
        {
@@ -753,7 +748,7 @@ spawnfunc(worldspawn)
        // character set: ASCII 33-126 without the following characters: : ; ' " \ $
        if(autocvar_sv_eventlog)
        {
-               s = sprintf("%d.%s.%06d", itos(autocvar_sv_eventlog_files_counter), strftime(false, "%s"), floor(random() * 1000000));
+               string 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));
@@ -806,12 +801,13 @@ spawnfunc(worldspawn)
 
        if(whichpack(strcat("maps/", mapname, ".cfg")) != "")
        {
-               fd = fopen(strcat("maps/", mapname, ".cfg"), FILE_READ);
+               int fd = fopen(strcat("maps/", mapname, ".cfg"), FILE_READ);
                if(fd != -1)
                {
+                       string s;
                        while((s = fgets(fd)))
                        {
-                               l = tokenize_console(s);
+                               int l = tokenize_console(s);
                                if(l < 2)
                                        continue;
                                if(argv(0) == "cd")
@@ -853,7 +849,7 @@ spawnfunc(worldspawn)
        monsterlist_reply = strzone(getmonsterlist());
        for(int i = 0; i < 10; ++i)
        {
-               s = getrecords(i);
+               string s = getrecords(i);
                if (s)
                        records_reply[i] = strzone(s);
        }
@@ -872,7 +868,7 @@ spawnfunc(worldspawn)
        // fill sv_curl_serverpackages from .serverpackage files
        if (autocvar_sv_curl_serverpackages_auto)
        {
-               s = "csprogs-" WATERMARK ".txt";
+               string s = "csprogs-" WATERMARK ".txt";
                // remove automatically managed files from the list to prevent duplicates
                for (int i = 0, n = tokenize_console(cvar_string("sv_curl_serverpackages")); i < n; ++i)
                {
@@ -884,7 +880,7 @@ spawnfunc(worldspawn)
                }
                // add automatically managed files to the list
                #define X(match) MACRO_BEGIN { \
-                       fd = search_begin(match, true, false); \
+                       int fd = search_begin(match, true, false); \
                        if (fd >= 0) \
                        { \
                                for (int i = 0, j = search_getsize(fd); i < j; ++i) \
@@ -923,7 +919,7 @@ spawnfunc(worldspawn)
 spawnfunc(light)
 {
        //makestatic (this); // Who the f___ did that?
-       remove(this);
+       delete(this);
 }
 
 string GetGametype()
@@ -970,10 +966,10 @@ float MapHasRightSize(string map)
                LOG_TRACE("checkwp "); LOG_TRACE(map);
                if(!fexists(strcat("maps/", map, ".waypoints")))
                {
-                       LOG_TRACE(": no waypoints\n");
+                       LOG_TRACE(": no waypoints");
                        return false;
                }
-               LOG_TRACE(": has waypoints\n");
+               LOG_TRACE(": has waypoints");
        }
 
        // open map size restriction file
@@ -988,18 +984,18 @@ float MapHasRightSize(string map)
                fclose(fh);
                if(player_count < mapmin)
                {
-                       LOG_TRACE("not enough\n");
+                       LOG_TRACE("not enough");
                        return false;
                }
                if(player_count > mapmax)
                {
-                       LOG_TRACE("too many\n");
+                       LOG_TRACE("too many");
                        return false;
                }
-               LOG_TRACE("right size\n");
+               LOG_TRACE("right size");
                return true;
        }
-       LOG_TRACE(": not found\n");
+       LOG_TRACE(": not found");
        return true;
 }
 
@@ -1038,7 +1034,7 @@ float Map_Check(float position, float pass)
                return 0;
        }
        else
-               LOG_DEBUG( "Couldn't select '", filename, "'...\n" );
+               LOG_DEBUG( "Couldn't select '", filename, "'..." );
 
        return 0;
 }
@@ -1071,7 +1067,7 @@ float() MaplistMethod_Iterate = // usual method
 {
        float pass, i;
 
-       LOG_TRACE("Trying MaplistMethod_Iterate\n");
+       LOG_TRACE("Trying MaplistMethod_Iterate");
 
        for(pass = 1; pass <= 2; ++pass)
        {
@@ -1088,7 +1084,7 @@ float() MaplistMethod_Iterate = // usual method
 
 float() MaplistMethod_Repeat = // fallback method
 {
-       LOG_TRACE("Trying MaplistMethod_Repeat\n");
+       LOG_TRACE("Trying MaplistMethod_Repeat");
 
        if(Map_Check(Map_Current, 2))
                return Map_Current;
@@ -1099,7 +1095,7 @@ float() MaplistMethod_Random = // random map selection
 {
        float i, imax;
 
-       LOG_TRACE("Trying MaplistMethod_Random\n");
+       LOG_TRACE("Trying MaplistMethod_Random");
 
        imax = 42;
 
@@ -1119,7 +1115,7 @@ float(float exponent) MaplistMethod_Shuffle = // more clever shuffling
 {
        float i, j, imax, insertpos;
 
-       LOG_TRACE("Trying MaplistMethod_Shuffle\n");
+       LOG_TRACE("Trying MaplistMethod_Shuffle");
 
        imax = 42;
 
@@ -1131,7 +1127,7 @@ float(float exponent) MaplistMethod_Shuffle = // more clever shuffling
                insertpos = pow(random(), 1 / exponent);       // ]0, 1]
                insertpos = insertpos * (Map_Count - 1);       // ]0, Map_Count - 1]
                insertpos = ceil(insertpos) + 1;               // {2, 3, 4, ..., Map_Count}
-               LOG_TRACE("SHUFFLE: insert pos = ", ftos(insertpos), "\n");
+               LOG_TRACE("SHUFFLE: insert pos = ", ftos(insertpos));
 
                // insert the current map there
                newlist = "";
@@ -2021,7 +2017,7 @@ void Physics_Frame()
 
        FOREACH_ENTITY_FLOAT(pure_data, false,
        {
-               if(IS_CLIENT(it) || it.classname == "" || it.movetype == MOVETYPE_PUSH || it.movetype == MOVETYPE_FAKEPUSH || it.movetype == MOVETYPE_PHYSICS)
+               if(IS_CLIENT(it) || it.classname == "" || it.move_movetype == MOVETYPE_PUSH || it.move_movetype == MOVETYPE_FAKEPUSH || it.move_movetype == MOVETYPE_PHYSICS)
                        continue;
 
                int mt = it.move_movetype;
@@ -2029,11 +2025,11 @@ void Physics_Frame()
                if(mt == MOVETYPE_PUSH || mt == MOVETYPE_FAKEPUSH || mt == MOVETYPE_PHYSICS)
                {
                        it.move_qcphysics = false;
-                       it.movetype = mt;
+                       set_movetype(it, mt);
                        continue;
                }
-               
-               it.movetype = ((it.move_qcphysics) ? MOVETYPE_NONE : it.move_movetype);
+
+               set_movetype(it, ((it.move_qcphysics) ? MOVETYPE_NONE : it.move_movetype));
 
                if(it.move_movetype == MOVETYPE_NONE)
                        continue;
@@ -2060,6 +2056,7 @@ void Physics_Frame()
        });
 }
 
+void systems_update();
 void EndFrame()
 {
        anticheat_endframe();
@@ -2094,6 +2091,7 @@ void EndFrame()
                PlayerState s = PS(it);
                s.ps_push(s, it);
        });
+       systems_update();
        IL_ENDFRAME();
 }
 
@@ -2170,7 +2168,7 @@ void Shutdown()
        if(world_initialized > 0)
        {
                world_initialized = 0;
-               LOG_TRACE("Saving persistent data...\n");
+               LOG_TRACE("Saving persistent data...");
                Ban_SaveBans();
 
                // playerstats with unfinished match
@@ -2193,7 +2191,7 @@ void Shutdown()
                CheatShutdown(); // must be after cheatcount check
                db_close(ServerProgsDB);
                db_close(TemporaryDB);
-               LOG_TRACE("Saving persistent data... done!\n");
+               LOG_TRACE("Saving persistent data... done!");
                // tell the bot system the game is ending now
                bot_endgame();
 
index 8cc37597938b17bbba95d75f972935366c2ed9d0..50c258f927a8295766d6317d92b6dc138ef2d35d 100644 (file)
@@ -163,7 +163,7 @@ void OnlineBanList_URI_Get_Callback(float id, float status, string data)
 
                LOG_TRACE("received ban list item ", ftos(i / 4), ": ip=", ip);
                LOG_TRACE(" timeleft=", ftos(timeleft), " reason=", reason);
-               LOG_TRACE(" serverip=", serverip, "\n");
+               LOG_TRACE(" serverip=", serverip);
 
                timeleft -= 1.5 * autocvar_g_ban_sync_timeout;
                if(timeleft < 0)
@@ -243,7 +243,7 @@ void OnlineBanList_Think(entity this)
        return;
 
 LABEL(killme)
-       remove(this);
+       delete(this);
 }
 
 const float BAN_MAX = 256;
@@ -507,10 +507,10 @@ float Ban_Insert(string ip, float bantime, string reason, float dosync)
                        if(time + bantime > ban_expire[i])
                        {
                                ban_expire[i] = time + bantime;
-                               LOG_TRACE(ip, "'s ban has been prolonged to ", ftos(bantime), " seconds from now\n");
+                               LOG_TRACE(ip, "'s ban has been prolonged to ", ftos(bantime), " seconds from now");
                        }
                        else
-                               LOG_TRACE(ip, "'s ban is still active until ", ftos(ban_expire[i] - time), " seconds from now\n");
+                               LOG_TRACE(ip, "'s ban is still active until ", ftos(ban_expire[i] - time), " seconds from now");
 
                        // and enforce
                        reason = Ban_Enforce(i, reason);
@@ -552,7 +552,7 @@ float Ban_Insert(string ip, float bantime, string reason, float dosync)
        }
        // okay, insert our new victim as i
        Ban_Delete(i);
-       LOG_TRACE(ip, " has been banned for ", ftos(bantime), " seconds\n");
+       LOG_TRACE(ip, " has been banned for ", ftos(bantime), " seconds");
        ban_expire[i] = time + bantime;
        ban_ip[i] = strzone(ip);
        ban_count = max(ban_count, i + 1);
index 64e10a2f2e0fdb01b40afb4ccfc06c137ddf4acc..05172241c3e320630e3e4fc02321de3ab370c86f 100644 (file)
@@ -160,7 +160,7 @@ spawnfunc(item_key)
        // reject this entity if more than one key was set!
        if (this.itemkeys>0 && (this.itemkeys & (this.itemkeys-1)) != 0) {
                objerror(this, "item_key.itemkeys must contain only 1 bit set specifying the key it represents!");
-               remove(this);
+               delete(this);
                return;
        }
 
@@ -202,7 +202,7 @@ spawnfunc(item_key)
 
                if (this.netname == "") {
                        objerror(this, "item_key doesn't have a default name for this key and a custom one was not specified!");
-                       remove(this);
+                       delete(this);
                        return;
                }
                break;
@@ -217,7 +217,7 @@ spawnfunc(item_key)
                _model = "models/keys/key.md3"; // FIXME: replace it by a keycard model!
        } else if (this.model == "") {
                objerror(this, "item_key doesn't have a default model for this key and a custom one was not specified!");
-               remove(this);
+               delete(this);
                return;
        }
 
index b3a496f41e988c1ef19dce7d448e12772daecd0c..7ffe4b934fbfa389bcac17b021855f97411d772c 100644 (file)
@@ -41,10 +41,10 @@ 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)
+Gametype GameTypeVote_Type_FromString(string type_name)
 {
-       float type = MapInfo_Type_FromString(type_name);
-       if ( type == 0 )
+       Gametype type = MapInfo_Type_FromString(type_name);
+       if (type == NULL)
                type = MapInfo_Type_FromString(cvar_string(
                        strcat("sv_vote_gametype_",type_name,"_type")));
        return type;
@@ -54,22 +54,22 @@ int GameTypeVote_AvailabilityStatus(string type_name)
 {
        int flag = GTV_FORBIDDEN;
 
-       float type = MapInfo_Type_FromString(type_name);
-       if ( type == 0 )
+       Gametype type = MapInfo_Type_FromString(type_name);
+       if ( type == NULL )
        {
                type = MapInfo_Type_FromString(cvar_string(
                        strcat("sv_vote_gametype_",type_name,"_type")));
                flag |= GTV_CUSTOM;
        }
 
-       if( type == 0 )
+       if( type == NULL )
                return flag;
 
        if ( autocvar_nextmap != "" )
        {
-               if ( !MapInfo_Get_ByName(autocvar_nextmap, false, 0) )
+               if ( !MapInfo_Get_ByName(autocvar_nextmap, false, NULL) )
                        return flag;
-               if (!(MapInfo_Map_supportedGametypes & type))
+               if (!(MapInfo_Map_supportedGametypes & type.m_flags))
                        return flag;
        }
 
@@ -83,7 +83,7 @@ float GameTypeVote_GetMask()
        n = min(MAPVOTE_COUNT, n);
        gametype_mask = 0;
        for(j = 0; j < n; ++j)
-               gametype_mask |= GameTypeVote_Type_FromString(argv(j));
+               gametype_mask |= GameTypeVote_Type_FromString(argv(j)).m_flags;
        return gametype_mask;
 }
 
@@ -92,7 +92,7 @@ string GameTypeVote_MapInfo_FixName(string m)
        if ( autocvar_sv_vote_gametype )
        {
                MapInfo_Enumerate();
-               MapInfo_FilterGametype(GameTypeVote_GetMask(), 0, MapInfo_RequiredFlags(), MapInfo_ForbiddenFlags(), 0);
+               _MapInfo_FilterGametype(GameTypeVote_GetMask(), 0, MapInfo_RequiredFlags(), MapInfo_ForbiddenFlags(), 0);
        }
        return MapInfo_FixName(m);
 }
@@ -695,12 +695,12 @@ void MapVote_Think()
        MapVote_Tick();
 }
 
-float GameTypeVote_SetGametype(float type)
+float GameTypeVote_SetGametype(Gametype type)
 {
        if (MapInfo_CurrentGametype() == type)
                return true;
 
-       float tsave = MapInfo_CurrentGametype();
+       Gametype tsave = MapInfo_CurrentGametype();
 
        MapInfo_SwitchGameType(type);
 
@@ -752,7 +752,7 @@ float GameTypeVote_Finished(float pos)
 float GameTypeVote_AddVotable(string nextMode)
 {
        float j;
-       if ( nextMode == "" || GameTypeVote_Type_FromString(nextMode) == 0 )
+       if ( nextMode == "" || GameTypeVote_Type_FromString(nextMode) == NULL )
                return false;
        for(j = 0; j < mapvote_count; ++j)
                if(mapvote_maps[j] == nextMode)
index 72d3250daeecb6ae71febeb1f4308d13faaebe4f..fb782ed5c6a242efbba13f0bc72dcb7f9676d9ea 100644 (file)
@@ -172,7 +172,7 @@ entity findnearest(vector point, .string field, string value, vector axismod)
             {
                 LOG_TRACE("Nearest point (");
                 LOG_TRACE(nearest_entity[0].netname);
-                LOG_TRACE(") is not visible, using a visible one.\n");
+                LOG_TRACE(") is not visible, using a visible one.");
             }
             return nearest_entity[i];
         }
@@ -181,7 +181,7 @@ entity findnearest(vector point, .string field, string value, vector axismod)
     if (num_nearest == 0)
         return NULL;
 
-    LOG_TRACE("Not seeing any location point, using nearest as fallback.\n");
+    LOG_TRACE("Not seeing any location point, using nearest as fallback.");
     /* DEBUGGING CODE:
     dprint("Candidates were: ");
     for(j = 0; j < num_nearest; ++j)
@@ -1036,8 +1036,7 @@ bool SUB_NoImpactCheck(entity this, entity toucher)
        // these stop the projectile from moving, so...
        if(trace_dphitcontents == 0)
        {
-               //dprint("A hit happened with zero hit contents... DEBUG THIS, this should never happen for projectiles! Projectile will self-destruct.\n");
-               LOG_TRACEF("A hit from a projectile happened with no hit contents! DEBUG THIS, this should never happen for projectiles! Projectile will self-destruct. (edict: %d, classname: %s, origin: %s)\n", etof(this), this.classname, vtos(this.origin));
+               LOG_TRACEF("A hit from a projectile happened with no hit contents! DEBUG THIS, this should never happen for projectiles! Projectile will self-destruct. (edict: %i, classname: %s, origin: %v)", this, this.classname, this.origin);
                checkclient(this);
        }
     if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
@@ -1050,11 +1049,11 @@ bool SUB_NoImpactCheck(entity this, entity toucher)
         traceline(this.origin - tic, this.origin + tic, MOVE_NORMAL, this);
         if (trace_fraction >= 1)
         {
-            LOG_TRACE("Odd... did not hit...?\n");
+            LOG_TRACE("Odd... did not hit...?");
         }
         else if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
         {
-            LOG_TRACE("Detected and prevented the sky-grapple bug.\n");
+            LOG_TRACE("Detected and prevented the sky-grapple bug.");
             return true;
         }
     }
@@ -1078,10 +1077,10 @@ bool WarpZone_Projectile_Touch_ImpactFilter_Callback(entity this, entity toucher
                else if(this.classname == "spike")
                {
                        W_Crylink_Dequeue(this);
-                       remove(this);
+                       delete(this);
                }
                else
-                       remove(this);
+                       delete(this);
                return true;
        }
        if(trace_ent && trace_ent.solid > SOLID_TRIGGER)
@@ -1245,7 +1244,7 @@ float MoveToRandomLocationWithinBounds(entity e, vector boundmin, vector boundma
     {
         setorigin(e, start);
         e.angles = vectoangles(end - start);
-        LOG_TRACE("Needed ", ftos(i + 1), " attempts\n");
+        LOG_TRACE("Needed ", ftos(i + 1), " attempts");
         return true;
     }
     else
index d742c77af105f6d33e916fcd1704acc23f3010ce..78ba560265e0b17ec95b2d36d578cef9ab6e43fe 100644 (file)
@@ -74,7 +74,7 @@
 #include "all.qh"
 
 STATIC_INIT_LATE(Gametype) {
-    Gametype g = MapInfo_Type(MapInfo_CurrentGametype());
+    Gametype g = MapInfo_CurrentGametype();
     if (g) {
         for (string _s = g.m_mutators; _s != ""; _s = cdr(_s)) {
             string s = car(_s);
index 257416538f52a5b1c3a9b5c0e09edf81c1dea250..0d53e054f48513fbdd716e289f5ad402f3c679be 100644 (file)
@@ -748,7 +748,7 @@ MUTATOR_HOOKABLE(CheckRules_World, EV_CheckRules_World);
 MUTATOR_HOOKABLE(WantWeapon, EV_WantWeapon);
 
 #define EV_AddPlayerScore(i, o) \
-    /** score field */  i(int, MUTATOR_ARGV_0_int) \
+    /** score field */  i(PlayerScoreField, MUTATOR_ARGV_0_entity) \
     /** score */        i(float, MUTATOR_ARGV_1_float) \
     /**/                o(float, MUTATOR_ARGV_1_float) \
     /** player */       i(entity, MUTATOR_ARGV_2_entity) \
index ee80b44b06df6213c745d39e0c2b3dc70bb9c116..1e60b203e3caa7226883860198bc9f9e130977df 100644 (file)
 #include <server/scores_rules.qh>
 #include <server/teamplay.qh>
 
-#include <server/bot/bot.qh>
-#include <server/bot/navigation.qh>
-#include <server/bot/waypoints.qh>
-#include <server/bot/havocbot/roles.qh>
-
-#include <server/bot/havocbot/havocbot.qh>
+#include <server/bot/api.qh>
 
 #include <server/command/vote.qh>
 
index 40fad29b34426e03fae679d508eab6968ca327ba..a63321a36a4731d9253021233886c1e4d9c02e84 100644 (file)
 #include <server/scores.qh>
 #include <server/scores_rules.qh>
 
-#include <server/bot/bot.qh>
-#include <server/bot/navigation.qh>
-#include <server/bot/waypoints.qh>
-
-#include <server/bot/havocbot/havocbot.qh>
-#include <server/bot/havocbot/roles.qh>
+#include <server/bot/api.qh>
 
 #include <server/command/vote.qh>
 #include <server/command/common.qh>
index 7285d7db36607738a58aa7c898a11a6c2cd5af55..092e07b798be7518b135277dcc4c885bc5093224 100644 (file)
@@ -59,7 +59,6 @@ void(entity this, float ratingscale, vector org, float sradius) havocbot_goalrat
 
 // scoreboard stuff
 const float ST_ASSAULT_OBJECTIVES = 1;
-const float SP_ASSAULT_OBJECTIVES = 4;
 
 // predefined spawnfuncs
 void target_objective_decrease_activate(entity this);
@@ -259,10 +258,11 @@ void assault_new_round(entity this)
        // Eject players from vehicles
     FOREACH_CLIENT(IS_PLAYER(it) && it.vehicle, vehicles_exit(it.vehicle, VHEF_RELEASE));
 
-    FOREACH_ENTITY_FLAGS(vehicle_flags, VHF_ISVEHICLE, LAMBDA(
+    IL_EACH(g_vehicles, true,
+    {
         vehicles_clearreturn(it);
         vehicles_spawn(it);
-    ));
+    });
 
        // up round counter
        this.winning = this.winning + 1;
@@ -332,7 +332,7 @@ int WinningCondition_Assault()
 // spawnfuncs
 spawnfunc(info_player_attacker)
 {
-       if (!g_assault) { remove(this); return; }
+       if (!g_assault) { delete(this); return; }
 
        this.team = NUM_TEAM_1; // red, gets swapped every round
        spawnfunc_info_player_deathmatch(this);
@@ -340,7 +340,7 @@ spawnfunc(info_player_attacker)
 
 spawnfunc(info_player_defender)
 {
-       if (!g_assault) { remove(this); return; }
+       if (!g_assault) { delete(this); return; }
 
        this.team = NUM_TEAM_2; // blue, gets swapped every round
        spawnfunc_info_player_deathmatch(this);
@@ -348,7 +348,7 @@ spawnfunc(info_player_defender)
 
 spawnfunc(target_objective)
 {
-       if (!g_assault) { remove(this); return; }
+       if (!g_assault) { delete(this); return; }
 
        this.classname = "target_objective";
        this.use = assault_objective_use;
@@ -359,7 +359,7 @@ spawnfunc(target_objective)
 
 spawnfunc(target_objective_decrease)
 {
-       if (!g_assault) { remove(this); return; }
+       if (!g_assault) { delete(this); return; }
 
        this.classname = "target_objective_decrease";
 
@@ -378,7 +378,7 @@ spawnfunc(target_objective_decrease)
 spawnfunc(func_breakable);
 spawnfunc(func_assault_destructible)
 {
-       if (!g_assault) { remove(this); return; }
+       if (!g_assault) { delete(this); return; }
 
        this.spawnflags = 3;
        this.classname = "func_assault_destructible";
@@ -393,7 +393,7 @@ spawnfunc(func_assault_destructible)
 
 spawnfunc(func_assault_wall)
 {
-       if (!g_assault) { remove(this); return; }
+       if (!g_assault) { delete(this); return; }
 
        this.classname = "func_assault_wall";
        this.mdl = this.model;
@@ -406,7 +406,7 @@ spawnfunc(func_assault_wall)
 
 spawnfunc(target_assault_roundend)
 {
-       if (!g_assault) { remove(this); return; }
+       if (!g_assault) { delete(this); return; }
 
        this.winning = 0; // round not yet won by attackers
        this.classname = "target_assault_roundend";
@@ -417,7 +417,7 @@ spawnfunc(target_assault_roundend)
 
 spawnfunc(target_assault_roundstart)
 {
-       if (!g_assault) { remove(this); return; }
+       if (!g_assault) { delete(this); return; }
 
        assault_attacker_team = NUM_TEAM_1;
        this.classname = "target_assault_roundstart";
index 55ec4a462ed991dbc89c7bc787bbc3bc719f60b5..9b16e4e96d56ada2e030b4def1ca4b834c09232e 100644 (file)
@@ -260,7 +260,7 @@ bool ctf_CaptureShield_CheckStatus(entity p)
        if(ctf_captureshield_max_ratio <= 0)
                return false;
 
-       s = PlayerScore_Add(p, SP_CTF_CAPS, 0);
+       s  = PlayerScore_Add(p, SP_CTF_CAPS,    0);
        s2 = PlayerScore_Add(p, SP_CTF_PICKUPS, 0);
        s3 = PlayerScore_Add(p, SP_CTF_RETURNS, 0);
        s4 = PlayerScore_Add(p, SP_CTF_FCKILLS, 0);
@@ -274,7 +274,7 @@ bool ctf_CaptureShield_CheckStatus(entity p)
        FOREACH_CLIENT(IS_PLAYER(it), LAMBDA(
                if(DIFF_TEAM(it, p))
                        continue;
-               se = PlayerScore_Add(it, SP_CTF_CAPS, 0);
+               se  = PlayerScore_Add(it, SP_CTF_CAPS,    0);
                se2 = PlayerScore_Add(it, SP_CTF_PICKUPS, 0);
                se3 = PlayerScore_Add(it, SP_CTF_RETURNS, 0);
                se4 = PlayerScore_Add(it, SP_CTF_FCKILLS, 0);
@@ -720,7 +720,7 @@ void ctf_Handle_Pickup(entity flag, entity player, int pickuptype)
                {
                        pickup_dropped_score = (autocvar_g_ctf_flag_return_time ? bound(0, ((flag.ctf_droptime + autocvar_g_ctf_flag_return_time) - time) / autocvar_g_ctf_flag_return_time, 1) : 1);
                        pickup_dropped_score = floor((autocvar_g_ctf_score_pickup_dropped_late * (1 - pickup_dropped_score) + autocvar_g_ctf_score_pickup_dropped_early * pickup_dropped_score) + 0.5);
-                       LOG_TRACE("pickup_dropped_score is ", ftos(pickup_dropped_score), "\n");
+                       LOG_TRACE("pickup_dropped_score is ", ftos(pickup_dropped_score));
                        PlayerTeamScore_AddScore(player, pickup_dropped_score);
                        ctf_EventLog("pickup", flag.team, player);
                        break;
@@ -893,7 +893,7 @@ void ctf_FlagThink(entity this)
 
        // sanity checks
        if(this.mins != CTF_FLAG.m_mins || this.maxs != CTF_FLAG.m_maxs) { // reset the flag boundaries in case it got squished
-               LOG_TRACE("wtf the flag got squashed?\n");
+               LOG_TRACE("wtf the flag got squashed?");
                tracebox(this.origin, CTF_FLAG.m_mins, CTF_FLAG.m_maxs, this.origin, MOVE_NOMONSTERS, this);
                if(!trace_startsolid || this.noalign) // can we resize it without getting stuck?
                        setsize(this, CTF_FLAG.m_mins, CTF_FLAG.m_maxs); }
@@ -1019,7 +1019,7 @@ void ctf_FlagThink(entity this)
 
                default: // this should never happen
                {
-                       LOG_TRACE("ctf_FlagThink(): Flag exists with no status?\n");
+                       LOG_TRACE("ctf_FlagThink(): Flag exists with no status?");
                        return;
                }
        }
@@ -1107,7 +1107,7 @@ METHOD(Flag, giveTo, bool(Flag this, entity flag, entity toucher))
 
                case FLAG_CARRY:
                {
-                       LOG_TRACE("Someone touched a flag even though it was being carried?\n");
+                       LOG_TRACE("Someone touched a flag even though it was being carried?");
                        break;
                }
 
@@ -1961,47 +1961,47 @@ void havocbot_role_ctf_defense(entity this)
 
 void havocbot_role_ctf_setrole(entity bot, int role)
 {
-       LOG_TRACE(strcat(bot.netname," switched to "));
+       string s = "(null)";
        switch(role)
        {
                case HAVOCBOT_CTF_ROLE_CARRIER:
-                       LOG_TRACE("carrier");
+                       s = "carrier";
                        bot.havocbot_role = havocbot_role_ctf_carrier;
                        bot.havocbot_role_timeout = 0;
                        bot.havocbot_cantfindflag = time + 10;
                        bot.bot_strategytime = 0;
                        break;
                case HAVOCBOT_CTF_ROLE_DEFENSE:
-                       LOG_TRACE("defense");
+                       s = "defense";
                        bot.havocbot_role = havocbot_role_ctf_defense;
                        bot.havocbot_role_timeout = 0;
                        break;
                case HAVOCBOT_CTF_ROLE_MIDDLE:
-                       LOG_TRACE("middle");
+                       s = "middle";
                        bot.havocbot_role = havocbot_role_ctf_middle;
                        bot.havocbot_role_timeout = 0;
                        break;
                case HAVOCBOT_CTF_ROLE_OFFENSE:
-                       LOG_TRACE("offense");
+                       s = "offense";
                        bot.havocbot_role = havocbot_role_ctf_offense;
                        bot.havocbot_role_timeout = 0;
                        break;
                case HAVOCBOT_CTF_ROLE_RETRIEVER:
-                       LOG_TRACE("retriever");
+                       s = "retriever";
                        bot.havocbot_previous_role = bot.havocbot_role;
                        bot.havocbot_role = havocbot_role_ctf_retriever;
                        bot.havocbot_role_timeout = time + 10;
                        bot.bot_strategytime = 0;
                        break;
                case HAVOCBOT_CTF_ROLE_ESCORT:
-                       LOG_TRACE("escort");
+                       s = "escort";
                        bot.havocbot_previous_role = bot.havocbot_role;
                        bot.havocbot_role = havocbot_role_ctf_escort;
                        bot.havocbot_role_timeout = time + 30;
                        bot.bot_strategytime = 0;
                        break;
        }
-       LOG_TRACE("\n");
+       LOG_TRACE(bot.netname, " switched to ", s);
 }
 
 
@@ -2444,7 +2444,7 @@ MUTATOR_HOOKFUNCTION(ctf, SV_ParseClientCommand)
 MUTATOR_HOOKFUNCTION(ctf, DropSpecialItems)
 {
        entity frag_target = M_ARGV(0, entity);
-       
+
        if(frag_target.flagcarried)
                ctf_Handle_Throw(frag_target, NULL, DROP_THROW);
 }
@@ -2467,7 +2467,7 @@ Keys:
 "noise5" sound played when flag touches the ground... */
 spawnfunc(item_flag_team1)
 {
-       if(!g_ctf) { remove(this); return; }
+       if(!g_ctf) { delete(this); return; }
 
        ctf_FlagSetup(NUM_TEAM_1, this);
 }
@@ -2485,7 +2485,7 @@ Keys:
 "noise5" sound played when flag touches the ground... */
 spawnfunc(item_flag_team2)
 {
-       if(!g_ctf) { remove(this); return; }
+       if(!g_ctf) { delete(this); return; }
 
        ctf_FlagSetup(NUM_TEAM_2, this);
 }
@@ -2503,7 +2503,7 @@ Keys:
 "noise5" sound played when flag touches the ground... */
 spawnfunc(item_flag_team3)
 {
-       if(!g_ctf) { remove(this); return; }
+       if(!g_ctf) { delete(this); return; }
 
        ctf_FlagSetup(NUM_TEAM_3, this);
 }
@@ -2521,7 +2521,7 @@ Keys:
 "noise5" sound played when flag touches the ground... */
 spawnfunc(item_flag_team4)
 {
-       if(!g_ctf) { remove(this); return; }
+       if(!g_ctf) { delete(this); return; }
 
        ctf_FlagSetup(NUM_TEAM_4, this);
 }
@@ -2539,8 +2539,8 @@ Keys:
 "noise5" sound played when flag touches the ground... */
 spawnfunc(item_flag_neutral)
 {
-       if(!g_ctf) { remove(this); return; }
-       if(!cvar("g_ctf_oneflag")) { remove(this); return; }
+       if(!g_ctf) { delete(this); return; }
+       if(!cvar("g_ctf_oneflag")) { delete(this); return; }
 
        ctf_FlagSetup(0, this);
 }
@@ -2553,7 +2553,7 @@ Keys:
 "cnt" Scoreboard color of the team (for example 4 is red and 13 is blue)... */
 spawnfunc(ctf_team)
 {
-       if(!g_ctf) { remove(this); return; }
+       if(!g_ctf) { delete(this); return; }
 
        this.classname = "ctf_team";
        this.team = this.cnt + 1;
@@ -2583,12 +2583,12 @@ void ctf_ScoreRules(int teams)
        CheckAllowedTeams(NULL);
        ScoreRules_basics(teams, SFL_SORT_PRIO_PRIMARY, 0, true);
        ScoreInfo_SetLabel_TeamScore  (ST_CTF_CAPS,     "caps",      SFL_SORT_PRIO_PRIMARY);
-       ScoreInfo_SetLabel_PlayerScore(SP_CTF_CAPS,     "caps",      SFL_SORT_PRIO_SECONDARY);
-       ScoreInfo_SetLabel_PlayerScore(SP_CTF_CAPTIME,  "captime",   SFL_LOWER_IS_BETTER | SFL_TIME);
-       ScoreInfo_SetLabel_PlayerScore(SP_CTF_PICKUPS,  "pickups",   0);
-       ScoreInfo_SetLabel_PlayerScore(SP_CTF_FCKILLS,  "fckills",   0);
-       ScoreInfo_SetLabel_PlayerScore(SP_CTF_RETURNS,  "returns",   0);
-       ScoreInfo_SetLabel_PlayerScore(SP_CTF_DROPS,    "drops",     SFL_LOWER_IS_BETTER);
+       ScoreInfo_SetLabel_PlayerScore(SP_CTF_CAPS,    "caps",      SFL_SORT_PRIO_SECONDARY);
+       ScoreInfo_SetLabel_PlayerScore(SP_CTF_CAPTIME, "captime",   SFL_LOWER_IS_BETTER | SFL_TIME);
+       ScoreInfo_SetLabel_PlayerScore(SP_CTF_PICKUPS, "pickups",   0);
+       ScoreInfo_SetLabel_PlayerScore(SP_CTF_FCKILLS, "fckills",   0);
+       ScoreInfo_SetLabel_PlayerScore(SP_CTF_RETURNS, "returns",   0);
+       ScoreInfo_SetLabel_PlayerScore(SP_CTF_DROPS,   "drops",     SFL_LOWER_IS_BETTER);
        ScoreRules_basics_end();
 }
 
@@ -2634,7 +2634,7 @@ void ctf_DelayedInit(entity this) // Do this check with a delay so we can wait f
        // if no teams are found, spawn defaults
        if(find(NULL, classname, "ctf_team") == NULL)
        {
-               LOG_TRACE("No \"ctf_team\" entities found on this map, creating them anyway.\n");
+               LOG_TRACE("No \"ctf_team\" entities found on this map, creating them anyway.");
                if(ctf_teams & BIT(0))
                        ctf_SpawnTeam("Red", NUM_TEAM_1);
                if(ctf_teams & BIT(1))
index b4d2459c3e26ed078e84ff89a11afa0b5725939c..65f2937fd978351104f35027d5d81cfd7eb38824 100644 (file)
@@ -8,16 +8,10 @@ void ctf_RespawnFlag(entity flag);
 
 // score rule declarations
 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;
 
 CLASS(Flag, Pickup)
-    ATTRIB(Flag, m_mins, vector, PL_MIN_CONST + '0 0 -13')
-    ATTRIB(Flag, m_maxs, vector, PL_MAX_CONST + '0 0 -13')
+    ATTRIB(Flag, m_mins, vector, PL_MIN_CONST + '0 0 -13');
+    ATTRIB(Flag, m_maxs, vector, PL_MAX_CONST + '0 0 -13');
 ENDCLASS(Flag)
 Flag CTF_FLAG; STATIC_INIT(Flag) { CTF_FLAG = NEW(Flag); }
 void ctf_FlagTouch(entity this, entity toucher) { ITEM_HANDLE(Pickup, CTF_FLAG, this, toucher); }
index 444fe5692e8bee057c004ac997e408b095ed934c..a712e033df7414ef7d7a929c3ef0c84bdaaf01ce 100644 (file)
@@ -38,9 +38,6 @@ REGISTER_MUTATOR(cts, false)
 
 // scores
 const float ST_CTS_LAPS = 1;
-const float SP_CTS_LAPS = 4;
-const float SP_CTS_TIME = 5;
-const float SP_CTS_FASTEST = 6;
 #endif
 
 #ifdef IMPLEMENTATION
@@ -111,8 +108,9 @@ void CTS_ClientKill(entity e) // silent version of ClientKill, used when player
 MUTATOR_HOOKFUNCTION(cts, PlayerPhysics)
 {
        entity player = M_ARGV(0, entity);
+       float dt = M_ARGV(1, float);
 
-       player.race_movetime_frac += PHYS_INPUT_TIMELENGTH;
+       player.race_movetime_frac += dt;
        float f = floor(player.race_movetime_frac);
        player.race_movetime_frac -= f;
        player.race_movetime_count += f;
@@ -285,7 +283,7 @@ MUTATOR_HOOKFUNCTION(cts, PutClientInServer)
 MUTATOR_HOOKFUNCTION(cts, PlayerDies)
 {
        entity frag_target = M_ARGV(2, entity);
-       
+
        frag_target.respawn_flags |= RESPAWN_FORCE;
        race_AbandonRaceCheck(frag_target);
 }
@@ -406,7 +404,7 @@ MUTATOR_HOOKFUNCTION(cts, ClientKill)
 
        if(player.killindicator && player.killindicator.health == 1) // player.killindicator.health == 1 means that the kill indicator was spawned by CTS_ClientKill
        {
-               remove(player.killindicator);
+               delete(player.killindicator);
                player.killindicator = NULL;
 
                ClientKill_Now(player); // allow instant kill in this case
index 3f75db9f387c320ab72a94840fa1badd366138a7..7c1e81184710c153ae2973b5dab788480320da42 100644 (file)
@@ -37,10 +37,7 @@ REGISTER_MUTATOR(dom, false)
 
 // score rule declarations
 const float ST_DOM_TICKS = 1;
-const float SP_DOM_TICKS = 4;
-const float SP_DOM_TAKES = 5;
 const float ST_DOM_CAPS = 1;
-const float SP_DOM_CAPS = 4;
 
 // pps: points per second
 .float dom_total_pps = _STAT(DOM_TOTAL_PPS);
@@ -535,7 +532,7 @@ spawnfunc(dom_controlpoint)
 {
        if(!g_domination)
        {
-               remove(this);
+               delete(this);
                return;
        }
        setthink(this, dom_controlpoint_setup);
@@ -580,7 +577,7 @@ spawnfunc(dom_team)
 {
        if(!g_domination || autocvar_g_domination_teams_override >= 2)
        {
-               remove(this);
+               delete(this);
                return;
        }
        precache_model(this.model);
@@ -678,7 +675,7 @@ void dom_DelayedInit(entity this) // Do this check with a delay so we can wait f
        // if no teams are found, spawn defaults
        if(find(NULL, classname, "dom_team") == NULL || autocvar_g_domination_teams_override >= 2)
        {
-               LOG_TRACE("No \"dom_team\" entities found on this map, creating them anyway.\n");
+               LOG_TRACE("No \"dom_team\" entities found on this map, creating them anyway.");
                domination_teams = bound(2, ((autocvar_g_domination_teams_override < 2) ? autocvar_g_domination_default_teams : autocvar_g_domination_teams_override), 4);
                dom_spawnteams(domination_teams);
        }
index 93547989097eb43aad853fa417268146eb14d1e9..a875e19ab390bebbaf8a047d6e194ab44b99bf71 100644 (file)
@@ -61,7 +61,6 @@ int autocvar_g_freezetag_teams;
 int autocvar_g_freezetag_teams_override;
 float autocvar_g_freezetag_warmup;
 
-const float SP_FREEZETAG_REVIVALS = 4;
 void freezetag_ScoreRules(int teams)
 {
        ScoreRules_basics(teams, SFL_SORT_PRIO_PRIMARY, SFL_SORT_PRIO_PRIMARY, true); // SFL_SORT_PRIO_PRIMARY
@@ -305,7 +304,7 @@ void havocbot_role_ft_offense(entity this)
        // If only one left on team or if role has timed out then start trying to free players.
        if (((unfrozen == 0) && (!STAT(FROZEN, this))) || (time > this.havocbot_role_timeout))
        {
-               LOG_TRACE("changing role to freeing\n");
+               LOG_TRACE("changing role to freeing");
                this.havocbot_role = havocbot_role_ft_freeing;
                this.havocbot_role_timeout = 0;
                return;
@@ -334,7 +333,7 @@ void havocbot_role_ft_freeing(entity this)
 
        if (time > this.havocbot_role_timeout)
        {
-               LOG_TRACE("changing role to offense\n");
+               LOG_TRACE("changing role to offense");
                this.havocbot_role = havocbot_role_ft_offense;
                this.havocbot_role_timeout = 0;
                return;
index b1a74f2aa998c92e28614b46905f4e9479eb8ca2..184cf33304f59cbace1f0a0762d9aa47d57ceaa1 100644 (file)
@@ -77,7 +77,7 @@ float autocvar_g_invasion_spawn_delay;
 
 spawnfunc(invasion_spawnpoint)
 {
-       if(!g_invasion) { remove(this); return; }
+       if(!g_invasion) { delete(this); return; }
 
        this.classname = "invasion_spawnpoint";
 
@@ -131,7 +131,7 @@ void invasion_SpawnChosenMonster(float mon)
 
        if(spawn_point == NULL)
        {
-               LOG_TRACE("Warning: couldn't find any invasion_spawnpoint spawnpoints, attempting to spawn monsters in random locations\n");
+               LOG_TRACE("Warning: couldn't find any invasion_spawnpoint spawnpoints, attempting to spawn monsters in random locations");
                entity e = spawn();
                setsize(e, (get_monsterinfo(mon)).mins, (get_monsterinfo(mon)).maxs);
 
index 1ce62672d8b6e5d9eaf6c5ffb0d608dcced47edf..da43b84deb3bb3f1909493c18057cb2c5e6e9d91 100644 (file)
@@ -32,10 +32,6 @@ REGISTER_MUTATOR(ka, false)
 
 entity ka_ball;
 
-const float SP_KEEPAWAY_PICKUPS = 4;
-const float SP_KEEPAWAY_CARRIERKILLS = 5;
-const float SP_KEEPAWAY_BCTIME = 6;
-
 void(entity this) havocbot_role_ka_carrier;
 void(entity this) havocbot_role_ka_collector;
 
@@ -470,7 +466,7 @@ MUTATOR_HOOKFUNCTION(ka, HavocBot_ChooseRole)
 MUTATOR_HOOKFUNCTION(ka, DropSpecialItems)
 {
        entity frag_target = M_ARGV(0, entity);
-       
+
        if(frag_target.ballcarried)
                ka_DropEvent(frag_target);
 }
@@ -506,9 +502,9 @@ void ka_SpawnBall() // loads various values for the ball, runs only once at star
 void ka_ScoreRules()
 {
        ScoreRules_basics(0, SFL_SORT_PRIO_PRIMARY, 0, true); // SFL_SORT_PRIO_PRIMARY
-       ScoreInfo_SetLabel_PlayerScore(SP_KEEPAWAY_PICKUPS,                     "pickups",              0);
-       ScoreInfo_SetLabel_PlayerScore(SP_KEEPAWAY_CARRIERKILLS,        "bckills",              0);
-       ScoreInfo_SetLabel_PlayerScore(SP_KEEPAWAY_BCTIME,                      "bctime",               SFL_SORT_PRIO_SECONDARY);
+       ScoreInfo_SetLabel_PlayerScore(SP_KEEPAWAY_PICKUPS,             "pickups",              0);
+       ScoreInfo_SetLabel_PlayerScore(SP_KEEPAWAY_CARRIERKILLS,   "bckills",           0);
+       ScoreInfo_SetLabel_PlayerScore(SP_KEEPAWAY_BCTIME,                  "bctime",           SFL_SORT_PRIO_SECONDARY);
        ScoreRules_basics_end();
 }
 
index 1ffe6e60c07518e44d625b9551a7ac1db74db995..5f6b5226d413d7f03e237eb0277adf4fe8dda037 100644 (file)
@@ -50,8 +50,6 @@ USING(kh_Think_t, void());
 void kh_StartRound();
 void kh_Controller_SetThink(float t, kh_Think_t func);
 
-entity kh_worldkeylist;
-.entity kh_worldkeynext;
 #endif
 
 #ifdef IMPLEMENTATION
@@ -138,12 +136,6 @@ float kh_interferemsg_time, kh_interferemsg_team;
 float kh_key_dropped, kh_key_carried;
 
 const float ST_KH_CAPS = 1;
-const float SP_KH_CAPS = 4;
-const float SP_KH_PUSHES = 5;
-const float SP_KH_DESTROYS = 6;
-const float SP_KH_PICKUPS = 7;
-const float SP_KH_KCKILLS = 8;
-const float SP_KH_LOSSES = 9;
 void kh_ScoreRules(int teams)
 {
        ScoreRules_basics(teams, SFL_SORT_PRIO_PRIMARY, SFL_SORT_PRIO_PRIMARY, true);
@@ -558,7 +550,7 @@ void kh_Key_Remove(entity key)  // runs after when all the keys have been collec
                }
        }
 
-       remove(key);
+       delete(key);
 
        kh_update_state();
 }
@@ -1099,7 +1091,7 @@ void kh_finalize()
 {
        // to be called before intermission
        kh_FinishRound();
-       remove(kh_controller);
+       delete(kh_controller);
        kh_controller = NULL;
 }
 
@@ -1147,7 +1139,7 @@ void havocbot_role_kh_carrier(entity this)
 
        if (!(this.kh_next))
        {
-               LOG_TRACE("changing role to freelancer\n");
+               LOG_TRACE("changing role to freelancer");
                this.havocbot_role = havocbot_role_kh_freelancer;
                this.havocbot_role_timeout = 0;
                return;
@@ -1174,7 +1166,7 @@ void havocbot_role_kh_defense(entity this)
 
        if (this.kh_next)
        {
-               LOG_TRACE("changing role to carrier\n");
+               LOG_TRACE("changing role to carrier");
                this.havocbot_role = havocbot_role_kh_carrier;
                this.havocbot_role_timeout = 0;
                return;
@@ -1184,7 +1176,7 @@ void havocbot_role_kh_defense(entity this)
                this.havocbot_role_timeout = time + random() * 10 + 20;
        if (time > this.havocbot_role_timeout)
        {
-               LOG_TRACE("changing role to freelancer\n");
+               LOG_TRACE("changing role to freelancer");
                this.havocbot_role = havocbot_role_kh_freelancer;
                this.havocbot_role_timeout = 0;
                return;
@@ -1215,7 +1207,7 @@ void havocbot_role_kh_offense(entity this)
 
        if (this.kh_next)
        {
-               LOG_TRACE("changing role to carrier\n");
+               LOG_TRACE("changing role to carrier");
                this.havocbot_role = havocbot_role_kh_carrier;
                this.havocbot_role_timeout = 0;
                return;
@@ -1225,7 +1217,7 @@ void havocbot_role_kh_offense(entity this)
                this.havocbot_role_timeout = time + random() * 10 + 20;
        if (time > this.havocbot_role_timeout)
        {
-               LOG_TRACE("changing role to freelancer\n");
+               LOG_TRACE("changing role to freelancer");
                this.havocbot_role = havocbot_role_kh_freelancer;
                this.havocbot_role_timeout = 0;
                return;
@@ -1257,7 +1249,7 @@ void havocbot_role_kh_freelancer(entity this)
 
        if (this.kh_next)
        {
-               LOG_TRACE("changing role to carrier\n");
+               LOG_TRACE("changing role to carrier");
                this.havocbot_role = havocbot_role_kh_carrier;
                this.havocbot_role_timeout = 0;
                return;
@@ -1269,12 +1261,12 @@ void havocbot_role_kh_freelancer(entity this)
        {
                if (random() < 0.5)
                {
-                       LOG_TRACE("changing role to offense\n");
+                       LOG_TRACE("changing role to offense");
                        this.havocbot_role = havocbot_role_kh_offense;
                }
                else
                {
-                       LOG_TRACE("changing role to defense\n");
+                       LOG_TRACE("changing role to defense");
                        this.havocbot_role = havocbot_role_kh_defense;
                }
                this.havocbot_role_timeout = 0;
@@ -1392,7 +1384,7 @@ MUTATOR_HOOKFUNCTION(kh, HavocBot_ChooseRole)
 MUTATOR_HOOKFUNCTION(kh, DropSpecialItems)
 {
        entity frag_target = M_ARGV(0, entity);
-       
+
        kh_Key_DropAll(frag_target, false);
 }
 
index adfd6eb6a76648b90ddb9f0b33413ec3dae01038..afd107bc43298c08e5d617a3f924c697b386826d 100644 (file)
@@ -32,10 +32,6 @@ REGISTER_MUTATOR(lms, false)
        return 0;
 }
 
-// scoreboard stuff
-const float SP_LMS_LIVES = 4;
-const float SP_LMS_RANK = 5;
-
 // lives related defs
 float lms_lowest_lives;
 float lms_next_place;
@@ -132,7 +128,7 @@ int WinningCondition_LMS()
                {
                        // SNAFU (maybe a draw game?)
                        ClearWinners();
-                       LOG_TRACE("No players, ending game.\n");
+                       LOG_TRACE("No players, ending game.");
                        return WINNING_YES;
                }
        }
@@ -180,7 +176,7 @@ MUTATOR_HOOKFUNCTION(lms, PutClientInServer)
 MUTATOR_HOOKFUNCTION(lms, PlayerDies)
 {
        entity frag_target = M_ARGV(2, entity);
-       
+
        frag_target.respawn_flags |= RESPAWN_FORCE;
 }
 
@@ -392,7 +388,7 @@ MUTATOR_HOOKFUNCTION(lms, GetPlayerStatus)
 MUTATOR_HOOKFUNCTION(lms, AddPlayerScore)
 {
        if(gameover)
-       if(M_ARGV(0, int) == SP_LMS_RANK) // score field
+       if(M_ARGV(0, entity) == SP_LMS_RANK) // score field
                return true; // allow writing to this field in intermission as it is needed for newly joining players
 }
 
index 63fbd15a272476c1184fd26786daf3ce478b5d9c..04561db369e806d5d6d227d49f56614680bb7f8c 100644 (file)
@@ -78,7 +78,7 @@ void race_ScoreRules()
        ScoreRules_basics(race_teams, 0, 0, false);
        if(race_teams)
        {
-               ScoreInfo_SetLabel_TeamScore(  ST_RACE_LAPS,    "laps",      SFL_SORT_PRIO_PRIMARY);
+               ScoreInfo_SetLabel_TeamScore(  ST_RACE_LAPS,    "laps",       SFL_SORT_PRIO_PRIMARY);
                ScoreInfo_SetLabel_PlayerScore(SP_RACE_LAPS,    "laps",      SFL_SORT_PRIO_PRIMARY);
                ScoreInfo_SetLabel_PlayerScore(SP_RACE_TIME,    "time",      SFL_SORT_PRIO_SECONDARY | SFL_LOWER_IS_BETTER | SFL_TIME);
                ScoreInfo_SetLabel_PlayerScore(SP_RACE_FASTEST, "fastest",   SFL_LOWER_IS_BETTER | SFL_TIME);
@@ -143,8 +143,9 @@ float WinningCondition_QualifyingThenRace(float limit)
 MUTATOR_HOOKFUNCTION(rc, PlayerPhysics)
 {
        entity player = M_ARGV(0, entity);
+       float dt = M_ARGV(1, float);
 
-       player.race_movetime_frac += PHYS_INPUT_TIMELENGTH;
+       player.race_movetime_frac += dt;
        float f = floor(player.race_movetime_frac);
        player.race_movetime_frac -= f;
        player.race_movetime_count += f;
@@ -318,7 +319,7 @@ MUTATOR_HOOKFUNCTION(rc, PutClientInServer)
 MUTATOR_HOOKFUNCTION(rc, PlayerDies)
 {
        entity frag_target = M_ARGV(2, entity);
-       
+
        frag_target.respawn_flags |= RESPAWN_FORCE;
        race_AbandonRaceCheck(frag_target);
 }
index 0c7c87c030644f24c062a06bd1a5158f05c788e4..8fdfc83433b57e9251f0ec18ecf3c9a42a9b74a6 100644 (file)
@@ -51,7 +51,7 @@ Keys:
 "cnt" Scoreboard color of the team (for example 4 is red and 13 is blue)... */
 spawnfunc(tdm_team)
 {
-       if(!g_tdm || !this.cnt) { remove(this); return; }
+       if(!g_tdm || !this.cnt) { delete(this); return; }
 
        this.classname = "tdm_team";
        this.team = this.cnt + 1;
@@ -73,7 +73,7 @@ void tdm_DelayedInit(entity this)
        // if no teams are found, spawn defaults
        if(find(NULL, classname, "tdm_team") == NULL)
        {
-               LOG_TRACE("No \"tdm_team\" entities found on this map, creating them anyway.\n");
+               LOG_TRACE("No \"tdm_team\" entities found on this map, creating them anyway.");
 
                int numteams = autocvar_g_tdm_teams_override;
 
index 0a28f206d0b4cb8e0e9ceab1c0f9738903741b47..abf7f71523c12146ad8b5422fe417a4d6048cd90 100644 (file)
@@ -75,7 +75,7 @@ float pathlib_makenode_adaptive(entity parent,vector start, vector to, vector go
 
     if(inwater(parent.origin))
     {
-        LOG_TRACE("FromWater\n");
+        LOG_TRACE("FromWater");
         pathlib_expandnode = pathlib_expandnode_box;
         pathlib_movenode   = pathlib_swimnode;
     }
@@ -83,13 +83,13 @@ float pathlib_makenode_adaptive(entity parent,vector start, vector to, vector go
     {
         if(inwater(to))
         {
-            LOG_TRACE("ToWater\n");
+            LOG_TRACE("ToWater");
             pathlib_expandnode = pathlib_expandnode_box;
             pathlib_movenode   = pathlib_walknode;
         }
         else
         {
-            LOG_TRACE("LandToLoand\n");
+            LOG_TRACE("LandToLoand");
             //if(edge_check(parent.origin))
             //    return 0;
 
@@ -102,7 +102,7 @@ float pathlib_makenode_adaptive(entity parent,vector start, vector to, vector go
     node = pathlib_nodeatpoint(to);
     if(node)
     {
-        LOG_TRACE("NodeAtPoint\n");
+        LOG_TRACE("NodeAtPoint");
         ++pathlib_merge_cnt;
 
         if(node.owner == openlist)
@@ -135,7 +135,7 @@ float pathlib_makenode_adaptive(entity parent,vector start, vector to, vector go
     {
         //pathlib_showsquare(where, 0 ,30);
         //pathlib_showsquare(parent.origin, 1 ,30);
-        LOG_TRACE("pathlib_movenode_goodnode = 0\n");
+        LOG_TRACE("pathlib_movenode_goodnode = 0");
         return 0;
     }
 
@@ -143,9 +143,9 @@ float pathlib_makenode_adaptive(entity parent,vector start, vector to, vector go
 
     if(pathlib_nodeatpoint(where))
     {
-        LOG_TRACE("NAP WHERE :",vtos(where),"\n");
-        LOG_TRACE("not NAP TO:",vtos(to),"\n");
-        LOG_TRACE("NAP-NNAP:",ftos(vlen(to-where)),"\n\n");
+        LOG_TRACE("NAP WHERE :",vtos(where));
+        LOG_TRACE("not NAP TO:",vtos(to));
+        LOG_TRACE("NAP-NNAP:",ftos(vlen(to-where)));
         return 0;
     }
 
@@ -153,7 +153,7 @@ float pathlib_makenode_adaptive(entity parent,vector start, vector to, vector go
     if(doedge)
         if (!tile_check(parent, where))
         {
-            LOG_TRACE("tile_check fail\n");
+            LOG_TRACE("tile_check fail");
 #if DEBUGPATHING
             pathlib_showsquare(where, 0 ,30);
 #endif
@@ -239,7 +239,7 @@ void pathlib_close_node(entity node,vector goal)
 
     if(node.owner == closedlist)
     {
-        LOG_TRACE("Pathlib: Tried to close a closed node!\n");
+        LOG_TRACE("Pathlib: Tried to close a closed node!");
         return;
     }
 
@@ -288,10 +288,10 @@ void pathlib_cleanup()
     }
 
     if(openlist)
-        remove(openlist);
+        delete(openlist);
 
     if(closedlist)
-        remove(closedlist);
+        delete(closedlist);
 
     openlist       = NULL;
     closedlist     = NULL;
@@ -455,12 +455,12 @@ entity pathlib_astar(entity this, vector from,vector to)
     to.y = fsnap(to.y, pathlib_gridsize);
     //to_z += 32;
 
-    LOG_TRACE("AStar init\n");
+    LOG_TRACE("AStar init");
     path = pathlib_mknode(from, NULL);
     pathlib_close_node(path, to);
     if(pathlib_foundgoal)
     {
-        LOG_TRACE("AStar: Goal found on first node!\n");
+        LOG_TRACE("AStar: Goal found on first node!");
 
         open           = new(path_end);
         open.owner     = open;
@@ -473,7 +473,7 @@ entity pathlib_astar(entity this, vector from,vector to)
 
     if(pathlib_expandnode(path, from, to) <= 0)
     {
-        LOG_TRACE("AStar path fail.\n");
+        LOG_TRACE("AStar path fail.");
         pathlib_cleanup();
 
         return NULL;
@@ -491,11 +491,11 @@ entity pathlib_astar(entity this, vector from,vector to)
     {
         if((gettime(GETTIME_REALTIME) - pathlib_starttime) > pathlib_maxtime)
         {
-            LOG_TRACE("Path took to long to compute!\n");
-            LOG_TRACE("Nodes - created: ", ftos(pathlib_made_cnt),"\n");
-            LOG_TRACE("Nodes -    open: ", ftos(pathlib_open_cnt),"\n");
-            LOG_TRACE("Nodes -  merged: ", ftos(pathlib_merge_cnt),"\n");
-            LOG_TRACE("Nodes -  closed: ", ftos(pathlib_closed_cnt),"\n");
+            LOG_TRACE("Path took to long to compute!");
+            LOG_TRACE("Nodes - created: ", ftos(pathlib_made_cnt));
+            LOG_TRACE("Nodes -    open: ", ftos(pathlib_open_cnt));
+            LOG_TRACE("Nodes -  merged: ", ftos(pathlib_merge_cnt));
+            LOG_TRACE("Nodes -  closed: ", ftos(pathlib_closed_cnt));
 
             pathlib_cleanup();
             return NULL;
@@ -512,7 +512,7 @@ entity pathlib_astar(entity this, vector from,vector to)
 
         if(pathlib_foundgoal)
         {
-            LOG_TRACE("Target found. Rebuilding and filtering path...\n");
+            LOG_TRACE("Target found. Rebuilding and filtering path...");
             ftime = gettime(GETTIME_REALTIME);
             ptime = ftime - ptime;
 
@@ -539,26 +539,26 @@ entity pathlib_astar(entity this, vector from,vector to)
 #if DEBUGPATHING
             pathlib_showpath2(start);
 
-            LOG_TRACE("Time used -      pathfinding: ", ftos(ptime),"\n");
-            LOG_TRACE("Time used - rebuild & filter: ", ftos(ftime),"\n");
-            LOG_TRACE("Time used -          cleanup: ", ftos(ctime),"\n");
-            LOG_TRACE("Time used -            total: ", ftos(ptime + ftime + ctime),"\n");
-            LOG_TRACE("Time used -         # frames: ", ftos(ceil((ptime + ftime + ctime) / sys_frametime)),"\n\n");
-            LOG_TRACE("Nodes -         created: ", ftos(pathlib_made_cnt),"\n");
-            LOG_TRACE("Nodes -            open: ", ftos(pathlib_open_cnt),"\n");
-            LOG_TRACE("Nodes -          merged: ", ftos(pathlib_merge_cnt),"\n");
-            LOG_TRACE("Nodes -          closed: ", ftos(pathlib_closed_cnt),"\n");
-            LOG_TRACE("Nodes -        searched: ", ftos(pathlib_searched_cnt),"\n");
-            LOG_TRACE("Nodes bestopen searched: ", ftos(pathlib_bestopen_searched),"\n");
-            LOG_TRACE("Nodes bestcash -   hits: ", ftos(pathlib_bestcash_hits),"\n");
-            LOG_TRACE("Nodes bestcash -   save: ", ftos(pathlib_bestcash_saved),"\n");
-            LOG_TRACE("AStar done.\n");
+            LOG_TRACE("Time used -      pathfinding: ", ftos(ptime));
+            LOG_TRACE("Time used - rebuild & filter: ", ftos(ftime));
+            LOG_TRACE("Time used -          cleanup: ", ftos(ctime));
+            LOG_TRACE("Time used -            total: ", ftos(ptime + ftime + ctime));
+            LOG_TRACE("Time used -         # frames: ", ftos(ceil((ptime + ftime + ctime) / sys_frametime)));
+            LOG_TRACE("Nodes -         created: ", ftos(pathlib_made_cnt));
+            LOG_TRACE("Nodes -            open: ", ftos(pathlib_open_cnt));
+            LOG_TRACE("Nodes -          merged: ", ftos(pathlib_merge_cnt));
+            LOG_TRACE("Nodes -          closed: ", ftos(pathlib_closed_cnt));
+            LOG_TRACE("Nodes -        searched: ", ftos(pathlib_searched_cnt));
+            LOG_TRACE("Nodes bestopen searched: ", ftos(pathlib_bestopen_searched));
+            LOG_TRACE("Nodes bestcash -   hits: ", ftos(pathlib_bestcash_hits));
+            LOG_TRACE("Nodes bestcash -   save: ", ftos(pathlib_bestcash_saved));
+            LOG_TRACE("AStar done.");
 #endif
             return start;
         }
     }
 
-    LOG_TRACE("A* Faild to find a path! Try a smaller gridsize.\n");
+    LOG_TRACE("A* Faild to find a path! Try a smaller gridsize.");
 
     pathlib_cleanup();
 
index 3059021d1238536b9d6b86b627bfbbd623bd6e5e..4a3bfe35c5bee6ba18262a33eff34e3f3a95bc11 100644 (file)
@@ -77,7 +77,7 @@ void a_think(entity this)
 {
     te_lightning1(this,this.origin, this.pos1);
     if(this.cnt < time)
-        remove(this);
+        delete(this);
     else
         this.nextthink = time + 0.2;
 }
@@ -87,7 +87,7 @@ vector pathlib_walknode(entity this, vector start, vector end, float doedge)
     vector direction,point,last_point,s,e;
     float steps, distance, i;
 
-    LOG_TRACE("Walking node from ", vtos(start), " to ", vtos(end), "\n");
+    LOG_TRACE("Walking node from ", vtos(start), " to ", vtos(end));
 
     pathlib_movenode_goodnode = 0;
 
@@ -109,7 +109,7 @@ vector pathlib_walknode(entity this, vector start, vector end, float doedge)
         //start - movenode_maxdrop
         a.cnt = time + 10;
 
-        LOG_TRACE("I cant walk on air!\n");
+        LOG_TRACE("I cant walk on air!");
         return trace_endpos;
     }
 
index a2aaf55635d119e08959f93ae9f3a6292834a989..906ebc7a54b1134d4291648da47e58c878b7831c 100644 (file)
@@ -1,5 +1,5 @@
 #include "path_waypoint.qh"
-#include "../bot/waypoints.qh"
+#include "../bot/api.qh"
 
 #include "pathlib.qh"
 #include "main.qh"
@@ -159,7 +159,7 @@ entity pathlib_waypointpath(entity wp_from, entity wp_to, float callback)
     pathlib_searched_cnt     = 0;
     pathlib_foundgoal      = false;
 
-    LOG_TRACE("pathlib_waypointpath init\n");
+    LOG_TRACE("pathlib_waypointpath init");
 
     // Initialize waypoint grid
     IL_EACH(g_waypoints, true,
@@ -179,10 +179,10 @@ entity pathlib_waypointpath(entity wp_from, entity wp_to, float callback)
     start_node = wp_from;
 
     start_node.pathlib_list = closedlist;
-    LOG_TRACE("Expanding ",ftos(pathlib_wpp_expand(start_node))," links\n");
+    LOG_TRACE("Expanding ",ftos(pathlib_wpp_expand(start_node))," links");
     if(pathlib_open_cnt <= 0)
     {
-        LOG_TRACE("pathlib_waypointpath: Start waypoint not linked! aborting.\n");
+        LOG_TRACE("pathlib_waypointpath: Start waypoint not linked! aborting.");
         return NULL;
     }
 
@@ -196,17 +196,17 @@ entity pathlib_waypointpath_step()
     n = pathlib_wpp_bestopen();
     if(!n)
     {
-        LOG_TRACE("Cannot find best open node, abort.\n");
+        LOG_TRACE("Cannot find best open node, abort.");
         return NULL;
     }
     pathlib_wpp_close(n);
-       LOG_TRACE("Expanding ",ftos(pathlib_wpp_expand(n))," links\n");
+       LOG_TRACE("Expanding ",ftos(pathlib_wpp_expand(n))," links");
 
     if(pathlib_foundgoal)
     {
         entity start, end, open, ln;
 
-        LOG_TRACE("Target found. Rebuilding and filtering path...\n");
+        LOG_TRACE("Target found. Rebuilding and filtering path...");
 
                buildpath_nodefilter = buildpath_nodefilter_none;
                start = path_build(NULL, start_node.origin, NULL, NULL);
index 6cb569149fb89be93781f550e3a242eb3cdfaf99..8a40b111840a34ebf2198ba53787d00fc59a8d2a 100644 (file)
@@ -418,7 +418,7 @@ void Portal_Remove(entity portal, float killed)
                fixedmakevectors(portal.mangle);
                sound(portal, CH_SHOTS, SND_PORTO_EXPLODE, VOL_BASE, ATTEN_NORM);
                Send_Effect(EFFECT_ROCKET_EXPLODE, portal.origin + v_forward * 16, v_forward * 1024, 4);
-               remove(portal);
+               delete(portal);
        }
        else
        {
@@ -642,7 +642,7 @@ entity Portal_Spawn(entity own, vector org, vector ang)
 
        if(!Portal_FindSafeOrigin(portal))
        {
-               remove(portal);
+               delete(portal);
                return NULL;
        }
 
index 163b1667449eb239bf20e392d828b8a263589eef..c49b604e69c0da8660bd9968a6c5680ce9cac6ab 100644 (file)
@@ -10,7 +10,6 @@
 
 #include "../server/_mod.inc"
 #include "bot/_mod.inc"
-#include "bot/havocbot/_mod.inc"
 #include "command/_mod.inc"
 #include "mutators/_mod.inc"
 #include "pathlib/_all.inc"
index e32968c56d54e1f400bb0c8b6070c0738918836f..b315d6cad4ac45b8513a842e8b8081a7a8dac81d 100644 (file)
@@ -4,8 +4,7 @@
 #include "portals.qh"
 #include "scores.qh"
 #include "spawnpoints.qh"
-#include "bot/waypoints.qh"
-#include "bot/navigation.qh"
+#include "bot/api.qh"
 #include "command/getreplies.qh"
 #include "../common/deathtypes/all.qh"
 #include "../common/notifications/all.qh"
@@ -905,7 +904,7 @@ vector trigger_race_checkpoint_spawn_evalfunc(entity this, entity player, entity
 spawnfunc(trigger_race_checkpoint)
 {
        vector o;
-       if(!g_race && !g_cts) { remove(this); return; }
+       if(!g_race && !g_cts) { delete(this); return; }
 
        EXACTTRIGGER_INIT;
 
@@ -953,7 +952,7 @@ spawnfunc(trigger_race_checkpoint)
 spawnfunc(target_checkpoint) // defrag entity
 {
        vector o;
-       if(!g_race && !g_cts) { remove(this); return; }
+       if(!g_race && !g_cts) { delete(this); return; }
        defrag_ents = 1;
 
        EXACTTRIGGER_INIT;
@@ -1031,7 +1030,7 @@ void race_RetractPlayer(entity this)
 
 spawnfunc(info_player_race)
 {
-       if(!g_race && !g_cts) { remove(this); return; }
+       if(!g_race && !g_cts) { delete(this); return; }
        ++race_spawns;
        spawnfunc_info_player_deathmatch(this);
 
index b69b0006a96d1a8a1b381fd4a4aaaf785657fe8a..6360b0ae5aba535b3727c36110ac5a85e099cce1 100644 (file)
@@ -4,9 +4,6 @@ float race_teams;
 
 // scores
 const float ST_RACE_LAPS = 1;
-const float SP_RACE_LAPS = 4;
-const float SP_RACE_TIME = 5;
-const float SP_RACE_FASTEST = 6;
 
 bool g_race_qualifying;
 
index d1302a84d7d0212ed1d1440d7bf5f9105e8fee53..3b11c5f9b6f409e0d51948286cab7160041b3270 100644 (file)
@@ -111,6 +111,6 @@ void round_handler_Reset(float next_think)
 
 void round_handler_Remove()
 {
-       remove(round_handler);
+       delete(round_handler);
        round_handler = NULL;
 }
index 89815b71b132af3f5f3a9a122aec0defbf693c27..e3d5fd9d72e5e0da5a904528c8ded99b87dd7a7e 100644 (file)
@@ -7,10 +7,6 @@
 
 .entity scorekeeper;
 entity teamscorekeepers[16];
-string scores_label[MAX_SCORE];
-float scores_flags[MAX_SCORE];
-string teamscores_label[MAX_TEAMSCORE];
-float teamscores_flags[MAX_TEAMSCORE];
 float teamscores_entities_count;
 var .float scores_primary;
 var .float teamscores_primary;
@@ -65,7 +61,7 @@ bool TeamScore_SendEntity(entity this, entity to, float sendflags)
 
        longflags = 0;
        for(i = 0, p = 1; i < MAX_TEAMSCORE; ++i, p *= 2)
-               if(this.(teamscores[i]) > 127 || this.(teamscores[i]) <= -128)
+               if(this.(teamscores(i)) > 127 || this.(teamscores(i)) <= -128)
                        longflags |= p;
 
 #if MAX_TEAMSCORE <= 8
@@ -79,9 +75,9 @@ bool TeamScore_SendEntity(entity this, entity to, float sendflags)
                if(sendflags & p)
                {
                        if(longflags & p)
-                               WriteInt24_t(MSG_ENTITY, this.(teamscores[i]));
+                               WriteInt24_t(MSG_ENTITY, this.(teamscores(i)));
                        else
-                               WriteChar(MSG_ENTITY, this.(teamscores[i]));
+                               WriteChar(MSG_ENTITY, this.(teamscores(i)));
                }
 
        return true;
@@ -120,9 +116,9 @@ float TeamScore_AddToTeam(float t, float scorefield, float score)
                error("Adding score to unknown team!");
        }
        if(score)
-               if(teamscores_label[scorefield] != "")
+               if(teamscores_label(scorefield) != "")
                        s.SendFlags |= pow(2, scorefield);
-       return (s.(teamscores[scorefield]) += score);
+       return (s.(teamscores(scorefield)) += score);
 }
 
 float TeamScore_Add(entity player, float scorefield, float score)
@@ -139,8 +135,8 @@ float TeamScore_Compare(entity t1, entity t2, float strict)
        for(i = 0; i < MAX_TEAMSCORE; ++i)
        {
                var .float f;
-               f = teamscores[i];
-               result = ScoreField_Compare(t1, t2, f, teamscores_flags[i], result, strict);
+               f = teamscores(i);
+               result = ScoreField_Compare(t1, t2, f, teamscores_flags(i), result, strict);
        }
 
        if (result.x == 0 && strict)
@@ -153,13 +149,13 @@ float TeamScore_Compare(entity t1, entity t2, float strict)
  * the scoreinfo entity
  */
 
-void ScoreInfo_SetLabel_PlayerScore(float i, string label, float scoreflags)
+void ScoreInfo_SetLabel_PlayerScore(PlayerScoreField i, string label, float scoreflags)
 {
-       scores_label[i] = label;
-       scores_flags[i] = scoreflags;
+       scores_label(i) = label;
+       scores_flags(i) = scoreflags;
        if((scoreflags & SFL_SORT_PRIO_MASK) == SFL_SORT_PRIO_PRIMARY)
        {
-               scores_primary = scores[i];
+               scores_primary = scores(i);
                scores_flags_primary = scoreflags;
        }
        if(label != "")
@@ -171,11 +167,11 @@ void ScoreInfo_SetLabel_PlayerScore(float i, string label, float scoreflags)
 
 void ScoreInfo_SetLabel_TeamScore(float i, string label, float scoreflags)
 {
-       teamscores_label[i] = label;
-       teamscores_flags[i] = scoreflags;
+       teamscores_label(i) = label;
+       teamscores_flags(i) = scoreflags;
        if((scoreflags & SFL_SORT_PRIO_MASK) == SFL_SORT_PRIO_PRIMARY)
        {
-               teamscores_primary = teamscores[i];
+               teamscores_primary = teamscores(i);
                teamscores_flags_primary = scoreflags;
        }
        if(label != "")
@@ -189,16 +185,15 @@ bool ScoreInfo_SendEntity(entity this, entity to, int sf)
 {
        float i;
        WriteHeader(MSG_ENTITY, ENT_CLIENT_SCORES_INFO);
-       WriteInt24_t(MSG_ENTITY, MapInfo_LoadedGametype);
-       for(i = 0; i < MAX_SCORE; ++i)
-       {
-               WriteString(MSG_ENTITY, scores_label[i]);
-               WriteByte(MSG_ENTITY, scores_flags[i]);
-       }
+       WriteRegistered(Gametypes, MSG_ENTITY, MapInfo_LoadedGametype);
+       FOREACH(Scores, true, {
+               WriteString(MSG_ENTITY, scores_label(it));
+               WriteByte(MSG_ENTITY, scores_flags(it));
+       });
        for(i = 0; i < MAX_TEAMSCORE; ++i)
        {
-               WriteString(MSG_ENTITY, teamscores_label[i]);
-               WriteByte(MSG_ENTITY, teamscores_flags[i]);
+               WriteString(MSG_ENTITY, teamscores_label(i));
+               WriteByte(MSG_ENTITY, teamscores_flags(i));
        }
        return true;
 }
@@ -230,31 +225,28 @@ void ScoreInfo_Init(int teams)
 
 bool PlayerScore_SendEntity(entity this, entity to, float sendflags)
 {
-       float i, p, longflags;
-
        WriteHeader(MSG_ENTITY, ENT_CLIENT_SCORES);
        WriteByte(MSG_ENTITY, etof(this.owner));
 
-       longflags = 0;
-       for(i = 0, p = 1; i < MAX_SCORE; ++i, p *= 2)
-               if(this.(scores[i]) > 127 || this.(scores[i]) <= -128)
+       int longflags = 0;
+       FOREACH(Scores, true, {
+           int p = 1 << (i % 16);
+               if (this.(scores(it)) > 127 || this.(scores(it)) <= -128)
                        longflags |= p;
+    });
 
-#if MAX_SCORE <= 8
-       WriteByte(MSG_ENTITY, sendflags);
-       WriteByte(MSG_ENTITY, longflags);
-#else
        WriteShort(MSG_ENTITY, sendflags);
        WriteShort(MSG_ENTITY, longflags);
-#endif
-       for(i = 0, p = 1; i < MAX_SCORE; ++i, p *= 2)
-               if(sendflags & p)
+       FOREACH(Scores, true, {
+           int p = 1 << (i % 16);
+               if (sendflags & p)
                {
                        if(longflags & p)
-                               WriteInt24_t(MSG_ENTITY, this.(scores[i]));
+                               WriteInt24_t(MSG_ENTITY, this.(scores(it)));
                        else
-                               WriteChar(MSG_ENTITY, this.(scores[i]));
+                               WriteChar(MSG_ENTITY, this.(scores(it)));
                }
+    });
 
        return true;
 }
@@ -262,7 +254,6 @@ bool PlayerScore_SendEntity(entity this, entity to, float sendflags)
 float PlayerScore_Clear(entity player)
 {
        entity sk;
-       float i;
 
        if(teamscores_entities_count)
                return 0;
@@ -270,13 +261,12 @@ float PlayerScore_Clear(entity player)
        if(MUTATOR_CALLHOOK(ForbidPlayerScore_Clear)) return 0;
 
        sk = player.scorekeeper;
-       for(i = 0; i < MAX_SCORE; ++i)
-       {
-               if(sk.(scores[i]) != 0)
-                       if(scores_label[i] != "")
-                               sk.SendFlags |= pow(2, i);
-               sk.(scores[i]) = 0;
-       }
+       FOREACH(Scores, true, {
+               if(sk.(scores(it)) != 0)
+                       if(scores_label(it) != "")
+                               sk.SendFlags |= pow(2, i % 16);
+               sk.(scores(it)) = 0;
+       });
 
        return 1;
 }
@@ -285,18 +275,15 @@ void Score_ClearAll()
 {
        entity sk;
        float t;
-       FOREACH_CLIENTSLOT(true,
-       {
+       FOREACH_CLIENTSLOT(true, {
                sk = it.scorekeeper;
-               if(!sk)
-                       continue;
-               for(int j = 0; j < MAX_SCORE; ++j)
-               {
-                       if(sk.(scores[j]) != 0)
-                               if(scores_label[j] != "")
-                                       sk.SendFlags |= pow(2, j);
-                       sk.(scores[j]) = 0;
-               }
+               if (!sk) continue;
+               FOREACH(Scores, true, {
+                       if(sk.(scores(it)) != 0)
+                               if(scores_label(it) != "")
+                                       sk.SendFlags |= pow(2, i % 16);
+                       sk.(scores(it)) = 0;
+               });
        });
        for(t = 0; t < 16; ++t)
        {
@@ -305,10 +292,10 @@ void Score_ClearAll()
                        continue;
                for(int j = 0; j < MAX_TEAMSCORE; ++j)
                {
-                       if(sk.(teamscores[j]) != 0)
-                               if(teamscores_label[j] != "")
+                       if(sk.(teamscores(j)) != 0)
+                               if(teamscores_label(j) != "")
                                        sk.SendFlags |= pow(2, j);
-                       sk.(teamscores[j]) = 0;
+                       sk.(teamscores(j)) = 0;
                }
        }
 }
@@ -327,11 +314,11 @@ void PlayerScore_Detach(entity player)
 {
        if(!player.scorekeeper)
                error("player has no scorekeeper");
-       remove(player.scorekeeper);
+       delete(player.scorekeeper);
        player.scorekeeper = NULL;
 }
 
-float PlayerScore_Add(entity player, float scorefield, float score)
+float PlayerScore_Add(entity player, PlayerScoreField scorefield, float score)
 {
        bool mutator_returnvalue = MUTATOR_CALLHOOK(AddPlayerScore, scorefield, score, player);
        score = M_ARGV(1, float);
@@ -346,18 +333,18 @@ float PlayerScore_Add(entity player, float scorefield, float score)
        {
                if(gameover)
                        return 0;
-               LOG_WARNING("Adding score to unknown player!");
+               LOG_WARN("Adding score to unknown player!");
                return 0;
        }
        if(score)
-               if(scores_label[scorefield] != "")
-                       s.SendFlags |= pow(2, scorefield);
+               if(scores_label(scorefield) != "")
+                       s.SendFlags |= pow(2, scorefield.m_id % 16);
        if(!warmup_stage)
-               PS_GR_P_ADDVAL(s.owner, strcat(PLAYERSTATS_TOTAL, scores_label[scorefield]), score);
-       return (s.(scores[scorefield]) += score);
+               PS_GR_P_ADDVAL(s.owner, strcat(PLAYERSTATS_TOTAL, scores_label(scorefield)), score);
+       return (s.(scores(scorefield)) += score);
 }
 
-float PlayerTeamScore_Add(entity player, float pscorefield, float tscorefield, float score)
+float PlayerTeamScore_Add(entity player, PlayerScoreField pscorefield, float tscorefield, float score)
 {
        float r;
        r = PlayerScore_Add(player, pscorefield, score);
@@ -371,13 +358,10 @@ float PlayerScore_Compare(entity t1, entity t2, float strict)
        if(!t1 || !t2) return (!t2) - !t1;
 
        vector result = '0 0 0';
-       float i;
-       for(i = 0; i < MAX_SCORE; ++i)
-       {
-               var .float f;
-               f = scores[i];
-               result = ScoreField_Compare(t1, t2, f, scores_flags[i], result, strict);
-       }
+       FOREACH(Scores, true, {
+               var .float f = scores(it);
+               result = ScoreField_Compare(t1, t2, f, scores_flags(it), result, strict);
+       });
 
        if (result.x == 0 && strict)
                result.x = etof(t1.owner) - etof(t2.owner);
@@ -562,53 +546,59 @@ string GetPlayerScoreString(entity pl, float shortString)
 {
        string out;
        entity sk;
-       float i, f;
+       float f;
        string l;
 
        out = "";
        if(!pl)
        {
                // label
-               for(i = 0; i < MAX_SCORE; ++i)
-                       if((scores_flags[i] & SFL_SORT_PRIO_MASK) == SFL_SORT_PRIO_PRIMARY)
+               FOREACH(Scores, true, {
+                       if ((scores_flags(it) & SFL_SORT_PRIO_MASK) == SFL_SORT_PRIO_PRIMARY)
                        {
-                               f = scores_flags[i];
-                               l = scores_label[i];
+                               f = scores_flags(it);
+                               l = scores_label(it);
                                out = strcat(out, GetScoreLogLabel(l, f), ",");
                        }
+        });
                if(shortString < 2)
-               for(i = 0; i < MAX_SCORE; ++i)
-                       if((scores_flags[i] & SFL_SORT_PRIO_MASK) == SFL_SORT_PRIO_SECONDARY)
+               FOREACH(Scores, true, {
+                       if((scores_flags(it) & SFL_SORT_PRIO_MASK) == SFL_SORT_PRIO_SECONDARY)
                        {
-                               f = scores_flags[i];
-                               l = scores_label[i];
+                               f = scores_flags(it);
+                               l = scores_label(it);
                                out = strcat(out, GetScoreLogLabel(l, f), ",");
                        }
+        });
                if(shortString < 1)
-               for(i = 0; i < MAX_SCORE; ++i)
-                       if((scores_flags[i] & SFL_SORT_PRIO_MASK) != SFL_SORT_PRIO_PRIMARY)
-                       if((scores_flags[i] & SFL_SORT_PRIO_MASK) != SFL_SORT_PRIO_SECONDARY)
+               FOREACH(Scores, true, {
+                       if((scores_flags(it) & SFL_SORT_PRIO_MASK) != SFL_SORT_PRIO_PRIMARY)
+                       if((scores_flags(it) & SFL_SORT_PRIO_MASK) != SFL_SORT_PRIO_SECONDARY)
                        {
-                               f = scores_flags[i];
-                               l = scores_label[i];
+                               f = scores_flags(it);
+                               l = scores_label(it);
                                out = strcat(out, GetScoreLogLabel(l, f), ",");
                        }
+        });
                out = substring(out, 0, strlen(out) - 1);
        }
        else if((sk = pl.scorekeeper))
        {
-               for(i = 0; i < MAX_SCORE; ++i)
-                       if((scores_flags[i] & SFL_SORT_PRIO_MASK) == SFL_SORT_PRIO_PRIMARY)
-                               out = strcat(out, ftos(sk.(scores[i])), ",");
+               FOREACH(Scores, true, {
+                       if ((scores_flags(it) & SFL_SORT_PRIO_MASK) == SFL_SORT_PRIO_PRIMARY)
+                               out = strcat(out, ftos(sk.(scores(it))), ",");
+        });
                if(shortString < 2)
-               for(i = 0; i < MAX_SCORE; ++i)
-                       if((scores_flags[i] & SFL_SORT_PRIO_MASK) == SFL_SORT_PRIO_SECONDARY)
-                               out = strcat(out, ftos(sk.(scores[i])), ",");
+               FOREACH(Scores, true, {
+                       if ((scores_flags(it) & SFL_SORT_PRIO_MASK) == SFL_SORT_PRIO_SECONDARY)
+                               out = strcat(out, ftos(sk.(scores(it))), ",");
+        });
                if(shortString < 1)
-               for(i = 0; i < MAX_SCORE; ++i)
-                       if((scores_flags[i] & SFL_SORT_PRIO_MASK) != SFL_SORT_PRIO_PRIMARY)
-                       if((scores_flags[i] & SFL_SORT_PRIO_MASK) != SFL_SORT_PRIO_SECONDARY)
-                               out = strcat(out, ftos(sk.(scores[i])), ",");
+               FOREACH(Scores, true, {
+                       if((scores_flags(it) & SFL_SORT_PRIO_MASK) != SFL_SORT_PRIO_PRIMARY)
+                       if((scores_flags(it) & SFL_SORT_PRIO_MASK) != SFL_SORT_PRIO_SECONDARY)
+                               out = strcat(out, ftos(sk.(scores(it))), ",");
+        });
                out = substring(out, 0, strlen(out) - 1);
        }
        return out;
@@ -626,27 +616,27 @@ string GetTeamScoreString(float tm, float shortString)
        {
                // label
                for(i = 0; i < MAX_TEAMSCORE; ++i)
-                       if((teamscores_flags[i] & SFL_SORT_PRIO_MASK) == SFL_SORT_PRIO_PRIMARY)
+                       if((teamscores_flags(i) & SFL_SORT_PRIO_MASK) == SFL_SORT_PRIO_PRIMARY)
                        {
-                               f = teamscores_flags[i];
-                               l = teamscores_label[i];
+                               f = teamscores_flags(i);
+                               l = teamscores_label(i);
                                out = strcat(out, GetScoreLogLabel(l, f), ",");
                        }
                if(shortString < 2)
                for(i = 0; i < MAX_TEAMSCORE; ++i)
-                       if((teamscores_flags[i] & SFL_SORT_PRIO_MASK) == SFL_SORT_PRIO_SECONDARY)
+                       if((teamscores_flags(i) & SFL_SORT_PRIO_MASK) == SFL_SORT_PRIO_SECONDARY)
                        {
-                               f = teamscores_flags[i];
-                               l = teamscores_label[i];
+                               f = teamscores_flags(i);
+                               l = teamscores_label(i);
                                out = strcat(out, GetScoreLogLabel(l, f), ",");
                        }
                if(shortString < 1)
                for(i = 0; i < MAX_TEAMSCORE; ++i)
-                       if((teamscores_flags[i] & SFL_SORT_PRIO_MASK) != SFL_SORT_PRIO_PRIMARY)
-                       if((teamscores_flags[i] & SFL_SORT_PRIO_MASK) != SFL_SORT_PRIO_SECONDARY)
+                       if((teamscores_flags(i) & SFL_SORT_PRIO_MASK) != SFL_SORT_PRIO_PRIMARY)
+                       if((teamscores_flags(i) & SFL_SORT_PRIO_MASK) != SFL_SORT_PRIO_SECONDARY)
                        {
-                               f = teamscores_flags[i];
-                               l = teamscores_label[i];
+                               f = teamscores_flags(i);
+                               l = teamscores_label(i);
                                out = strcat(out, GetScoreLogLabel(l, f), ",");
                        }
                out = substring(out, 0, strlen(out) - 1);
@@ -654,17 +644,17 @@ string GetTeamScoreString(float tm, float shortString)
        else if((sk = teamscorekeepers[tm - 1]))
        {
                for(i = 0; i < MAX_TEAMSCORE; ++i)
-                       if((teamscores_flags[i] & SFL_SORT_PRIO_MASK) == SFL_SORT_PRIO_PRIMARY)
-                               out = strcat(out, ftos(sk.(teamscores[i])), ",");
+                       if((teamscores_flags(i) & SFL_SORT_PRIO_MASK) == SFL_SORT_PRIO_PRIMARY)
+                               out = strcat(out, ftos(sk.(teamscores(i))), ",");
                if(shortString < 2)
                for(i = 0; i < MAX_TEAMSCORE; ++i)
-                       if((teamscores_flags[i] & SFL_SORT_PRIO_MASK) == SFL_SORT_PRIO_SECONDARY)
-                               out = strcat(out, ftos(sk.(teamscores[i])), ",");
+                       if((teamscores_flags(i) & SFL_SORT_PRIO_MASK) == SFL_SORT_PRIO_SECONDARY)
+                               out = strcat(out, ftos(sk.(teamscores(i))), ",");
                if(shortString < 1)
                for(i = 0; i < MAX_TEAMSCORE; ++i)
-                       if((teamscores_flags[i] & SFL_SORT_PRIO_MASK) != SFL_SORT_PRIO_PRIMARY)
-                       if((teamscores_flags[i] & SFL_SORT_PRIO_MASK) != SFL_SORT_PRIO_SECONDARY)
-                               out = strcat(out, ftos(sk.(teamscores[i])), ",");
+                       if((teamscores_flags(i) & SFL_SORT_PRIO_MASK) != SFL_SORT_PRIO_PRIMARY)
+                       if((teamscores_flags(i) & SFL_SORT_PRIO_MASK) != SFL_SORT_PRIO_SECONDARY)
+                               out = strcat(out, ftos(sk.(teamscores(i))), ",");
                out = substring(out, 0, strlen(out) - 1);
        }
        return out;
@@ -799,10 +789,10 @@ void Score_NicePrint_Team(entity to, float t, float w)
        {
                s = strcat(s, Team_ColoredFullName(t));
                for(i = 0; i < MAX_TEAMSCORE; ++i)
-                       if(teamscores_label[i] != "")
+                       if(teamscores_label(i) != "")
                        {
-                               fl = teamscores_flags[i];
-                               sc = sk.(teamscores[i]);
+                               fl = teamscores_flags(i);
+                               sc = sk.(teamscores(i));
                                s = strcat(s, " ", Score_NicePrint_ItemColor(fl), ScoreString(fl, sc));
                        }
        }
@@ -811,13 +801,14 @@ void Score_NicePrint_Team(entity to, float t, float w)
 
        s = strcat(s, strpad(max(0, NAMEWIDTH - strlennocol(s)), ""));
 
-       for(i = 0; i < MAX_SCORE; ++i)
-               if(scores_label[i] != "")
+       FOREACH(Scores, true, {
+               if(scores_label(it) != "")
                {
-                       fl = scores_flags[i];
-                       s2 = scores_label[i];
+                       fl = scores_flags(it);
+                       s2 = scores_label(it);
                        s = strcat(s, " ", Score_NicePrint_ItemColor(fl), strpad(-w, substring(s2, 0, w)));
                }
+    });
 
        print_to(to, s);
 }
@@ -845,13 +836,14 @@ void Score_NicePrint_Player(entity to, entity p, float w)
                }
        }
 
-       for(i = 0; i < MAX_SCORE; ++i)
-               if(scores_label[i] != "")
+       FOREACH(Scores, true, {
+               if(scores_label(it) != "")
                {
-                       fl = scores_flags[i];
-                       sc = sk.(scores[i]);
+                       fl = scores_flags(it);
+                       sc = sk.(scores(it));
                        s = strcat(s, " ", Score_NicePrint_ItemColor(fl), strpad(-w, ScoreString(fl, sc)));
                }
+    });
 
        print_to(to, s);
 }
@@ -870,13 +862,13 @@ void Score_NicePrint_Spectator(entity to, entity p)
 void Score_NicePrint(entity to)
 {
        entity p;
-       float i;
        float w;
 
        int t = 0;
-       for(i = 0; i < MAX_SCORE; ++i)
-               if(scores_label[i] != "")
+       FOREACH(Scores, true, {
+               if(scores_label(it) != "")
                        ++t;
+    });
        w = bound(6, floor(SCORESWIDTH / t - 1), 9);
 
        p = PlayerScore_Sort(score_dummyfield, 1, 1, 0);
@@ -905,14 +897,12 @@ void Score_NicePrint(entity to)
 
 void PlayerScore_PlayerStats(entity p)
 {
-       entity s;
-       float i;
-       s = p.scorekeeper;
-
-       for(i = 0; i < MAX_SCORE; ++i)
-               if(s.(scores[i]) != 0)
-                       if(scores_label[i] != "")
-                               PS_GR_P_ADDVAL(s.owner, strcat(PLAYERSTATS_SCOREBOARD, scores_label[i]), s.(scores[i]));
+       entity s = p.scorekeeper;
+       FOREACH(Scores, true, {
+               if(s.(scores(it)) != 0)
+                       if(scores_label(it) != "")
+                               PS_GR_P_ADDVAL(s.owner, strcat(PLAYERSTATS_SCOREBOARD, scores_label(it)), s.(scores(it)));
+    });
 }
 
 void PlayerScore_TeamStats()
@@ -925,9 +915,9 @@ void PlayerScore_TeamStats()
                if(!sk)
                        continue;
                for(i = 0; i < MAX_TEAMSCORE; ++i)
-                       if(sk.(teamscores[i]) != 0)
-                               if(teamscores_label[i] != "")
+                       if(sk.(teamscores(i)) != 0)
+                               if(teamscores_label(i) != "")
                                        // the +1 is important here!
-                                       PS_GR_T_ADDVAL(t+1, strcat(PLAYERSTATS_SCOREBOARD, teamscores_label[i]), sk.(teamscores[i]));
+                                       PS_GR_T_ADDVAL(t+1, strcat(PLAYERSTATS_SCOREBOARD, teamscores_label(i)), sk.(teamscores(i)));
        }
 }
index a462bde92c4bed31f706262a2314b43a5c3ff8f0..cf767659056d5f9cef2a39ae063d18a5923c8c5e 100644 (file)
@@ -3,8 +3,6 @@
 #include <common/constants.qh>
 
 entity scores_initialized; // non-NULL when scores labels/rules have been set
-.float scores[MAX_SCORE];
-.float teamscores[MAX_TEAMSCORE];
 .float scoreboard_pos;
 
 /**
@@ -24,7 +22,7 @@ void PlayerScore_Detach(entity player);
  * Means: FIXME make players unable to join the game when not called ClientConnect yet.
  * Returns the new score.
  */
-float PlayerScore_Add(entity player, float scorefield, float score);
+float PlayerScore_Add(entity player, PlayerScoreField scorefield, float score);
 
 /**
  * Initialize the score of this player if needed.
@@ -57,12 +55,12 @@ float TeamScore_GetCompareValue(float t);
  * Adds a score to both the player and the team. Returns the team score if
  * possible, otherwise the player score.
  */
-float PlayerTeamScore_Add(entity player, float pscorefield, float tscorefield, float score);
+float PlayerTeamScore_Add(entity player, PlayerScoreField pscorefield, float tscorefield, float score);
 
 /**
  * Adds to the generic score fields for both the player and the team.
  */
-#define PlayerTeamScore_AddScore(p,s) PlayerTeamScore_Add(p, SP_SCORE, ST_SCORE, s)
+#define PlayerTeamScore_AddScore(p, s) PlayerTeamScore_Add(p, SP_SCORE, ST_SCORE, s)
 
 /**
  * Set the label of a team score item, as well as the scoring flags.
@@ -72,7 +70,7 @@ void ScoreInfo_SetLabel_TeamScore(float i, string label, float scoreflags);
 /**
  * Set the label of a player score item, as well as the scoring flags.
  */
-void ScoreInfo_SetLabel_PlayerScore(float i, string label, float scoreflags);
+void ScoreInfo_SetLabel_PlayerScore(PlayerScoreField i, string label, float scoreflags);
 
 /**
  * Initialize the scores info for the given number of teams.
index b93c114c06eb40f1c18fa829d3196a93a32ac795..d3aceac50b2b28e8f2606d74ab4fe4713b12bba7 100644 (file)
@@ -19,14 +19,14 @@ int AvailableTeams()
        //return boolean(c1 >= 0) + boolean(c2 >= 0) + boolean(c3 >= 0) + boolean(c4 >= 0);
 }
 
-// NOTE: SP_ constants may not be >= MAX_SCORE; ST_constants may not be >= MAX_TEAMSCORE
+// NOTE: ST_constants may not be >= MAX_TEAMSCORE
 // scores that should be in all modes:
 void ScoreRules_basics(int teams, float sprio, float stprio, float score_enabled)
 {
-       float i;
-       for(i = 0; i < MAX_SCORE; ++i)
-               ScoreInfo_SetLabel_PlayerScore(i, "", 0);
-       for(i = 0; i < MAX_TEAMSCORE; ++i)
+       FOREACH(Scores, true, {
+               ScoreInfo_SetLabel_PlayerScore(it, "", 0);
+    });
+       for(int i = 0; i < MAX_TEAMSCORE; ++i)
                ScoreInfo_SetLabel_TeamScore(i, "", 0);
 
        ScoreRules_teams = teams;
@@ -47,6 +47,7 @@ void ScoreRules_basics(int teams, float sprio, float stprio, float score_enabled
 
        ScoreInfo_SetLabel_PlayerScore(SP_DMG, "damage", 0);
        ScoreInfo_SetLabel_PlayerScore(SP_DMGTAKEN, "damagetaken", SFL_LOWER_IS_BETTER);
+       ScoreInfo_SetLabel_PlayerScore(SP_ELO, "elo", 0);
 }
 void ScoreRules_basics_end()
 {
index 4be19b879d317ac5976bbe87f3c70cd7f1870e93..958b0bd6e3a7c7ddf8ebefced698652592d80f19 100644 (file)
@@ -265,7 +265,7 @@ vector Spawn_Score(entity this, entity spot, float mindist, float teamcheck)
 
                if(!found)
                {
-                       LOG_TRACE("WARNING: spawnpoint at ", vtos(spot.origin), " could not find its target ", spot.target, "\n");
+                       LOG_TRACE("WARNING: spawnpoint at ", vtos(spot.origin), " could not find its target ", spot.target);
                        return '-1 0 0';
                }
        }
index 7469d2230de7e1bd79f3c9746410d7d42e880b23..4a72bb1aee81d2444355b7d305d37ed83b32c13c 100644 (file)
@@ -4,8 +4,7 @@
 #include "g_hook.qh"
 #include "g_world.qh"
 
-#include "bot/bot.qh"
-#include "bot/waypoints.qh"
+#include "bot/api.qh"
 
 #include "command/common.qh"
 
@@ -155,11 +154,12 @@ float game_delay_last;
 
 bool autocvar_sv_autopause = false;
 float RedirectionThink();
-void PM_Main(Client this);
+void systems_update();
+void sys_phys_update(entity this, float dt);
 void StartFrame()
 {
     // TODO: if move is more than 50ms, split it into two moves (this matches QWSV behavior and the client prediction)
-    FOREACH_ENTITY_CLASS(STR_PLAYER, IS_FAKE_CLIENT(it), PM_Main(it));
+    FOREACH_ENTITY_CLASS(STR_PLAYER, IS_FAKE_CLIENT(it), sys_phys_update(it, frametime));
     FOREACH_ENTITY_CLASS(STR_PLAYER, IS_FAKE_CLIENT(it), PlayerPreThink(it));
 
        execute_next_frame();
@@ -246,7 +246,7 @@ void SV_OnEntityPreSpawnFunction(entity this)
        if (this.gametypefilter != "")
        if (!isGametypeInFilter(MapInfo_LoadedGametype, teamplay, have_team_spawns, this.gametypefilter))
        {
-               remove(this);
+               delete(this);
                __spawnfunc_expecting = false;
                return;
        }
@@ -355,7 +355,7 @@ LABEL(cvar_fail)
                if (!inv)
                {
                        //print("cvarfilter fail\n");
-                       remove(this);
+                       delete(this);
                        __spawnfunc_expecting = false;
                        return;
                }
@@ -363,12 +363,12 @@ LABEL(cvar_fail)
 
        if(DoesQ3ARemoveThisEntity(this))
        {
-               remove(this);
+               delete(this);
                __spawnfunc_expecting = false;
                return;
        }
 
-       this.move_movetype = this.movetype;
+       set_movetype(this, this.movetype);
 
        // support special -1 and -2 angle from radiant
        if (this.angles == '0 -1 0')
@@ -393,7 +393,7 @@ LABEL(cvar_fail)
 
        if(MUTATOR_CALLHOOK(OnEntityPreSpawn, this))
        {
-               remove(this);
+               delete(this);
                __spawnfunc_expecting = false;
                return;
        }
index 32024aec5f258fe6c0615652d4838b2bc7357b98..1ccf6695a185a1ad37558818e8ada3ae1205ccd6 100644 (file)
@@ -2,7 +2,6 @@
 
 #undef droptofloor
 #undef sound
-#undef remove
 #undef cvar_set
 #undef cvar_string
 #undef cvar
index e2156705a03b0cd1de67161f0b61ed6ba7d8eb42..56f85bd4689fd47a7f189dec8d57949435213adf 100644 (file)
@@ -5,7 +5,7 @@
 #include "scores.qh"
 #include "scores_rules.qh"
 
-#include "bot/bot.qh"
+#include "bot/api.qh"
 
 #include "command/vote.qh"
 
index 7bbf00dc51c335262f6b3a757b3d97188d5692c5..96674db702943a933786ca954c4ec20498839ae8 100644 (file)
@@ -3,8 +3,8 @@
 void test_weapons_hurt(entity this)
 {
     EXPECT_NE(100, this.health);
-    remove(this.enemy);
-    remove(this);
+    delete(this.enemy);
+    delete(this);
 }
 
 TEST(Weapons, Hurt)
index abb41ad06a8e812569217467106b04f8e2877600..9efc4ce6a0700f31511eb9dfb2c9a5ae56e92cb9 100644 (file)
@@ -47,7 +47,7 @@ void accuracy_init(entity e)
 
 void accuracy_free(entity e)
 {
-       remove(e.accuracy);
+       delete(e.accuracy);
 }
 
 // force a resend of a player's accuracy stats
index 0288347ee1f1e61bdaa47cc70b93479c04f2f02f..ff5eaa59a41e187b7a29f4f6939a4f042b7d8806 100644 (file)
@@ -29,7 +29,7 @@ void Weapon_whereis(Weapon this, entity cl)
                        continue;
                entity wp = WaypointSprite_Spawn(
                        WP_Weapon,
-                       1, 0,
+                       -2, 0,
                        NULL, it.origin + ('0 0 1' * it.maxs.z) * 1.2,
                        cl, 0,
                        NULL, enemy,
@@ -75,7 +75,7 @@ bool client_hasweapon(entity this, Weapon wpn, float andammo, bool complain)
 
                                // always allow selecting the Mine Layer if we placed mines, so that we can detonate them
                                if(wpn == WEP_MINE_LAYER)
-                                       FOREACH_ENTITY_CLASS("mine", it.owner == this,
+                                       IL_EACH(g_mines, it.owner == this,
                                        {
                                                f = 1;
                                                break; // no need to continue
@@ -101,7 +101,15 @@ bool client_hasweapon(entity this, Weapon wpn, float andammo, bool complain)
                if (weaponsInMap & WepSet_FromWeapon(wpn))
                {
                        Send_WeaponComplain(this, wpn.m_id, 1);
-                       Weapon_whereis(wpn, this);
+                       if(autocvar_g_showweaponspawns < 3)
+                               Weapon_whereis(wpn, this);
+                       else
+                       {
+                               FOREACH(Weapons, it.impulse == wpn.impulse,
+                               {
+                                       Weapon_whereis(it, this);
+                               });
+                       }
                }
                else
                {
@@ -264,8 +272,11 @@ void W_SwitchWeapon(entity this, Weapon w)
        }
        else if(!forbidWeaponUse(this)) {
                entity actor = this;
-               .entity weaponentity = weaponentities[0]; // TODO: unhardcode
-               w.wr_reload(w, actor, weaponentity);
+               for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+               {
+                       .entity weaponentity = weaponentities[slot];
+                       w.wr_reload(w, actor, weaponentity);
+               }
        }
 }
 
index 748f434eb325dd3cf002279d599cd8ed2dade4ef..faec22f307315b37f06b47b40d72d0e64cb272e5 100644 (file)
@@ -39,7 +39,7 @@ void weapon_defaultspawnfunc(entity this, Weapon e)
                s = M_ARGV(2, string);
                if (s == "")
                {
-                       remove(this);
+                       delete(this);
                        startitem_failed = true;
                        return;
                }
@@ -76,7 +76,7 @@ void weapon_defaultspawnfunc(entity this, Weapon e)
                }
                if (wpn == WEP_Null)
                {
-                       remove(this);
+                       delete(this);
                        startitem_failed = true;
                        return;
                }
index c69b8e9a9ce1c2ebb70e2c8799f84535a3a2b606..7cc7580c17dd8922b894cc141e47fd63de9d70a0 100644 (file)
@@ -45,6 +45,7 @@ string W_ThrowNewWeapon(entity own, float wpn, float doreduce, vector org, vecto
        wep.owner = wep.enemy = own;
        wep.flags |= FL_TOSSED;
        wep.colormap = own.colormap;
+       wep.glowmod = weaponentity_glowmod(info, own.clientcolors);
 
        W_DropEvent(wr_drop,own,wpn,wep);
 
@@ -79,7 +80,6 @@ string W_ThrowNewWeapon(entity own, float wpn, float doreduce, vector org, vecto
        weapon_defaultspawnfunc(wep, info);
        if(startitem_failed)
                return string_null;
-       wep.glowmod = weaponentity_glowmod(info, own.clientcolors);
        setthink(wep, thrown_wep_think);
        wep.savenextthink = wep.nextthink;
        wep.nextthink = min(wep.nextthink, time + 0.5);
@@ -165,7 +165,7 @@ bool W_IsWeaponThrowable(entity this, int w)
 }
 
 // toss current weapon
-void W_ThrowWeapon(entity this, vector velo, vector delta, float doreduce)
+void W_ThrowWeapon(entity this, .entity weaponentity, vector velo, vector delta, float doreduce)
 {
        Weapon w = PS(this).m_weapon;
        if (w == WEP_Null)
@@ -174,7 +174,6 @@ void W_ThrowWeapon(entity this, vector velo, vector delta, float doreduce)
                return;
        if(!autocvar_g_weapon_throwable)
                return;
-       .entity weaponentity = weaponentities[0]; // TODO: unhardcode
        if(this.(weaponentity).state != WS_READY)
                return;
        if(!W_IsWeaponThrowable(this, w.m_id))
index 5a27025bc8bfcd146ed19a9a52eed1600ed66f75..a03968083edbd5e1e0a1c06a8471a1058b8b8843 100644 (file)
@@ -9,6 +9,6 @@ string W_ThrowNewWeapon(entity own, float wpn, float doreduce, vector org, vecto
 bool W_IsWeaponThrowable(entity this, int w);
 
 // toss current weapon
-void W_ThrowWeapon(entity this, vector velo, vector delta, float doreduce);
+void W_ThrowWeapon(entity this, .entity weaponentity, vector velo, vector delta, float doreduce);
 
 void SpawnThrownWeapon(entity this, vector org, float w);
index 6e7279618cc497a2b0ae99d6baa6785a112851bd..f773180fea091f1621a03b1886aba93a3ed9ee69 100644 (file)
@@ -20,9 +20,9 @@
 // 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.
 // make sure you call makevectors first (FIXME?)
-void W_SetupShot_Dir_ProjectileSize_Range(entity ent, vector s_forward, vector mi, vector ma, float antilag, float recoil, Sound snd, float chan, float maxdamage, float range)
+void W_SetupShot_Dir_ProjectileSize_Range(entity ent, .entity weaponentity, vector s_forward, vector mi, vector ma, float antilag, float recoil, Sound snd, float chan, float maxdamage, float range)
 {
-    TC(Sound, snd);
+       TC(Sound, snd);
        float nudge = 1; // added to traceline target and subtracted from result  TOOD(divVerent): do we still need this? Doesn't the engine do this now for us?
        float oldsolid;
        vector vecs, dv;
@@ -58,7 +58,6 @@ void W_SetupShot_Dir_ProjectileSize_Range(entity ent, vector s_forward, vector m
        if(IS_PLAYER(ent))
                W_HitPlotAnalysis(ent, v_forward, v_right, v_up);
 
-       .entity weaponentity = weaponentities[0]; // TODO: unhardcode
        vector md = ent.(weaponentity).movedir;
        if(md.x > 0)
                vecs = md;
@@ -300,7 +299,7 @@ void FireRailgunBullet (entity this, vector start, vector end, float bdamage, fl
                ));
 
                if(pseudoprojectile)
-                       remove(pseudoprojectile);
+                       delete(pseudoprojectile);
        }
 
        // find all the entities the railgun hit and hurt them
@@ -476,7 +475,10 @@ void fireBullet(entity this, vector start, vector dir, float spread, float max_s
                        break;
 
                float dist_taken = max(autocvar_g_ballistics_mindistance, vlen(trace_endpos - start));
-               solid_penetration_left *= (dist_taken / maxdist);
+               // fraction_used_of_what_is_left = dist_taken / maxdist
+               // solid_penetration_left = solid_penetration_left - solid_penetration_left * fraction_used_of_what_is_left
+               solid_penetration_left *= 1 - dist_taken / maxdist;
+               solid_penetration_left = max(solid_penetration_left, 0);
 
                // Only show effect when going through a player (invisible otherwise)
                if (hit && (hit.solid != SOLID_BSP))
index 52e5bd840e21e9adf9eb57a4e8cf3c9366000ab3..21f12c1e4c02633ef9d16f658b99990a87cf74b9 100644 (file)
@@ -7,13 +7,13 @@ vector w_shotend;
 // 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.
 // make sure you call makevectors first (FIXME?)
-void W_SetupShot_Dir_ProjectileSize_Range(entity ent, vector s_forward, vector mi, vector ma, float antilag, float recoil, Sound snd, float chan, float maxdamage, float range);
+void W_SetupShot_Dir_ProjectileSize_Range(entity ent, .entity weaponentity, vector s_forward, vector mi, vector ma, float antilag, float recoil, Sound snd, float chan, float maxdamage, float range);
 
-#define W_SetupShot_Dir_ProjectileSize(ent,s_forward,mi,ma,antilag,recoil,snd,chan,maxdamage) W_SetupShot_Dir_ProjectileSize_Range(ent, s_forward, mi, ma, antilag, recoil, snd, chan, maxdamage, MAX_SHOT_DISTANCE)
-#define W_SetupShot_ProjectileSize(ent,mi,ma,antilag,recoil,snd,chan,maxdamage) W_SetupShot_Dir_ProjectileSize(ent, v_forward, mi, ma, antilag, recoil, snd, chan, maxdamage)
-#define W_SetupShot_Dir(ent,s_forward,antilag,recoil,snd,chan,maxdamage) W_SetupShot_Dir_ProjectileSize(ent, s_forward, '0 0 0', '0 0 0', antilag, recoil, snd, chan, maxdamage)
-#define W_SetupShot(ent,antilag,recoil,snd,chan,maxdamage) W_SetupShot_ProjectileSize(ent, '0 0 0', '0 0 0', antilag, recoil, snd, chan, maxdamage)
-#define W_SetupShot_Range(ent,antilag,recoil,snd,chan,maxdamage,range) W_SetupShot_Dir_ProjectileSize_Range(ent, v_forward, '0 0 0', '0 0 0', antilag, recoil, snd, chan, maxdamage, range)
+#define W_SetupShot_Dir_ProjectileSize(ent,wepent,s_forward,mi,ma,antilag,recoil,snd,chan,maxdamage) W_SetupShot_Dir_ProjectileSize_Range(ent, wepent, s_forward, mi, ma, antilag, recoil, snd, chan, maxdamage, MAX_SHOT_DISTANCE)
+#define W_SetupShot_ProjectileSize(ent,wepent,mi,ma,antilag,recoil,snd,chan,maxdamage) W_SetupShot_Dir_ProjectileSize(ent, wepent, v_forward, mi, ma, antilag, recoil, snd, chan, maxdamage)
+#define W_SetupShot_Dir(ent,wepent,s_forward,antilag,recoil,snd,chan,maxdamage) W_SetupShot_Dir_ProjectileSize(ent, wepent, s_forward, '0 0 0', '0 0 0', antilag, recoil, snd, chan, maxdamage)
+#define W_SetupShot(ent,wepent,antilag,recoil,snd,chan,maxdamage) W_SetupShot_ProjectileSize(ent, wepent, '0 0 0', '0 0 0', antilag, recoil, snd, chan, maxdamage)
+#define W_SetupShot_Range(ent,wepent,antilag,recoil,snd,chan,maxdamage,range) W_SetupShot_Dir_ProjectileSize_Range(ent, wepent, v_forward, '0 0 0', '0 0 0', antilag, recoil, snd, chan, maxdamage, range)
 
 vector W_CalculateProjectileVelocity(entity actor, vector pvelocity, vector mvelocity, float forceAbsolute);
 
index 7c8061e94e02d24cfd2e08510983296e89ea0ee1..c0ed81e68173da34f4c819e6701e924cf2f6f748 100644 (file)
@@ -54,7 +54,7 @@ vector CL_Weapon_GetShotOrg(int wpn)
        CL_WeaponEntity_SetModel(e, wi.mdl, false);
        vector ret = e.movedir;
        CL_WeaponEntity_SetModel(e, "", false);
-       remove(e);
+       delete(e);
        return ret;
 }
 
@@ -69,8 +69,8 @@ void CL_Weaponentity_Think(entity this)
        if (this.owner.(weaponentity) != this)
        {
                // owner has new gun; remove old one
-               if (this.weaponchild) remove(this.weaponchild);
-               remove(this);
+               if (this.weaponchild) delete(this.weaponchild);
+               delete(this);
                return;
        }
        if (IS_DEAD(this.owner))
@@ -110,7 +110,7 @@ void CL_ExteriorWeaponentity_Think(entity this)
        this.nextthink = time;
        if (this.owner.exteriorweaponentity != this)
        {
-               remove(this);
+               delete(this);
                return;
        }
        if (IS_DEAD(this.owner))
@@ -215,10 +215,9 @@ bool weapon_prepareattack_checkammo(Weapon thiswep, entity actor, bool secondary
        // always keep the Mine Layer if we placed mines, so that we can detonate them
        if (thiswep == WEP_MINE_LAYER)
        {
-               FOREACH_ENTITY_ENT(owner, actor,
+               IL_EACH(g_mines, it.owner == actor,
                {
-                       if(it.classname != "mine") continue;
-                       if(it.owner == actor) return false;
+                       return false;
                });
        }
 
@@ -418,11 +417,10 @@ bool forbidWeaponUse(entity player)
 
 .bool hook_switchweapon;
 
-void W_WeaponFrame(Player actor)
+void W_WeaponFrame(Player actor, .entity weaponentity)
 {
     TC(Player, actor);
     TC(PlayerState, PS(actor));
-       .entity weaponentity = weaponentities[0];  // TODO: unhardcode
        entity this = actor.(weaponentity);
        if (frametime) actor.weapon_frametime = frametime;
 
@@ -460,7 +458,7 @@ void W_WeaponFrame(Player actor)
                switch (this.state)
                {
                        default:
-                               LOG_WARNINGF("unhandled weaponentity (%i) state for player (%i): %d\n", this, actor, this.state);
+                               LOG_WARNF("unhandled weaponentity (%i) state for player (%i): %d", this, actor, this.state);
                                break;
                        case WS_INUSE:
                        case WS_RAISE:
@@ -571,7 +569,7 @@ void W_WeaponFrame(Player actor)
                        }
                        else if (e)
                        {
-                               e.wr_gonethink(e, actor);
+                               e.wr_gonethink(e, actor, weaponentity);
                        }
                }
 
@@ -594,9 +592,8 @@ void W_WeaponFrame(Player actor)
        }
 }
 
-void W_AttachToShotorg(entity actor, entity flash, vector offset)
+void W_AttachToShotorg(entity actor, .entity weaponentity, entity flash, vector offset)
 {
-       .entity weaponentity = weaponentities[0];
        flash.owner = actor;
        flash.angles_z = random() * 360;
 
@@ -691,10 +688,9 @@ void W_ReloadedAndReady(Weapon thiswep, entity actor, .entity weaponentity, int
        w_ready(wpn, actor, weaponentity, PHYS_INPUT_BUTTON_ATCK(actor) | (PHYS_INPUT_BUTTON_ATCK2(actor) << 1));
 }
 
-void W_Reload(entity actor, float sent_ammo_min, Sound sent_sound)
+void W_Reload(entity actor, .entity weaponentity, float sent_ammo_min, Sound sent_sound)
 {
     TC(Sound, sent_sound);
-       .entity weaponentity = weaponentities[0];
        // set global values to work with
        Weapon e = PS(actor).m_weapon;
 
index 2aeca53811ecce7b1dae7595aea7b77b4713921a..d0ba63412198f1d6c016484965a0aba1c610fc87 100644 (file)
@@ -10,15 +10,15 @@ vector CL_Weapon_GetShotOrg(float wpn);
 
 float forbidWeaponUse(entity player);
 
-void W_AttachToShotorg(entity actor, entity flash, vector offset);
+void W_AttachToShotorg(entity actor, .entity weaponentity, entity flash, vector offset);
 
 void W_DecreaseAmmo(Weapon wep, entity actor, float ammo_use);
 
 void W_DropEvent(.void(Weapon, entity actor) event, entity player, float weapon_type, entity weapon_item);
 
-void W_Reload(entity actor, float sent_ammo_min, Sound sent_sound);
+void W_Reload(entity actor, .entity weaponentity, float sent_ammo_min, Sound sent_sound);
 
-void W_WeaponFrame(Player actor);
+void W_WeaponFrame(Player actor, .entity weaponentity);
 
 float W_WeaponRateFactor(entity this);
 
diff --git a/qcsrc/tools/cloc.txt b/qcsrc/tools/cloc.txt
new file mode 100644 (file)
index 0000000..9b1b3af
--- /dev/null
@@ -0,0 +1,13 @@
+QC
+    filter call_regexp_common C++
+    filter remove_inline //.*$
+    extension qc
+    extension inc
+    3rd_gen_scale 0.5
+    end_of_line_continuation \\$
+QC Header
+    filter call_regexp_common C++
+    filter remove_inline //.*$
+    extension qh
+    3rd_gen_scale 0.5
+    end_of_line_continuation \\$
index b638927bf4a50441d0adef391b4f48101337cef6..daf20ebf3ba748a68be9a1712be73c532f605fa9 100755 (executable)
@@ -1,6 +1,6 @@
-#!/bin/bash
+#!/usr/bin/env bash
 set -eu
-cd "$(dirname "$0")"
+cd ${0%/*}
 cd ..
 
 function startswith() {
index 5662337411f3767e852ec0a8b65226cc64826ca6..594c60ea29d8ae509dfd3d748987e74f0fe21b60 100755 (executable)
@@ -1,6 +1,6 @@
-#!/bin/bash
+#!/usr/bin/env bash
 set -eu
-cd "$(dirname "$0")"
+cd ${0%/*}
 cd ..
 
 function check() {
@@ -14,6 +14,7 @@ function check() {
 
 check lib
 check common
+check ecs
 check client
 check server
 check menu
index 98cdab9dd51b3036def6ce08a78f128abdc91d22..b598727223ee7321209bbc9360e9d32cd833a565 100644 (file)
@@ -418,7 +418,7 @@ sp_angle_shift                           = ignore   # ignore/add/remove/force
 sp_permit_cpp11_shift                    = false    # false/true
 
 # Add or remove space before '(' of 'if', 'for', 'switch', and 'while'
-sp_before_sparen                         = add      # ignore/add/remove/force #force
+sp_before_sparen                         = force    # ignore/add/remove/force #force
 
 # Add or remove space inside if-condition '(' and ')'
 # NOTE: is 68 worse than ignore
@@ -431,10 +431,10 @@ sp_inside_sparen_close                   = ignore   # ignore/add/remove/force #f
 sp_inside_sparen_open                    = ignore   # ignore/add/remove/force #force
 
 # Add or remove space after ')' of 'if', 'for', 'switch', and 'while'
-sp_after_sparen                          = add      # ignore/add/remove/force
+sp_after_sparen                          = force    # ignore/add/remove/force
 
 # Add or remove space between ')' and '{' of 'if', 'for', 'switch', and 'while'
-sp_sparen_brace                          = add      # ignore/add/remove/force
+sp_sparen_brace                          = force    # ignore/add/remove/force
 
 # Add or remove space between 'invariant' and '(' in the D language.
 sp_invariant_paren                       = ignore   # ignore/add/remove/force #ignore
@@ -630,11 +630,11 @@ sp_macro                                 = remove   # ignore/add/remove/force #f
 sp_macro_func                            = remove   # ignore/add/remove/force #force
 
 # Add or remove space between 'else' and '{' if on the same line
-sp_else_brace                            = add      # ignore/add/remove/force
+sp_else_brace                            = force    # ignore/add/remove/force
 
 # Add or remove space between '}' and 'else' if on the same line
 # WARNING: Code doesn't seem to use this feature - delete from the config?
-sp_brace_else                            = ignore   # ignore/add/remove/force
+sp_brace_else                            = force    # ignore/add/remove/force
 
 # Add or remove space between '}' and the name of a typedef on the same line
 sp_brace_typedef                         = add      # ignore/add/remove/force
@@ -1116,17 +1116,17 @@ nl_union_brace                           = ignore   # ignore/add/remove/force
 
 # Add or remove newline between 'if' and '{'
 # NOTE: is 136 worse than ignore
-nl_if_brace                              = add      # ignore/add/remove/force
+nl_if_brace                              = remove   # ignore/add/remove/force
 
 # Add or remove newline between '}' and 'else'
-nl_brace_else                            = add      # ignore/add/remove/force
+nl_brace_else                            = remove   # ignore/add/remove/force
 
 # Add or remove newline between 'else if' and '{'
 # If set to ignore, nl_if_brace is used instead
-nl_elseif_brace                          = add      # ignore/add/remove/force
+nl_elseif_brace                          = remove   # ignore/add/remove/force
 
 # Add or remove newline between 'else' and '{'
-nl_else_brace                            = add      # ignore/add/remove/force
+nl_else_brace                            = remove   # ignore/add/remove/force
 
 # Add or remove newline between 'else' and 'if'
 nl_else_if                               = remove   # ignore/add/remove/force
@@ -1137,7 +1137,7 @@ nl_brace_finally                         = ignore   # ignore/add/remove/force
 
 # Add or remove newline between 'finally' and '{'
 # WARNING: Code doesn't seem to use this feature - delete from the config?
-nl_finally_brace                         = ignore   # ignore/add/remove/force
+nl_finally_brace                         = remove   # ignore/add/remove/force
 
 # Add or remove newline between 'try' and '{'
 # WARNING: Code doesn't seem to use this feature - delete from the config?
@@ -1149,7 +1149,7 @@ nl_getset_brace                          = ignore   # ignore/add/remove/force
 
 # Add or remove newline between 'for' and '{'
 # NOTE: is 109 worse than ignore
-nl_for_brace                             = add      # ignore/add/remove/force
+nl_for_brace                             = remove   # ignore/add/remove/force
 
 # Add or remove newline between 'catch' and '{'
 # WARNING: Code doesn't seem to use this feature - delete from the config?
@@ -1161,7 +1161,7 @@ nl_brace_catch                           = ignore   # ignore/add/remove/force
 
 # Add or remove newline between 'while' and '{'
 # NOTE: is 22 worse than ignore
-nl_while_brace                           = add      # ignore/add/remove/force
+nl_while_brace                           = remove   # ignore/add/remove/force
 
 # Add or remove newline between 'scope (x)' and '{' (D)
 # WARNING: Code doesn't seem to use this feature - delete from the config?
@@ -1570,27 +1570,27 @@ nl_between_annotation                    = ignore   # ignore/add/remove/force
 #
 
 # Add or remove braces on single-line 'do' statement
-mod_full_brace_do                        = add      # ignore/add/remove/force
+mod_full_brace_do                        = force    # ignore/add/remove/force
 
 # Add or remove braces on single-line 'for' statement
 # NOTE: is 3 worse than ignore
-mod_full_brace_for                       = remove   # ignore/add/remove/force
+mod_full_brace_for                       = force    # ignore/add/remove/force
 
 # Add or remove braces on single-line function definitions. (Pawn)
 mod_full_brace_function                  = ignore   # ignore/add/remove/force #ignore
 
 # Add or remove braces on single-line 'if' statement. Will not remove the braces if they contain an 'else'.
-mod_full_brace_if                        = add      # ignore/add/remove/force
+mod_full_brace_if                        = force    # ignore/add/remove/force
 
 # Make all if/elseif/else statements in a chain be braced or not. Overrides mod_full_brace_if.
 # If any must be braced, they are all braced.  If all can be unbraced, then the braces are removed.
-mod_full_brace_if_chain                  = true     # false/true #force
+mod_full_brace_if_chain                  = false    # false/true #force
 
 # Don't remove braces around statements that span N newlines
 mod_full_brace_nl                        = 2        # number #force
 
 # Add or remove braces on single-line 'while' statement
-mod_full_brace_while                     = remove   # ignore/add/remove/force
+mod_full_brace_while                     = force    # ignore/add/remove/force
 
 # Add or remove braces on single-line 'using ()' statement
 # WARNING: Code doesn't seem to use this feature - delete from the config?
@@ -1608,7 +1608,7 @@ mod_pawn_semicolon                       = false    # false/true
 mod_full_paren_if_bool                   = false    # false/true
 
 # Whether to remove superfluous semicolons
-mod_remove_extra_semicolon               = false    # false/true
+mod_remove_extra_semicolon               = true     # false/true
 
 # If a function body exceeds the specified number of newlines and doesn't have a comment after
 # the close brace, a comment will be added.